Skip to main content

REST API: A friendly introduction

Have you ever wondered how different applications or devices can communicate with each other over the internet? How does your browser know what to display when you visit a website? How does your mobile app fetch data from a server?

The answer is: they use APIs.

An API, or application programming interface, is a set of rules that define how applications or devices can connect to and communicate with each other. An API acts as a bridge between the client (the application or device that requests data) and the server (the application or device that provides data).

There are different types of APIs, such as SOAP, XML-RPC, GraphQL, etc. But one of the most common and popular is REST API.

A REST API is an API that conforms to the design principles of the REST, or representational state transfer architectural style. REST was first defined in 2000 by computer scientist Dr. Roy Fielding in his doctoral dissertation.

REST provides a relatively high level of flexibility and freedom for developers. It can be developed using virtually any programming language and support a variety of data formats. It also enables scalability, performance, and reliability for web services.

The key principles of a REST API include: #

  1. Resource identification: Each resource should have a unique identifier, such as a URL.
  2. Resource manipulation: Clients should be able to manipulate resources through a limited set of methods, such as GET, POST, PUT, and DELETE.
  3. Stateless: The server should not store any client context between requests. Each request should be self-contained and include all the information needed to process the request.
  4. Representations: Resources can have multiple representations, such as XML, JSON, or HTML.
  5. Hypermedia: The server should provide links to related resources to enable clients to discover and navigate the API.

What are requests and responses? #

Requests and responses are the messages exchanged between the client, and the server using HTTP (hypertext transfer protocol). HTTP is a standard protocol that defines how messages are formatted and transmitted over the web.

A request is a message sent by the client to the server asking for some data or action. A request consists of:

Basic request:

GET / HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
Accept: text/html

Basic response:

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Mon, 27 Feb 2021 17:48:38 GMT

<html>
<head>
<title>Home Page</title>
</head>
<body>
<h1>Welcome to Example.com</h1>
<p>This is the home page of Example.com</p>
</body>
</html>

HTTP Headers #

HTTP headers are additional information that are sent with the request or response. They can provide information about the client, the server, the resource, the body, or other aspects of the message. Headers consist of a case-insensitive name followed by a colon and a value.

For example, these are some common headers:

HTTP headers can be divided into several categories, such as general headers, request headers, response headers, entity headers, etc.

Limitations of HTTP #

HTTP has some limitations, such as:

HTTP methods and REST API #

Now, when we know how HTTP request is built, we can dive into REST API implementation, with resources identified using URLs, and the HTTP methods used to manipulate those resources. In real-life app, a REST API for managing products might have the following endpoints:

The API would return data in a standardized format, such as JSON or XML, and the client application would use the HTTP methods to manipulate the resources as needed.

GET, POST, PUT, and DELETE client implementation in JavaScript #

In JavaScript, you can use the fetch() API to make HTTP requests to a RESTful API. Here are examples of how to implement GET, PUT, and DELETE requests using fetch().

GET request:

fetch('https://example.com/products')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));

This code fetches a list of products from the server and logs the data to the console. The response is parsed as JSON using the json() method, which returns a promise.

POST request:

const newProduct = { name: 'New Product', price: 9.49 };

fetch(`https://example.com/products`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(newProduct)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));

PUT request:

const productId = 123;
const newProduct = { name: 'New Product', price: 9.49 };

fetch(`https://example.com/products/${productId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(newProduct)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));

And DELETE:

const productId = 123;

fetch(`https://example.com/products/${productId}`, {
method: 'DELETE'
})
.then(response => console.log('Product deleted successfully.'))
.catch(error => console.error(error));

GET, POST, PUT, and DELETE server implementation in PHP #

I must say, that following examples are just representation of what's going on when backend receives request and might not work if you try to run it.

if ($_SERVER['REQUEST_METHOD'] === 'GET') {
// Handle GET request
$product_list = getProducts();
// ...

// Return a response
http_response_code(200);
echo json_encode($product_list);
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Handle POST request
$input = file_get_contents('php://input');
parse_str($input, $post_params);
// Call method which adds product to the database

// Return a response
http_response_code(200);
echo json_encode(['message' => 'Product added']);
} elseif ($_SERVER['REQUEST_METHOD'] === 'PUT') {
// Handle PUT request
$input = file_get_contents('php://input');
parse_str($input, $put_params);

// Do something with the PUT data
$id = $put_params['id'];
$name = $put_params['name'];
// ...

// Return a response
http_response_code(200);
echo json_encode(['message' => 'Product updated']);
} elseif ($_SERVER['REQUEST_METHOD'] === 'DELETE') {
// Handle DELETE request
$id = $_REQUEST['id'];

// Do something with the DELETE data
// ...

// Return a response
http_response_code(204);
}

In this example, we first check the value of $_SERVER['REQUEST_METHOD'] to determine the HTTP method of the request. For POST and PUT requests, we read the raw input data from the request body using file_get_contents('php://input'), then parse the input data into an associative array using parse_str(). We can then access the PUT, POST data in the $put_params variable or $post_params variable respectively.

For a DELETE request, we simply read the id parameter from the $_REQUEST superglobal variable.

After processing the request data, we can return a response using http_response_code() to set the HTTP status code and echo to output a response body. In the GET, POST, and PUT example, we return a JSON-encoded message indicating that some action has been done to the resource with a 200 OK status code. In the DELETE example, we return a 204 No Content status code with no response body.