Home
- Home
- Blog
Author :
Global TechHub
Introduction
RESTful Web Services are basically REST
Architecture based Web Services. In REST Architecture everything is a resource.
RESTful web services are light weight, highly scalable and maintainable and are
very commonly used to create APIs for web-based applications. This article
describes the Rest API principles and best practices.
Many of the API design opinions found on the
web are academic discussions revolving around subjective interpretations of
fuzzy standards as opposed to what makes sense in the real world. My goal with
this post is to describe best practices for a pragmatic API designed for
today's web applications. I make no attempt to satisfy a standard if it doesn't
feel right.
Overview
The success of an API is determined by the
pace developers adopt and have success using an API. The rapid adoption of APIs
is based on the design. Follow these RESTful API Design Principles for
successful API adoption:
ü
Reduce complexity
ü
Keep URL intuitive and simple
ü
Errors handling
ü
Mandatory versioning
ü
It should use web standards where
they make sense
ü It should be efficient, while maintaining balance with the other
requirements
Below are the basic best practices we should
keep in mind while we are designing a Rest API.
Ø
Terminologies
Ø
API endpoint
Ø
Query Parameters
Ø
HTTP methods
Ø
HTTP Headers
Ø
HTTP Status Codes
Ø
Security
Ø
Caching
Ø Versioning
Terminologies
The following are the most important terms
related to REST APIs
v Resource is an object or representation of something, which has some associated
data with it and there can be set of methods to operate on it. E.g. customer, bank
and employees are resources and delete, add, update are the operations to be
performed on these resources.
v
Collections are set of resources, e.g Companies
is the collection of Company resource.
v URL (Uniform Resource Locator) is a path
through which a resource can be located and some actions can be performed on
it.
API
endpoint
Names and Verbs
To describe your resources, use concrete
names and not action verbs.
For decades, computer scientists used action
verbs in order to expose services in an RPC way, for instance:
ü
getOrder(O123)
ü
createOrder(order)
ü
updateOrder(order)
ü deleteOrder(O123)
By contrast, the RESTful approach is to use:
ü
GET /orders/1234
ü
POST /orders (with JSON describing a
user in the body)
ü
PUT /orders (with JSON describing a
user in the body)
ü DELETE /ordes/1234
The paths should contain the plural form of
resources and the HTTP method should define the kind of action to be performed
on the resource.
Nested Resources
Let's say product have many users associated
with them. What would this URL structure look like?
List all:
ü GET /product/123/users
URI case
When it comes to naming resources in a
program, we need to follow CamelCase.
CamelCase has been popularized by the Java
language. It intends to emphasize the beginning of each word by making the
first letter uppercase. E.g. camelCase, currentUser, etc. Aside from debates
about its readability, its main drawback is to be ineffective in contexts which
are not case sensitive.
Query
Parameters
It's best to keep the base resource URLs as
lean as possible. Complex result filters, sorting requirements and advanced
searching (when restricted to a single type of resource) can all be easily
implemented as query parameters on top of the base URL. Let's look at these in
more detail:
Filtering: Use a unique
query parameter for each field that implements filtering. For example, when
requesting a list of tickets from the /tickets endpoint, you may want to limit
these to only those in the open state. This could be accomplished with a
request like GET /tickets?state=open. Here, state is a query parameter that
implements a filter.
Sorting: Similar to filtering, a generic
parameter sort can be used to describe sorting rules. Accommodate complex
sorting requirements by letting the sort parameter take in list of comma
separated fields, each with a possible unary negative to imply descending sort
order. Let's look at some examples:
GET /tickets?sort=-priority - Retrieves a
list of tickets in descending order of priority
GET /tickets?sort=-priority,created_at -
Retrieves a list of tickets in descending order of priority. Within a specific
priority, older tickets are ordered first
Searching: Sometimes basic
filters aren't enough and you need the power of full text search. Perhaps
you're already using ElasticSearch or another Lucene based search technology.
When full text search is used as a mechanism of retrieving resource instances
for a specific type of resource, it can be exposed on the API as a query
parameter on the resource's endpoint. Let's say q. Search queries should be
passed straight to the search engine and API output should be in the same
format as a normal list result.
Combining these together, we can build
queries like:
GET /tickets?sort=-updated_at - Retrieve
recently updated tickets
GET /tickets?state=closed&sort=-updated_at - Retrieve recently closed tickets
GET /tickets?q=return&state=open&sort=-priority,created_at - Retrieve the highest priority open tickets mentioning the word 'return'
Aliases for common queries
To make the API experience more pleasant for
the average consumer, consider packaging up sets of conditions into easily
accessible RESTful paths. For example, the recently closed tickets query above
could be packaged up as
GET /tickets/recently_closed
Limiting which fields are returned by the API
The API consumer doesn't always need the
full representation of a resource. The ability select and chose returned fields
goes a long way in letting the API consumer minimize network traffic and speed
up their own usage of the API.
Use a fields query parameter that takes a
comma separated list of fields to include. For example, the following request
would retrieve just enough information to display a sorted listing of open
tickets:
GET
/tickets?fields=id,subject,customer_name,updated_at&state=open&sort=-updated_at
HTTP
methods
As stated earlier, one of the key objectives
of the REST approach is using HTTP as an application protocol in order to avoid
shaping a homemade API. Hence, we should systematically use HTTP verbs to
describe what actions are performed on the resources and facilitate the
developer’s work handling recurrent CRUD operations.
The following methods are usually observed:
HTTP Method
|
Description
|
Sample URI
|
GET
|
The GET method is used to retrieve
information from the given server using a given URI. Requests using GET
should only retrieve data and should have no other effect on the data.
|
GET /orders/123
|
POST
|
A POST request is used to send data to the
server, for example, customer information, file upload, etc. using HTML
forms.
|
POST /orders
|
PUT
|
Replaces all current
representations of the target resource with the uploaded content.
|
PUT /orders
|
DELETE
|
Removes all current representations of the
target resource given by a URI.
|
DELETE /orders/123
|
OPTIONS
|
Describes the communication options
for the target resource.
|
OPTIONS /orders
|
HTTP
Headers
HTTP header fields provide required
information about the request or response, or about the object sent in the
message body.
There are 4 types of HTTP message headers:
General Header: these header fields have general
applicability for both request and response messages.
Client Request Header: these header fields have applicability
only for request messages.
Server Response Header: these header
fields have applicability only for response messages.
Entity Header: these header fields define meta
information about the entity-body or, if no BODY is present, about the resource
identified by the request.
HTTP
Status Codes
When the client raises a request to the
server through an API, the client should know the feedback, whether it failed,
passed or the request was wrong. HTTP status codes are bunch of standardized
codes which has various explanations in various scenarios. The server should
always return the right status code.
The following are the important
categorization of HTTP codes:
2xx (Success category)
These status codes represent that the
requested action was received and successfully processed by the server.
ü
200 Ok The standard HTTP response representing
success for GET, PUT or POST.
ü
201 Created This status code should be returned
whenever the new instance is created. E.g on creating a new instance, using
POST method, should always return 201 status code.
ü
202 Accepted This status code should be returned
whenever the request is accepted by Resouce.
ü 204 No Content represents the request is successfully processed, but has not returned
any content.
DELETE can be a good example of this.
The API DELETE /companies/43/employees/2
will delete the employee 2 and in return we do not need any data in the
response body of the API, as we explicitly asked the system to delete. If there
is any error, like if employee 2 does not exist in the database, then the
response code would be not be of 2xx Success Category but around 4xx Client
Error category.
3xx (Redirection Category)
ü
304 Not Modified indicates that the client has the
response already in its cache. And hence there is no need to transfer the same
data again.
ü 302 Redirected indicates when client is redicted URI to another URI.
4xx (Client Error
Category)
These status codes represent that the client
has raised a faulty request.
ü
400 Bad Request indicates that the request by the
client was not processed, as the server could not understand what the client is
asking for.
ü
401 Unauthorized indicates that the client is not
allowed to access resources, and should re-request with the required
credentials.
ü
403 Forbidden indicates that the request is valid
and the client is authenticated, but the client is not allowed access the page
or resource for any reason. E.g sometimes the authorized client is not allowed
to access the directory on the server.
ü
404 Not Found indicates that the requested resource
is not available now.
ü
405 - Method Not Allowed When an HTTP method is being requested that
isn't allowed for the authenticated user.
ü
409 - Conflict (i.e. trying to create the same
resource with a PUT request)
ü
410 Gone indicates that the requested resource is no
longer available which has been intentionally moved.
ü
415 Unsupported Media Type - If incorrect
content type was provided as part of the request
ü
422 Unprocessable Entity - Used for
validation errors
ü 429 Too Many Requests - When a request is rejected due to rate limiting
5xx (Server Error Category)
ü
500 Internal Server Error indicates that the
request is valid, but the server is totally confused and the server is asked to
serve some unexpected condition.
ü 503 Service Unavailable indicates that the server is down or unavailable to receive and process
the request. Mostly if the server is undergoing maintenance.
Security
A RESTful API should be stateless. This
means that request authentication should not depend on cookies or sessions.
Instead, each request should come with some sort authentication credentials.
By always using SSL, the authentication
credentials can be simplified to a randomly generated access token that is
delivered in the user name field of HTTP Basic Auth. The great thing about this
is that it's completely browser explorable - the browser will just popup a
prompt asking for credentials if it receives a 401 Unauthorized status code
from the server.
However, this token-over-basic-auth method
of authentication is only acceptable in cases where it's practical to have the
user copy a token from an administration interface to the API consumer
environment. In cases where this isn't possible, OAuth 2 should be used to
provide secure token transfer to a third party. OAuth 2 uses Bearer tokens
& also depends on SSL for its underlying transport encryption.
An API that needs to support JSONP will need
a third method of authentication, as JSONP requests cannot send HTTP Basic Auth
credentials or Bearer tokens. In this case, a special query parameter
access_token can be used. Note: there is an inherent security issue in using a
query parameter for the token as most web servers store query parameters in
server logs.
For what it's worth, all three methods above
are just ways to transport the token across the API boundary. The actual
underlying token itself could be identical.
Caching
HTTP provides a built-in caching framework!
All you have to do is include some additional outbound response headers and do
a little validation when you receive some inbound request headers.
There are 2 approaches: ETag and
Last-Modified
ETag: When generating a response, include a HTTP
header ETag containing a hash or checksum of the representation. This value
should change whenever the output representation changes. Now, if an inbound
HTTP requests contains a If-None-Match header with a matching ETag value, the
API should return a 304 Not Modified status code instead of the output
representation of the resource.
Last-Modified: This basically works like to ETag,
except that it uses timestamps. The response header Last-Modified contains a
timestamp in RFC 1123 format which is validated against If-Modified-Since. Note
that the HTTP spec has had 3 different acceptable date formats and the server
should be prepared to accept any one of them.
Versioning
When your APIs are being consumed by the
world, upgrading the APIs with some breaking change would also lead to breaking
the existing products or services using your APIs.
http://api.yourservice.com/v1/companies/34/employees
is a good example, which has the version
number of the API in the path. If there is any major breaking update, we can
name the new set of APIs as v2 or v1.x.x.
Conclussion
REST is not something new. REST is a return
to the Web the way it was before the age of the big application server, through
its emphasis on the early Internet standards, URI, and HTTP.
Resource modeling requires a careful
consideration based on the business needs, technical considerations (clean
design, maintainability, etc.) and cost-benefit analysis of various approaches
discussed earlier so that the API design brings out the best API consumer
interaction experience.
Download
S. No
|
File Name
|
Size
|
Download
|
1
|
REST API
Design Principles.pdf
|
500 KB
|
Comments
Post a Comment