# RESTful API

## RESTful API

The following is from: <https://restfulapi.net/>

## What is REST

REST is acronym for**RE**presentational**S**tate**T**ransfer. It is architectural style for**distributed hypermedia systems**and was first presented by Roy Fielding in 2000 in his famous[dissertation](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm).

Like any other architectural style, REST also does have it’s own[6 guiding constraints](https://restfulapi.net/rest-architectural-constraints/)which must be satisfied if an interface needs to be referred as**RESTful**. These principles are listed below.

### Guiding Principles of REST

1. **Client–server**

   – By separating the user interface concerns from the data storage concerns, we improve the portability of the user interface across multiple platforms and improve scalability by simplifying the server components.
2. **Stateless**

   – Each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client.
3. **Cacheable**

   – Cache constraints require that the data within a response to a request be implicitly or explicitly labeled as cacheable or non-cacheable. If a response is cacheable, then a client cache is given the right to reuse that response data for later, equivalent requests.
4. **Uniform interface**

   – By applying the software engineering principle of generality to the component interface, the overall system architecture is simplified and the visibility of interactions is improved. In order to obtain a uniform interface, multiple architectural constraints are needed to guide the behavior of components. REST is defined by four interface constraints: identification of resources; manipulation of resources through representations; self-descriptive messages; and, hypermedia as the engine of application state.
5. **Layered system**

   – The layered system style allows an architecture to be composed of hierarchical layers by constraining component behavior such that each component cannot “see” beyond the immediate layer with which they are interacting.
6. **Code on demand (optional)**

   – REST allows client functionality to be extended by downloading and executing code in the form of applets or scripts. This simplifies clients by reducing the number of features required to be pre-implemented.

### Resource

The key abstraction of information in REST is a **resource**. Any information that can be named can be a resource: a document or image, a temporal service, a collection of other resources, a non-virtual object (e.g. a person), and so on. REST uses a **resource identifier** to identify the particular resource involved in an interaction between components.

The state of resource at any particular timestamp is known as **resource representation**. A representation consists of data, metadata describing the data and **hypermedia** links which can help the clients in transition to next desired state.

The data format of a representation is known as a[**media type**](https://www.iana.org/assignments/media-types/media-types.xhtml). The media type identifies a specification that defines how a representation is to be processed.**A truly RESTful API looks like*****hypertext***. Every addressable unit of information carries an address, either explicitly (e.g., link and id attributes) or implicitly (e.g., derived from the media type definition and representation structure).

### Resource Methods

Other important thing associated with REST is **resource methods** to be used to perform the desired transition. A large number of people wrongly relate resource methods to HTTP **GET/PUT/POST/DELETE** methods.

### REST and HTTP are not same !!

A lot of people prefer to compare HTTP with REST.**REST and HTTP are not same.**

## How to design a REST API

Learning REST in pieces is one thing, while applying all those learned concepts into real application design is completely another challenge. In this tutorial, we will learn to design REST APIs for a network based application. Please note that the takeaway from this whole exercise is the learning of how to apply REST principles in design process.

**Steps in designing REST Services**

> **Identify Object Model**\
> **Create Model URIs**\
> **Determine Representations**\
> **Assign HTTP Methods**\
> **More Actions**

### Identify Object Model

The very first step in designing a REST API based application is – identifying the objects which will be presented as resources.

**Example**

> For a network based application, object modeling is pretty much simpler. There can be many things such as devices, managed entities, routers, modems etc. For simplicity sake, we will consider only two resources i.e.
>
> * Devices
> * Configurations
>
>   Here configuration is sub-resource of a device. A device can have many configuration options.
>
> Note that both objects/resources in our above model will have a unique identifier, which is the integer id property.

### Create Model URIs

Now when object model is ready, it’s time to decide the resource URIs. At this step, while designing the resource URIs – focus on the relationship between resources and its sub-resources. **These resource URIs are endpoints for RESTful services**.

**Example**

In our application, a device is a top-level resource. And configuration is sub-resource under device. Let’s write down the URIs.

```
/devices
/devices/{id}

/configurations
/configurations/{id}

/devices/{id}/configurations
/devices/{id}/configurations/{id}
```

Notice that these URIs do not use any verb or operation. **It’s very important to not include any verb in URIs**. **URIs should all be nouns only**.

### Determine Representations

Now when resource URIs have been decided, let’s work on their representations. Mostly representations are defined in either XML or JSON format. We will see XML examples as its more expressive on how data is composed.

#### Collection of Device Resource

When returning a collection resource, include only most important information about resource. This will keep the size of payload small, and so will improve the **performance of REST APIs**.

```markup
<devices size="2">

    <link rel="self" href="/devices"/>

    <device id="12345">
        <link rel="self" href="/devices/12345"/>
        <deviceFamily>apple-es</deviceFamily>
        <OSVersion>10.3R2.11</OSVersion>
        <platform>SRX100B</platform>
        <serialNumber>32423457</serialNumber>
        <connectionStatus>up</connectionStatus>
        <ipAddr>192.168.21.9</ipAddr>
        <name>apple-srx_200</name>
        <status>active</status>
    </device>

    <device id="556677">
        <link rel="self" href="/devices/556677"/>
        <deviceFamily>apple-es</deviceFamily>
        <OSVersion>10.3R2.11</OSVersion>
        <platform>SRX100B</platform>
        <serialNumber>6453534</serialNumber>
        <connectionStatus>up</connectionStatus>
        <ipAddr>192.168.20.23</ipAddr>
        <name>apple-srx_200</name>
        <status>active</status>
    </device>

</devices>
```

#### Single Device Resource

Opposite to collection URI, here include complete information of a device in this URI. Here, also include a list of links for sub-resources and other supported operations. This will make your REST API [HATEOAS](https://restfulapi.net/hateoas/) driven.

```markup
<device id="12345">
    <link rel="self" href="/devices/12345"/>

    <id>12345</id>
    <deviceFamily>apple-es</deviceFamily>
    <OSVersion>10.0R2.10</OSVersion>
    <platform>SRX100-LM</platform>
    <serialNumber>32423457</serialNumber>
    <name>apple-srx_100_lehar</name>
    <hostName>apple-srx_100_lehar</hostName>
    <ipAddr>192.168.21.9</ipAddr>
    <status>active</status>

    <configurations size="2">
        <link rel="self" href="/configurations" />

        <configuration id="42342">
            <link rel="self" href="/configurations/42342" />
        </configuration>

        <configuration id="675675">
            <link rel="self" href="/configurations/675675" />
        </configuration>
    </configurations>

    <method href="/devices/12345/exec-rpc" rel="rpc"/>
    <method href="/devices/12345/synch-config"rel="synch device configuration"/>
</device>
```

#### Configuration Resource Collection

Similar to device collection representation, create configuration collection representation with only minimal information.

```
<configurations size="20">
    <link rel="self" href="/configurations" />

    <configuration id="42342">
        <link rel="self" href="/configurations/42342" />
    </configuration>

    <configuration id="675675">
        <link rel="self" href="/configurations/675675" />
    </configuration>
    ...
    ...
</configurations>
```

Please note that`configurations`collection representation inside`device`is similar to top-level`configurations`URI. Only difference is that`configurations`for a device are only two, so only two configuration items are listed as subresource under device.

#### Single Configuration Resource

Now, single configuration resource representation must have all possible information about this resource – including relevant links.

```
<configuration id="42342">
    <link rel="self" href="/configurations/42342" />
    <content><![CDATA[...]]></content>
    <status>active</status>
    <link  rel="raw configuration content" href="/configurations/42342/raw" />
</configuration>
```

#### Configuration Resource Collection Under Single Device

This resource collection of configurations will be a subset of primary collection of configurations, and will be specific a device only. As it is the subset of primary collection,**DO NOT create a different representation data fields**than primary collection. Use same presentation fields as primary collection.

```
<configurations size="2">
    <link rel="self" href="/devices/12345/configurations" />

    <configuration id="53324">
        <link rel="self" href="/devices/12345/configurations/53324" />
        <link rel="detail" href="/configurations/53324" />
    </configuration>

    <configuration id="333443">
        <link rel="self" href="/devices/12345/configurations/333443" />
        <link rel="detail" href="/configurations/333443" />
    </configuration>
</configurations>
```

Notice that this subresource collection has two links. One for its direct representation inside sub-collection i.e.`/devices/12345/configurations/333443`and other pointing to its location in **primary collection** i.e.`/configurations/333443`.

Having two links is important as you can provide access to a device specific configuration in more unique manner, and you will have ability to mask some fields (if design require it) which shall not be visible in a **secondary collection**.

#### Single Configuration Resource Under Single Device

This representation should have either exactly similar representation as of Configuration representation from primary collection; OR you may mask few fields.

This subresource representation will also have an additional link to its primary presentation.

```
<configuration id="11223344">
    <link rel="self" href="/devices/12345/configurations/11223344" />
    <link rel="detail" href="/configurations/11223344" />
    <content><![CDATA[...]]></content>
    <status>active</status>
    <link rel="raw configuration content" href="/configurations/11223344/raw" />
</configuration>
```

Now, before moving forward to next section, let’s note down few observations so you don’t miss them.

* Resource URIs are all nouns.
* URIs are usually in two forms – collection of resources and singular resource.
* Collection may be in two forms primary collection and secondary collection. Secondary collection is sub-collection from a primary collection only.
* Each resource/collection contain at least one link i.e. to itself.
* Collections contain only most important information about resources.
* To get complete information about a resource, you need to access through its specific resource URI only.
* Representations can have extra links (i.e. methods in single device). Here

  `method`

  represent a POST method. You can have more attributes or form links in altogether new way also.
* We have not talked about operations on these resources yet.

### Assign HTTP Methods

So our resource URIs and their representation are fixed now. Let’s decide the possible operations in application and map these operations on resource URIs. A user of network application can perform browse, create, update or delete operations. So let’s map them.

#### Browse all devices or configurations \[Primary Collection]

| `HTTP GET /devicesHTTP GET /configurations` |
| ------------------------------------------- |

If the collection size is large, you can apply paging and filtering as well. e.g. Below requests will fetch first 20 records from collection.

| `HTTP GET /devices?startIndex=0&size=20HTTP GET /configurations?startIndex=0&size=20` |
| ------------------------------------------------------------------------------------- |

#### Browse all devices or configurations \[Secondary Collection]

| `HTTP GET /devices/{id}/configurations` |
| --------------------------------------- |

It will be mostly a small size collection – so no need to enable filtering or soring here.

#### Browse single device or configuration \[Primary Collection]

To get the complete detail of a device or configuration, use`GET`operation on singular resource URIs.

| `HTTP GET /devices/{id}HTTP GET /configurations/{id}` |
| ----------------------------------------------------- |

#### Browse single device or configuration \[Secondary Collection]

| `HTTP GET /devices/{id}/configurations/{id}` |
| -------------------------------------------- |

Subresource representation will be either same as or subset of primary presentation.

#### Create a device or configuration

Create is not[idempotent](https://restfulapi.net/idempotent-rest-apis/)operation, and in HTTP protocol –`POST`is also not idempotent. So use POST.

| `HTTP POST /devicesHTTP POST /configurations` |
| --------------------------------------------- |

Please note that request payload will not contain any`id`attribute, as server is responsible for deciding it. Response of create request will look like this:

| `HTTP/1.1 201 CreatedContent-Type: application/xmlLocation:`[`http://example.com/network-app/configurations/678678`](http://example.com/network-app/configurations/678678)`<configurationid="678678"><linkrel="self"href="/configurations/678678"/><content><![CDATA[...]]></content><status>active</status><linkrel="raw configuration content"href="/configurations/678678/raw"/></configuration>` |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

#### Update a device or configuration

Update operation is an idempotent operation and HTTP`PUT`is also is idempotent method. So we can use PUT method for update operations.

| `HTTP PUT /devices/{id}HTTP PUT /configurations/{id}` |
| ----------------------------------------------------- |

PUT response may look like this.

| `HTTP/1.1 200 OKContent-Type: application/xml<configurationid="678678"><linkrel="self"href="/configurations/678678"/><content><![CDATA[. updated content here .]]></content><status>active</status><linkrel="raw configuration content"href="/configurations/678678/raw"/></configuration>` |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

#### Remove a device or configuration

Removing is always a`DELETE`operation.

| `HTTP DELETE /devices/{id}HTTP DELETE /configurations/{id}` |
| ----------------------------------------------------------- |

A successful response SHOULD be`202 (Accepted)`if resource has been queues for deletion (async operation), or`200 (OK)`/`204 (No Content)`if resource has been deleted permanently (sync operation).

In case of async operation, application shall return a task id which can be tracked for success/failure status.

*Please note that you should put enough analysis in deciding the behavior when a subresource is deleted from system. Normally, you may want to **SOFT DELETE** a resource in these requests – in other words, set their status INACTIVE. By following this approach, you will not need to find and remove its references from other places as well.*

#### Applying or Removing a configuration from a device

In real application, you will need to apply the configuration on device – OR you may want to remove the configuration from device (not from primary collection). You shall use PUT and DELETE methods in this case, because of its **idempotent** nature.

| `//Apply Configuration on a deviceHTTP PUT /devices/{id}/configurations      //Remove Configuration on a device HTTP DELETE /devices/{id}/configurations/{id}` |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------- |

### More Actions

So far we have designed only object model, URIs and then decided HTTP methods or operations on them. You need to work on other aspects of the application as well:

1\) Logging\
2\) [Security](https://restfulapi.net/security-essentials/)\
3\) Discovery etc.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://aaronice.gitbook.io/system-design/distributed-systems/restful-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
