Post

REST API

[toc]


REST API REpresentational State Transfer


basic

REST, Representational State Transfer

  • presented by Roy Fielding in 2000
  • an architectural style for distributed hypermedia systems, designing standards between computers, making it easier for systems to communicate with each other.
  • a set of rules developers follow when they create APIs
  • a set of useful conventions for structuring a web API.
    • A system is called RESTful when it adheres to these constraints.
    • Like any other architectural style, REST have 6 guiding constraints which must be satisfied if an interface needs to be referred as RESTful.
  • interact with “web API” over HTTP, making requests to specific URLs, and getting relevant data back in the response.

REST is a programming pattern which describes how data should be transfer between client and server over the network.

  • REST specifies a set of design constraints that leads to higher performance and better maintainability.
  • These constraints are: client-server, stateless, cacheable, layer system, uniform interface and code-on-demand.

If your web services conform to the REST constraints, and can be used in standalone (i.e., does not need an UI), then you have a RESTful Web Service API (RESTful API). RESTful API works like a regular API, but delivers through a web server.

RESTful API is typically accessible through a URI.

  • The most common scheme is to use the various HTTP request method to perform CRUD (Create-Read-Update-Delete) database operations.

REST

  1. Client–server
    • separating the user interface concerns from the data storage concerns
    • 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
    • Each request 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 4 interface constraints:
      • identification of resources;
      • manipulation of resources through representations;
      • self-descriptive messages;
      • 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.

client:

A client can refer to either a developer or software application which uses the API. When you are implementing the Google Maps API in your application, you are accessing resources via the API, which makes you a client. Similarly, a web browser can also be a client.

Resource:

A resource describes an object, data, or piece of information that you may need to store or send to other services. For example, the location coordinates you receive when you work with Google Maps API are a resource.


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.

resource identifier

  • identify the particular resource involved in an interaction between components.

resource representation

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

media type

  • The data format of a representation
  • 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

  • to perform the desired transition.
  • A large number of people wrongly relate resource methods to HTTP GET/PUT/POST/DELETE methods.
  • In REST, you use these to indicate different actions.
  • GET: The GET method is only used to retrieve information from the given server. Requests using this method should only recover data and should have no other effect on the data.
  • POST: to send data back to the server using HTML forms.
  • PUT: eplaces all the current representations of the target resource with the uploaded content.
  • DELETE: removes all the current representations of the target resource given by URI.

When we are working with RESTful APIs,

  • a client will send an HTTP request,
  • and the server will respond with the HTTP response

When an HTTP request is sent to the server, it usually contains the following:

  • A header
    • HTTP verb + URI + HTTP version
    • GET /home.html HTTP/1.1
  • A blank line that separates the header with the body
  • An optional body

When an HTTP response is sent back to the client, it usually contains the following:

  • A header
    • HTTP version, status code, and reason phrase
  • A blank line that separates the header from the body
  • An optional body

design a REST API

designing REST Services

  1. Identify Object Model
  2. Create Model URIs
  3. Determine Representations
  4. Assign HTTP Methods
  5. More Actions

Identify Object Model

  • identifying the objects which will be presented as resources.
  • For network-based application, 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.

  1. Resource URIs are all nouns.
  2. URIs are usually in two forms
    • singular resource.
    • collection of resources
      • Collection may be in 2 forms
      • primary collection and secondary collection.
      • Secondary collection is sub-collection from a primary collection only.
  3. Each resource/collection contain at least one link i.e. to itself.
  4. Collections contain only most important information about resources.
  5. To get complete information about a resource, you need to access through its specific resource URI only.
  6. 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.
  7. We have not talked about operations on these resources yet.

Create Model URIs

  • designing the resource URIs –
  • focus on the relationship between resources and its sub-resources.
  • These resource URIs are endpoints for RESTful services.
  • URIs should all be nouns only.

example:

1
2
3
4
5
6
7
8
9
10
11
# a device is a top-level resource.
# And configuration is sub-resource under the device.

/devices
/devices/{id}

/configurations
/configurations/{id}

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

Determine Representations

  • Mostly representations are defined in either XML or JSON format.

Collection of Device Resource

  • When returning a collection resource, include only the most important information about resources.
  • This will keep the size of payload small
  • improve the performance of REST APIs.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<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.
  • also include a list of links for sub-resources and other supported operations.
  • This will make your REST API HATEOAS driven.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<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.
1
2
3
4
5
6
7
8
9
10
11
12
13
<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.

1
2
3
4
5
6
<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 the 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 the same presentation fields as the primary collection.
1
2
3
4
5
6
7
8
9
10
11
12
13
<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 essential as you can provide access to a device- specific configuration in a more unique manner, and you will have the ability to mask some fields (if design requires 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 the primary collection, OR you may mask few fields.

  • This subresource representation will also have an additional link to its primary presentation.
1
2
3
4
5
6
7
<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>

Assign HTTP Methods

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

GET

GET is generally used to get information about some object or record that already exists.

  • the GET does not modify anything, or at least isn’t supposed to.
  • For example
    • to-do list web service.
    • You might do an HTTP GET to the URL /tasks/ to get a list of current tasks to be done.
    • So it may return something like this:
1
2
3
4
5
[
  { "id": 3643, "summary": "Wash car" },
  { "id": 3697, "summary": "Visit gym" }
]
// a list of JSON objects. (A “JSON object” is a data type very similar to a Python dictionary.)

For web browser GETs a web page, the HTML sent back is the response body.

For an API, the response body can be empty or not. It depends on the API and the end point.

1
2
3
4
5
6
7
8
9
10
11
12
// POST to /tasks/ to add something to our to-do list,
// may get back an automatically assigned task ID. This can again be in the form of a JSON object:
{ "id": 3792 }


// GET /tasks/ again, our list of tasks will include this new one:

[
  { "id": 3643, "summary": "Wash car" },
  { "id": 3697, "summary": "Visit gym" },
  { "id": 3792, "summary": "Get milk" }
]

Browse all devices or configurations [Primary Collection]

1
2
3
4
5
6
7
8
HTTP GET /devices
HTTP GET /configurations

# If the collection size is large
# apply paging and filtering as well.
# e.g., Below requests will fetch the first 20 records from collection.
HTTP GET /devices?startIndex=0&size=20
HTTP GET /configurations?startIndex=0&size=20

Browse all devices or configurations [Secondary Collection]

1
2
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.
1
2
HTTP GET /devices/{id}
HTTP GET /configurations/{id}

Browse single device or configuration [Secondary Collection]

1
2
HTTP GET /devices/{id}/configurations/{id}
Subresource representation will be either same as or a subset of primary presentation.

POST

In contrast, POST is typically used when you want to create something.

  • So to add a new item to the todo list, you might trigger an HTTP POST to /tasks/.

  • When do a POST, normally will include a body in the request.
  • That means you send along some sequence of bytes—some data defining the object or record you are creating.
  • What kind of data? These days, it’s very common to pass JSON objects.
1
2
3
4
5
6
7
// The API may state that a `POST` to `/tasks/` must include a single object with two fields, “summary” and “description”, like this:
{
  "summary": "Get milk",
  "description": "Need to get a half gallon of organic 2% milk."
}
// This is a string, encoding a JSON object.
// The API server then parses it and creates the equivalent Python dictionary.

Create a device or configuration

Create is not idempotent operation

  • in HTTP protocol – POST is also not idempotent. So use POST.
1
2
HTTP POST /devices
HTTP POST /configurations

Please note that request payload will not contain any id attribute, as the server is responsible for deciding it.

  • The response to create request will look like this:
1
2
3
4
5
6
7
8
9
10
11
HTTP/1.1 201 Created
Content-Type: application/xml
Location: https://example.com/network-app/configurations/678678

<configuration id="678678">
    <link rel="self" href="/configurations/678678" />
    <content><![CDATA[...]]></content>
    <status>active</status>
    <link  rel="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.

1
2
HTTP PUT /devices/{id}
HTTP PUT /configurations/{id}

PUT response may look like this.

1
2
3
4
5
6
7
8
9
HTTP/1.1 200 OK
Content-Type: application/xml

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

Remove a device or configuration

1
2
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 the case of async operation, the application shall return a task id that 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 the system. Usually, 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 a real application, you will need to apply the configuration on the device – OR you may want to remove the configuration from the device (not from the primary collection). You shall use PUT and DELETE methods in this case, because of its idempotent nature.

1
2
3
4
5
# //Apply Configuration on a device
HTTP PUT /devices/{id}/configurations

# //Remove Configuration on a device
HTTP DELETE /devices/{id}/configurations/{id}

References:

.

This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.