Unraveling RESTful Services

Unraveling RESTful Services

By M. Vaqqas

Introduction to RESTful Services using HTTP 1.1. Originally published in Dr. Dobbs with the title "RESTful Services a Tutorial". Re-posting here with the original title. (Feel free to copy the article in full or in parts as long as you provide the link to this article)

You may want to check out the first article in the series: https://www.dhirubhai.net/pulse/restful-architecture-mohammad-vaqqas/


More than a decade after its introduction, REST is becoming one of the most important technologies for Web applications. Its importance is likely to continue growing quickly as all technologies move towards an API orientation. Every major development language now includes frameworks for building RESTful web services. As such, it is important for web developers and architects to have a clear understanding of the REST and RESTful services. This tutorial explains REST architecturally and then dives into the details of using it for common API-based tasks.

While REST stands for Representational State Transfer, which is an architectural style for networked hypermedia applications, it is primarily used to build web services that are lightweight, maintainable, and scalable. A service based on REST is called RESTful service. REST is not dependent on any protocol but almost every RESTful service uses HTTP as its underlying protocol. In this article, I examine the creation of RESTful services with HTTP.

Features of a RESTful Service

Every system uses resources. These resources can be pictures, video files, web pages, business information, or anything that can be represented in a computer-based system. The purpose of a service is to provide a window to its clients so that they can access these resources. Service architects and developers want this service to be easy to implement, maintainable, extensible, and scalable. A RESTful design promises that and more. In general, RESTful service should have the following properties and features, which I’ll describe in more detail:

  • Representations
  • Messages
  • URIs
  • Uniform interface
  • Stateless
  • Links between resources
  • Caching

Representations

The focus of a RESTful service is on resources and how to provide access to these resources. A resource can easily be thought of as an object as in OOP. A resource can consist of other resources. While designing a system, the first thing we do is to identify the resources and determine how they are related to each other. This is similar to the first step of designing a database.? We identify entities and relations.?

Once we have identified our resources the next thing we need is to find a way to represent these resources in our system. You can use any format for representing the resources, as REST does not put a restriction on the format of a representation.?

For example, depending on your requirements, you can decide to use JSON or XML. If you are building web services that will be used by web pages for AJAX calls then JSON is a good choice. XML can be used to represent more complex resources. For example, a resource called “Person” can be represented as:

JSON Representation of a resource


XML Representation of a resource

In fact, you can use more than one format and decide which one to use for a response depending on the type of client or some request parameters. Whichever format you use, a good representation should have some obvious qualities:

  • Both client and server should be able to comprehend this format of representation.?
  • A representation should be able to completely represent a resource. If there is a need to partially represent a resource, then you should think about breaking this resource into child resources. Dividing big resources into smaller ones also allows you to transfer a smaller representation. Smaller representations mean less time required to create and transfer them, which means faster services.
  • The representation should be capable of linking resources to each other. This can be done by placing a URI or unique ID of the related resource in a representation. I? will discuss more about this in the coming sections.

Messages

The client and service talk to each other via messages. Clients send a request to the server, and the server replies with a response. Apart from the actual data, these messages also contain some metadata about the message. It is important to have some background about the HTTP 1.1 request and response formats for designing RESTful web services.

HTTP Request

An HTTP Request has the following format:

An HTTP Request

<VERB> is one of the HTTP methods like GET, PUT, POST, DELETE, OPTIONS, etc

<URI> is the URI of the resource on which the operation is going to be performed

<HTTP Version> is the version of HTTP, generally “HTTP v1.1”

<Request Header> contains the metadata as a collection of key-value pairs of headers and their values. These settings contain information about the message and its sender like client type, the formats the client supports, the format type of the message body, cache settings for the response, and a lot more information.?

<Request Body> is the actual message content. In a RESTful service that’s where the representations of resources sit in a message.

There are no tags or markups to mark the beginning or end of a section in an HTML message.?

Here is a sample POST request message, which is supposed to insert a new resource ‘Person’?

Listing 3: A Sample POST Request

A Sample POST Request

We can see the POST command which is followed by the URI and the HTTP version. This request also contains some request headers. The Host header is the address of the server. Content-Type tells about the type of content in the message body. Content-Length is the length of the data in the message body. Content length can be used to verify that the entire message body has been received. Notice there are no start or end tags in this message.

Here is an actual GET request that was created by my browser when I tried to visit the HTTP 1.1 specifications on w3.org:

An Actual GET Request

There is no message body in this request. The Accept header tells the server about the various presentation formats this client supports. A server, if it supports more than one representation format, can decide the representation format for a response on runtime depending on the value of the Accept header. User-Agent contains information about the type of client who made this request. Accept-Encoding/Language tells about the encoding and language this client supports.?

HTTP Response

Format of an HTTP Response

Format of an HTTP Response

The server returns <response code>, which contains the status of the request. This response code is generally the 3-digit HTTP status code. [? https://en.wikipedia.org/wiki/List_of_HTTP_status_codes ]?

<Response Header> contains the metadata and settings about the response message.

<Response Body> contains the representation if the request was successful.

Here is the actual response I received for the request cited above in Listing 3:

An Actual Response to a GET Request

The response code “200 OK” means that everything went well and the response message body contains a valid representation of the resource I requested. In this case, the representation is an HTML document that is declared by the Content-Type header in the response header. The headers in the message are quite self-explanatory. We will discuss some of these headers later in this article. There are so many other such attributes. If you wish to explore them all you can visit “https://www.w3.org/Protocols/rfc2616/rfc2616.html HTTP/1.1”.

You can catch and inspect such HTTP requests and responses using a free tool called Fiddler? [ https://www.telerik.com/download/fiddler” ]

Addressing Resources

REST requires each resource to have at least one URI. A RESTful service uses a directory hierarchy like human readable URIs to address its resources. The job of a URI is to identify a resource or a collection of resources. The actual operation is determined by an HTTP verb. The URI should not say anything about the operation or action. This enables us to call the same URI with different HTTP verbs to perform different operations.?

Suppose we have a database of persons and we wish to expose it to the outer world through a service. A resource ‘person’ can be addressed like this

https://MyService/Persons/1

The above URL has the following format: Protocol://ServiceName/ResourceType/ResourceID

Some important recommendations for well-structured URIs:

  • Use plural nouns for naming your resources.?
  • Avoid using spaces as they create confusion. Use _ (Underscore) or – (Hyphen) instead.?
  • A URI is case insensitive. I use camel case in my URIs for better clarity. You can use all lowercase URIs.?
  • You can have your own conventions but stay consistent throughout the service. Make sure your clients are aware of this convention. It becomes easier for your clients to construct the URIs programmatically if they are aware of the resource hierarchy and the URI convention you follow.
  • A cool URI never changes; so give it a good thought before deciding the URIs for your service. Just in case you need to change the location of a resource do not discard the old URI. If a request comes for the old URI use status code 300 and redirect the client to the new location.
  • Avoid verbs for your resource names until your resource is actually an operation or a process. Verbs are more suitable for the names of operations instead of resources. For example, a RESTful service should not have these URIs: https://MyService/FetcthPerson/1 Or https://MyService/DeletePerson?id=1

Query Parameters in URI

The preceding URI is constructed with the help of a query parameter:

https://MyService/Persons?id=1

The query parameter approach will work just fine. REST does not stop you from using query parameters. However, this approach has a few disadvantages.?

  • Increased complexity and reduced readability which will increase if you have more parameters
  • Search engine crawlers and indexers like Google ignore URIs with query parameters. If you are developing for the Web this would be a great disadvantage as a portion of your web service will be hidden from the search engines.?

The basic purpose of query parameters is to provide parameters to an operation that needs the data items. For example, if you wish the format of the presentation to be decided by the client. You can achieve that through a parameter like this:

https://MyService/Persons/1?format=xml&encoding=UTF8 or https://MyService/Persons/1?format=json&encoding=UTF8 Including the parameters ‘format’ and ‘encoding’ here in the main URI in a parent-child hierarchy will not be logically correct as they have no such relation:

https://MyService/Persons/1/json/UTF8

Query parameters also allow optional parameters. This is not possible otherwise in a URI. Use query parameters only for the use they are intended for providing parameter values to a process.?

Uniform Interface

A RESTful system should have a uniform interface. HTTP 1.1 provides a set of methods, called verbs. Among these, the most important are:

HTTP Methods

A Safe operation is an operation that does not have any effect on the original value of the resource. For example, the mathematical operation divide by 1 is a safe operation as no matter how many times you divide a number by 1 the original value will not change. An Idempotent operation is an operation that gives the same result no matter how many times you perform it. For example mathematical operation multiplied by zero is idempotent as no matter how many times you multiply a number by zero the result is always the same. Similarly, a Safe HTTP method does not make any changes to the resource on the server. An Idempotent HTTP method has the same effect no matter how many times it is performed. Classifying methods as Safe and Idempotent makes it easy to predict the results in the unreliable environment of the web where the client may fire the same request again.

GET is probably the most popular method on the web. It is used to fetch a resource. HEAD returns only the response headers with an empty body. This method can be used in a scenario when you do not need the entire representation of the resource. For example, HEAD can be used to quickly check whether a resource exists on the server or not.

The method OPTIONS is used to get a list of allowed operations on the resource. For example consider the request:

OPTIONS https://MyService/Persons/1 HTTP/1.1

HOST: MyService

The service after authorizing and authenticating the request can return something like

200 OK Allow: HEAD, GET, PUT

The second line contains the list of operations that are allowed for this client.

You should use these methods only for the purpose they are intended for. For instance, never use GET to create or delete a resource on the server. If you do so this will confuse your clients and they might end up doing operations they did not intend to.

To illustrate this let’s consider this request:?

GET https://MyService/DeletePersons/1 HTTP/1.1

HOST: MyService

By HTTP 1.1 specification a GET request is supposed to fetch resources from the server. But this is so easy to implement your service such that this request actually deletes a Person. This request will work perfectly but this is not a RESTful design. Instead, use the DELETE method to delete a resource like this:

DELETE https://MyService/Persons/1 HTTP/1.1

HOST: MyService

REST recommends a uniform interface and HTTP provides you with that uniform interface. However, it is up to the service architects and developers to keep it uniform.

Difference between PUT and POST

The short descriptions of these two methods I provided above are almost the same. These two methods confuse a lot of developers. So let’s discuss these separately.?

The key difference between PUT and POST is that PUT is idempotent while POST is not. No matter how many times you send a PUT request the results will be the same.? While POST is not an idempotent method. Making a POST multiple times may result in multiple resources getting created on the server.

Another difference is that with PUT you must always specify the complete URI of the resource. This implies that the client should be able to construct the URI of a resource even if it does not yet exist on the server. This is possible when it is the client’s job to choose a unique name or id for the resource. Creating a user on the server requires the client to choose a user ID. If the client is not able to guess the complete URI of the resource then you have no option but to use POST.

Difference Between PUT and POST

It is clear from the above table that a PUT request will not modify or create more than one resource no matter how many times it is fired (if the URI is the same). There is no difference between PUT and POST if the resource already exists, both update the existing resource. The third request (POST https://MyService/Persons/) will create a resource each time it is fired. A lot of developers think that REST does not allow POST to be used for update operations; however, REST imposes no such restrictions.

Stateless

A RESTful service is stateless and does not maintain the application state for any client. A request cannot be dependent on a past request and service treats each request independently. HTTP is a stateless protocol by design and you need to do something extra to implement a state-full service using HTTP. But this is really easy to implement state-full services with current technologies. We need a clear understanding of a stateless and state-full design so that we can avoid a state-full design.

A Stateless design:

Request1: GET https://MyService/Persons/1 HTTP/1.1 Request2: GET https://MyService/Persons/2 HTTP/1.1

Each of these requests can be treated separately.

A stateful design:

Request1: GET https://MyService/Persons/1 HTTP/1.1 Request2: GET https://MyService/NextPerson? HTTP/1.1

To process the second request, the server needs to remember the last PersonID client fetched. In other words, the server needs to remember the current state—otherwise Request2 cannot be processed. Design your service in a way that a request never refers to a previous request. Stateless services are easier to host, easy to maintain, and more scalable. Plus, such services can provide better response time to requests, as it is much easier to load and balance them.

Links between Resources

A resource representation can contain links to other resources like an HTML page contains links to other pages. The representations returned by the service should drive the process flow as in the case of a website. When you visit any website you are presented with an index page. You click one of the links and move to another page and so on. Here the representation is the HTML documents and the user is driven through the website by these HTML documents themselves. The user does not need a map before coming to a website. A service can be (and should be) designed in the same manner.?

Let’s consider the case in which a client requests one resource that contains multiple other resources. Instead of dumping all these resources, you can list all the resources and provide links to these resources. Links help keep the representations small in size.

For example, if multiple persons can be part of a Club, then a Club can be represented in MyService as:

Links to other resources

Caching

Caching is the concept of storing the generated results and using the stored results instead of generating them repeatedly if the same request arrives in near future. This can be done on the client, the server, or any other component between them, such as a proxy server. Caching is a great way of enhancing service performance, but if not managed properly can result in clients being served stale results.

Caching can be controlled using these HTTP headers:

HTTP Headers for Caching

Duration passed in seconds since this was fetched from the server. Can be inserted by an intermediary component.?

Values of these headers can be used in combination with the directives in the Cache-Control header to check if the cached results are still valid or not. The most common directives for Cache-Control header:

Cache-Control Directives

You can see some of these headers and directives above in Listing 5. Depending on the nature of the resources, a service can decide the values of these headers and directives. For example, a service providing stock market updates would keep the cache age limit to as low as possible or even turn off caching completely as this is a piece of critical information and users should get the latest results all the time. While a public pictures repository whose contents do not change so frequently would use longer caching age and slack caching rules. The server, the client, and any intermediate component between them should follow these directives sincerely else it will result in outdated information getting served.

Documenting RESTful APIs

RESTful services do not necessarily require a document to help clients discover them. Due to URIs, links, and a uniform interface, it is extremely simple to discover RESTful services at runtime. A client can simply know the base address of the service and from there, it can discover the service on its own by traversing through the resources using links. The method OPTION can be used effectively in the process of discovering a service.?

This does not mean that RESTful services require no documentation at all. There is no excuse for not documenting your service. You should document every resource and URI for the client developers. You can use any format for structuring your document but it should contain enough information about resources, URIs, Available Methods, and any other information required for accessing your service. Table X is a sample documentation of MyService. This is a simple and short document that contains all the aspects of MyService and should be sufficient for developing a client.

Service Name: MyService Address: https://MyService/


Sample API Documentation

You may also like to document the representations of each resource and provide some sample representations.?

Conclusion

REST is a great way of developing lightweight web services that are easy to implement, maintain and discover. HTTP provides an excellent interface to implement RESTful services with features like a uniform interface and caching. However, it is up to developers to implement and utilize these features correctly. If we get the basics right a RESTful service can be easily implemented using any of the existing technologies like Python, .NET, or Java. I hope this article provides enough information for you to start developing your own RESTful services.

References

  1. Chapter 5 of the original theses by Roy Fielding: https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm
  2. HTTP 1.1 Documentation: https://www.w3.org/Protocols/rfc2616/rfc2616.html
  3. RESTful Web Services Cookbook by Subbu Allamaraju: https://shop.oreilly.com/product/9780596801694.do
  4. RESTful Services by Leonard Richardson and Sam Ruby: https://shop.oreilly.com/product/9780596529260.do

要查看或添加评论,请登录

Mohammad Vaqqas的更多文章

  • My Git Cheat Sheet

    My Git Cheat Sheet

    Clone a repository (Download the code from the git server) git clone Set author name in the config of the repository…

    1 条评论
  • RESTful Architecture

    RESTful Architecture

    INTRODUCTION REST stands for Representational State Transfer which was introduced by Roy Fielding in 2000. It has been…

社区洞察

其他会员也浏览了