└── README.md /README.md: -------------------------------------------------------------------------------- 1 | 2 |

Introduction

3 | 4 |

Representational State Transfer (REST) is an architectural 5 | style defined by Roy Fielding in 2000 in his PhD dissertation. REST describes a 6 | web architecture that is not specific to web APIs. However, it has become the 7 | most popular style of web API, overtaking SOAP in 2008. REST APIs are simple to 8 | use, scalable, portable and easy to integrate with. The aim of this paper is to 9 | look at what constraints are involved in creating a RESTful API and what the 10 | best practices are for web REST APIs.

11 | 12 |

REST Constraints

13 | 21 | 22 |

Client-Server

23 | 24 |

The Client-Server constraint is focused on separation of 25 | concerns. By separating the front end UI from the back end data storage 26 | concerns, portability and scalability are improved. This also allows the 27 | separate components to evolve independently.

28 | 29 | 30 |

Stateless

31 | 32 |

The server should not store any state of the current 33 | session. This means every request sent 34 | from the client to the server should include all information necessary to 35 | fulfil that request. Session state is managed solely by the client.

36 | 37 |

The pros of this constraint are visibility, reliability and 38 | scalability. Visibility is improved because the server only has to deal with 39 | one request and the information that was sent with it. Reliability and 40 | scalability are improved because the server is not storing any session 41 | information so session information does not have to be copied across multiple 42 | server instances in case of a server failure and this allows for easy 43 | scalability for the same reason.

44 | 45 |

The con is that common information will have to get sent 46 | with each request (e.g. user authentication information) which will decrease 47 | network performance. Having the client store all session state reduces the 48 | servers control with consistent application behaviour because of multiple 49 | client versions

50 | 51 |

Cache

52 | 53 |

The cache constraint is to improve network efficiency and 54 | hence improve user-perceived performance. Each request can either be cacheable 55 | or non-cacheable. If a response is cacheable, the client can use the cached 56 | response for the same request later on.

57 | 58 |

The major benefit of caching is performance. Allowing 59 | certain responses to be cacheable allows for fewer requests to the server and 60 | much faster retrieval of cached data for the client.

61 | 62 |

The disadvantage is if cached data differs from data that 63 | would have been sent back if the request had reached the server. This needs to 64 | be maintained by having a time limit on the how long the response should be 65 | cached for.

66 | 67 |

68 | 69 |

Uniform Interface

70 | 71 |

This constraint is what distinguishes REST from other 72 | network-based architectural styles. The constraint states that all services and 73 | service consumers must share a single, overarching technical interface. The 74 | uniform interface is generally applied using methods and media types provided 75 | by HTTP. This constraint will be the main area of focus for best practices because 76 | the API design is how other developers will see the API and interact with it. Four 77 | sub constraints are defined to achieve the uniform interface constraint, these 78 | are

79 | 80 | 86 | 87 |

Identification of resources

88 | 89 |

Fielding defines a resource as “Any information that can be 90 | named: a document or image, a temporal service (e.g. today's weather in 91 | Los Angeles), a collection of other resources, a non-virtual object (e.g. 92 | a person)”. In web based REST APIs, resources are identified using URIs. The 93 | resources are conceptually separate from the representation returned to the 94 | client. The server sends a representation of a resource using HTML, XML, JSON 95 | or other formats.

96 | 97 |

Manipulation of resources through representations

98 | 99 |

The representation of the resource that the client stores 100 | should have all the information necessary to manipulate the resource itself 101 | through the API (modify or delete).

102 | 103 |

Self-descriptive messages

104 | 105 |

The message response from the API should include the 106 | information necessary to tell the client how to process the message. With web 107 | REST APIs, this is done using internet media types. In the response header, the 108 | Content-type field will have a value describing the message body format e.g. application/json. 109 | Responses should also outline the cache criteria.

110 | 111 |

Hypermedia as the engine of application state (HATEOAS)

112 | 113 |

One initial base resource should be the entry point to the 114 | API. Clients should then receive applicable actions from the server. Hypermedia 115 | in web REST APIs are hyperlinks within hypertext. For example, if the client 116 | retrieves a resource representation, the response should include other applicable 117 | actions that can be taken on that resource like modifying or delete with the 118 | URI hyperlink for each.

119 | 120 |

121 | 122 |

Layered System

123 | 124 |

The layered system builds on top of the Client-Server 125 | architecture and describes a system that is made up of multiple architectural 126 | layers. The constraint outlines that each layer should only know about the 127 | immediate layer it is interacting with.

128 | 129 |

By restricting the knowledge of what other layers a layer 130 | knows about, this decreases complexity and allows for easier scalability by allowing 131 | load balancing of services. Also, additional middleware will be easier to 132 | integrate.

133 | 134 |

The main disadvantage is increased overhead and latency. 135 | This can be mitigated with the cache constraint, allowing cached content at the 136 | boundaries of the separate layers where applicable.

137 | 138 |

139 | 140 |

Code-On-Demand (optional)

141 | 142 |

This constraint allows client functionality to be extended 143 | by the server sending executable code in the form of applets or scripts. This 144 | means that additional modules can be executed on the client when necessary or 145 | needed.

146 | 147 |

This constraint is optional so it can be excluded without 148 | violating the principles of REST.

149 | 150 |

151 | 152 |

RESTful Web API Best Practices

153 | 154 |

URL structure

155 | 156 |

The base URL is the entry point of the API. The path after 157 | the base should identify a resource or collection of resources. The query 158 | parameter is appended to the end of the resource path.

159 | 160 | http://example.com/users/1234/activities?activityType=running

161 | 162 | 163 |

164 | Base URL, Resource, Query Parameter 165 |

166 | 167 |

In the above example, the resource should be viewed in a 168 | hierarchical way. ‘/Users’ is a top level collection. ‘/1234’ is the id that 169 | identifies a unique user. ‘/activities’ is a collection of activity resources 170 | specific to the user 1234.

171 | 172 |

173 | 174 |

Resource Naming

175 | 176 |

The URIs that identify resources are arguably the most important 177 | to get right because they are the most visible part of the API.

178 | 179 |

Only 2 URIs per resource

180 | 181 |

182 | 183 | /users 184 | 185 |

186 |

187 | 188 | /users/1234 189 | 190 |

191 | 192 | 193 |

The first is a collection of resources, the second is a 194 | specific resource in the collection. In this case, all users and a specific 195 | user.

196 | 197 |

Nouns, not verbs

198 | 199 |

Keep verbs out of the resource name. The HTTP method is what 200 | describes the action for the request. Resource names should be nouns but plural 201 | nouns are preferable. Readability is paramount with a consistent pattern. With 202 | the verb approach, different developers will come up with vastly different 203 | naming schemes and they are not easy to learn. Using nouns, the API is easier 204 | to understand and read. Plural nouns are always preferred to keep consistency 205 | and understanding. The /users collection compared /user tells the reader that 206 | it identifies all users, not just one.

207 | 208 |

Examples with verbs - 209 | Bad

210 | 211 |

/getUsers

212 | 213 |

/createUser

214 | 215 |

/saveUser

216 | 217 |

/getUserActivities

218 | 219 |

/updateUserActivity

220 | 221 |

/deleteActivities

222 | 223 |

/deleteUserActivity

224 | 225 |

226 | 227 |

Examples with nouns – 228 | Good

229 | 230 |

The HTTP methods on the right are what would be used as an equivalent 231 | to the bad URIs.

232 | 233 |

/users GET(getUsers), 234 | POST(createUser)

235 | 236 |

/users/1234 PUT(saveUser)

237 | 238 |

/users/1234/activities GET(getUserActivities), 239 | DELETE(deleteActivities)

240 | 241 |

/users/1234/activities/4321 PUT(updateUserActivity), 242 | DELETE(deleteUserActivity)

243 | 244 |

245 | 246 |

Lower case

247 | 248 |

Consistency is key with casing. Lower case is easier to type 249 | in and no confusion can occur when trying to remember the casing. Mixed case 250 | might also cause ambiguity.

251 | 252 |

Keep It Intuitive

253 | 254 |

URIs should be human-guessable, meaningful and predictable. 255 | The name should tell the user what they are looking at. 256 | ‘/users/1234/activities’ should give a hint that the URI identifies the 257 | activities collection for user 1234. When URIs are meaningful like this, a user 258 | should be able to predict or guess other URIs if they know some of the API.

259 | 260 |

Hackable

261 | 262 |

The hierarchy of resources should allow the user to remove the 263 | leaf path and access the parent resource. By removing the ‘activities’ leaf 264 | path from the example URIs above, we are left with ‘/users/1234’ which we would 265 | expect identifies a unique user. Again, by removing the remaining leaf path 266 | ‘1234’, we expect ‘/users’ identifies a collection of users. Lower case names

267 | 268 |

269 | 270 |

When/what to use query parameters for

271 | 272 |

URI query parameters are used for filtering, searching, sorting 273 | and pagination.

274 | 275 |

Filtering or searching

276 | 277 |

Send a unique value for the field(s) to be filtered/searched, 278 | for example /users?firstname=david&age=24. Each 279 | additional field should be preceded with an ‘&’. This will return the users 280 | that only have a name of ‘david’ and an age of 24.

281 | 282 |

Sorting

283 | 284 |

Sorting needs two criteria, the field to sort and the 285 | direction of the sort. The direction should be ASC (ascending) or DESC (descending). 286 | For example /users?sort=email&dir=DESC.

287 | 288 |

Pagination

289 | 290 |

Pagination also requires two parameters. The item to start on 291 | (start) and how many items to return (limit). For example 292 | /users?start=60&limit=20 will return the items from 60-79.

293 | 294 |

295 | 296 |

HTTP Methods

297 | 298 | 303 | 304 | 316 | 333 | 350 | 367 | 384 | 385 | 386 | 397 | 406 | 415 | 426 | 437 | 438 | 439 | 450 | 459 | 468 | 477 | 486 | 487 |
306 |

309 |

Resource

312 |

315 |
320 |

323 |

POST

326 |

create

329 |

332 |
337 |

340 |

GET

343 |

read

346 |

349 |
354 |

357 |

PUT

360 |

update

363 |

366 |
371 |

374 |

DELETE

377 |

delete

380 |

383 |
390 |

392 |

/users

394 |

396 |
403 |

Create a new user

405 |
412 |

List users

414 |
421 |

Bulk update users

423 |

or error

425 |
432 |

Delete all users

434 |

or error

436 |
443 |

445 |

/users/1234

447 |

449 |
456 |

error

458 |
465 |

List unique user

467 |
474 |

Update user

476 |
483 |

Delete user

485 |
488 | 489 |

490 | 491 |

The four HTTP methods map to CRUD. Create = POST, Read = 492 | GET, Update = PUT and Delete = DELETE. The HTTP method determines what action 493 | is performed on the resource. Web REST APIs use the HTTP protocol for requests/responses, 494 | HTTP outlines a set of methods that can be used for requests and the four above 495 | are the main ones used in REST APIs. In the above example, most APIs would not 496 | allow a PUT or DELETE on a collection (/users) as this could be dangerous.

497 | 498 |

GET, PUT and DELETE are idempotent but POST is not. This 499 | means, no matter how many times the idempotent request methods are sent, the 500 | outcome will always be the same. With POST, a new resource will be created 501 | every time.

502 | 503 |

504 | 505 |

What to include in HTTP headers

506 | 507 |

HTTP headers should include metadata for the request and 508 | response. This includes the body format, caching and authorisation fields. Below 509 | are three examples of common header fields:

510 | 511 |

Content-Type: The 512 | format type of the request or response body. Used with POST and PUT. Example: Content-Type: application/json.

513 | 514 |

Accept: Request 515 | only - Lists Content-Types acceptable for the response. Example: Accept: text/plain; application/json.

516 | 517 |

Allow: Response 518 | only - Valid methods for the resource, if an invalid method was used.

519 | 520 |

Caching

521 | 522 |

The browser has a built in caching framework which can be 523 | leveraged using cache specific HTTP headers in the response, these are Cache-Control and 524 | Etag.

525 | 526 |

Cache-Control: This 527 | specifies how long the response should be cached for in seconds. Example: Cache-Control: max-age=3600.

528 | 529 |

Etag: 530 | A unique identifier for a specific version of a resource. Example: ETag: “x234dff”.

531 | 532 |

When the cached response times out and another request is 533 | made for the same resource, the browser will send the ETag token as a value of 534 | a request header called If-None-Match. The server should check this token 535 | against the current resource version and send back a response with a status 536 | code of ‘304 Not modified’ if they match. The cache time-out will get then get 537 | reset.

538 | 539 |

If-None-Match: Etag 540 | token sent in new request. If the resource hasn’t changed, the response is ‘304 541 | Not Modified’ and the cache time out is reset.

542 | 543 |

544 | 545 |

Error handling

546 | 547 |

Standard HTTP status codes for error responses.

548 | 549 |

HTTP status codes starting with 4xx are client errors and 550 | 5xx are server errors. Here are some examples of common error response status 551 | codes.

552 | 553 |

400 Bad Request: Malformed request 555 | syntax

556 | 557 |

401 Unauthorized: Authentication is 559 | required or has failed

560 | 561 |

404 Not Found: Requested resource could 563 | not be found

564 | 565 |

405 Method Not Allowed: HTTP method 567 | used is not allowed on the resource

568 | 569 |

Detailed error description

570 | 571 |

The error message in the response should explain the problem 572 | in human readable format. Let it be verbose, you shouldn’t be trying to save 573 | bandwidth on errors.

574 | 575 |

Internal error code

576 | 577 |

Include the internal error code so it can be looked up for 578 | more information. To go one step further, include a URL link in the response to 579 | the specific internal error in your documentation.

580 | 581 |

Extra: Allow HTTP status code override

582 | 583 |

Allow a URL query parameter on all requests that will always 584 | return a HTTP status code of 200. Twitter’s query param to allow this is ‘suppress_response_codes=true’. 585 | The original http status code should then be included in the response body. This 586 | can be useful when some proxies only allow 200 status codes through or for 587 | debugging reasons.

588 | 589 |

590 | 591 |

Versioning

592 | 593 |

There is some debate on how to version APIs or whether 594 | versioning should be included at all. Versioning an API breaks the HATEOAS 595 | constraint of REST but pragmatic REST APIs that don’t adhere to this constraint 596 | might still need to version. If the API needs to be versioned, the two most 597 | popular ways this can be achieved is to include it as a custom request header 598 | or include it as part of the URL. The most visible method and easiest to work 599 | with is to keep it in the URL, for example /v1/users. Some standards should be 600 | used.

601 | 602 |

Include the letter v

603 | 604 |

Including the letter v in your version name automatically 605 | indicates that part of the URL path specifies the version.

606 | 607 |

Keep to whole version numbers

608 | 609 |

Even though there will be numerous internal build numbers 610 | for bug fixes and enhancements, APIs should not change version very often. Keeping 611 | the version to whole numbers like v1 or v2 forces the API to rarely release a 612 | new version and limits the number of legacy API versions that need to be 613 | maintained.

614 | 615 |

616 | 617 |

Security and Authorization

618 | 619 |

A full discussion on this topic is outside the scope of this 620 | document but I will cover the basic best practices.

621 | 622 |

HTTPS on all requests to the API

623 | 624 |

HTTPS means using HTTP over the SSL/TLS protocol. The 625 | purpose of HTTPS is to prevent man-in-the-middle and wiretapping attacks. Using 626 | this is especially important if the API is using HTTP basic authentication.

627 | 628 |

OAuth 2

629 | 630 |

This provides authentication through third parties such as 631 | facebook or twitter. This will require an extra library but the major benefit 632 | is outsourcing your full authorization to these secure third parties. OAuth 2 633 | also allows custom authorization, on the initial login request, the server 634 | returns a JSON Web Token that is stored on the client. Each subsequent request 635 | sends this JWT as Bearer token in the Authorization request header field.

636 | 637 |

638 | 639 |

Session state

640 | 641 |

The server should not store any state of the current 642 | session. This means every request sent 643 | from the client to the server should include all information necessary to 644 | fulfil that request. Session state is managed solely by the client.

645 | 646 |

The session can be stored on the client in many forms, such 647 | as cookies or tokens.

648 | 649 |

650 | 651 |

HATEOAS

652 | 653 |

Think of it as state are webpages and transitions are 654 | hyperlinks. It boils down to including links in each response message for the 655 | next request message. This way the server drives the app state, not the client. 656 | For example, a GET on /users/1234 will include links in the response for other 657 | appropriate actions to take next, such as PUT /users/1234 or DELETE 658 | /users/1234.

659 | 660 |

HAL (Hypertext Application Language)

661 | 662 |

HAL provides a set of conventions for expressing hyperlinks 663 | in either JSON or XML. This is one of the most common formats for implementing 664 | HATEOAS. The media type for HAL is application/hal+json. HAL responses include 665 | a link to the resource just retrieved and other associated resources and it 666 | specifies how to embed links in nested data. More can be read here http://stateless.co/hal_specification.html. 668 | Here is an example to show the structure of a response.

669 | 670 | 671 |

REST API Grading: Richardson Maturity Model

672 | 673 | 674 |

The Richardson Maturity Model outlined by Leonard Richardson 675 | is a way to grade your API based on four levels. It breaks down the main 676 | elements of REST into three steps.

677 | 678 |

(Image credit: Martin Fowler)

679 | 680 |

The model has simplified the REST constraints but is a good 681 | basic way to grade your web REST API. The levels are to be taken as building 682 | blocks, to reach the next level the previous level has to be met. Reaching 683 | level 1 of the RMM is common with REST APIs trying to represent CRUD-driven 684 | objects as resources. When level 3 is reached, the API is truly RESTful.

685 | 686 |

Level 0: The swamp of POX (plain old XML)

687 | 688 |

The API uses HTTP as the transport protocol. It doesn’t use 689 | HTTP to indicate application state as it will use one method which is usually POST 690 | for most URIs. No resources are clearly defined and all requests are sent to a 691 | single endpoint. Examples of this level are SOAP and XML-RPC

692 | 693 |

Level 1: Resources

694 | 695 |

Level 1 is when your API can distinguish between different 696 | resources. Requests are sent to individual resource URIs. However, a single 697 | method like POST is still used.

698 | 699 |

Level 2: HTTP Verbs

700 | 701 |

So far, the previous levels have mostly used a single HTTP 702 | method like POST. This level starts using HTTP methods as they are used in HTTP 703 | itself. GET, POST, PUT and DELETE are used for various resources.

704 | 705 |

Level 3: Hypermedia Controls

706 | 707 |

The last level is when HATEOAS is implemented in your API. 708 | According to the Richard Maturity Model, APIs that reach this level are 709 | considered RESTful.

710 | --------------------------------------------------------------------------------