HTTP API Design Part 2: Responses

Support this website by purchasing prints of my photographs! Check them out here.

This is the second of four articles on HTTP API Design. These articles are based on content from my recent book Advanced Microservices. This content is influenced by the HTTP standard itself as well as common RESTful practices.

HTTP Response Overview

After a server receives a request from a client it will always reply with an HTTP response (unless something horrible happens). This message is similar in formatting to the request but is different enough to warrant it's own article. The following is an example of a complete HTTP Response:

```plain HTTP/1.1 200 OK <-- Status Line Date: Wed, 14 Jun 2017 23:23:01 GMT <-- Response Headers Content-Type: application/json Access-Control-Max-Age: 1728000 Cache-Control: no-cache <-- Two Newlines { <-- Body "id": "12", "created": "2017-06-14T23:22:59Z", "modified": null, "name": "Gir", "animal_type": "12" }

The first line is called a Status Line and contains two pieces of information. The first is the protocol, in this case HTTP 1.1, followed by a space. The second piece of information is the status of the request, which is made up of a machine-parseable numeric representation of the status (a status code) as well as a space and a human-readable Reason-Phrase, followed by a newline. The Reason-Phrase is paired with the status code, but for the most part it's an antiquated string that clients can ignore.

Just like an HTTP Request, the response contains a series of key/value header pairs. The name of the header is on the left, followed by a colon and a space, and then the value, followed by a newline. Technically the name of the header can be in any case but the diligent server will reply using Capital-Hyphenated-Words. Headers can be repeated if they have multiple values, e.g. repeating the Set-Cookie header allows us to set multiple cookies in a single response.

The status codes are separated into different numeric ranges, with each range representing a different class of statuses. The following sections of this article describe the different ranges as well as common values within each range.

The headers are followed by an optional body, which requires two newlines from the last header before the start of the body content. Nearly all responses will include a body though it is technically optional.

1XX Status Codes – Informational

The 1XX range of status codes (100 – 199) are informational status codes. You will very likely go your entire career and never have to deal with a status code in this range.

  • 101 Switching Protocols: used for websockets

2XX Status Codes – Successful

The 2XX range of status codes (200 – 299) are successful status codes.They signal to the client that whatever the operation, such as creating a resource or simply retrieving one, has been successfully completed. Ideally they are the most frequently consumed and produced status codes.

  • 200 OK: normal successful catch-all status
  • 201 Created: resource has been created
  • 202 Accepted: successfully created or modified resource but change is asynchronous
  • 204 No Content: request was successful but has no body

3XX Status Codes – Redirection

The 3XX range of status codes (300 – 399) are used for redirecting the client from one place to another. They don't have a body but instead make use of a Location header. This contains a URL the client should be redirected to.

  • 301 Moved Permanently: resource is at new location, always go to new location
  • 302 Found: resource is at new location, but always check old location first

4XX Status Codes – Client Error

The 4XX range of status codes (400 – 499) represent errors on behalf of the client. When a normally Unsafe request encounters an error in this range, the operation should NOT have altered the state of the server.

  • 400 Invalid Request: generic client failure
  • 401 Unauthorized: client needs to provide an authorization header
  • 403 Forbidden: client isn't allowed to access a resource
  • 404 Not Found: resource can't be found, doesn't exist
  • 405 Method Not Allowed: the endpoint exists but doesn't support the requested method
  • 406 Not Acceptable: the server cannot generate a response for the requested Accept header

5XX Status Codes – Server Error

The 5XX range of status codes (500 – 599) represent errors which occur on the server. When these happen something wrong probably happened on the server, or perhaps the request wasn't even received. When an Unsafe request happens it is now impossible to know the state of the server. These errors should be avoided at all costs.

  • 500 Internal Server Error: generic server side error
  • 501 Not Implemented: the server does not yet support this method/endpoint combination
  • 503 Service Unavailable: the server is temporarily unavailable, e.g. database disconnected
  • 521 Web Server Is Down: an intermediary server couldn't connect to the destination server

Response Headers

Much like with requests, there are a ton of Response Headers to make use of. These headers represent metadata about the response. Typically you want to make use of a standard HTTP header but sometimes you need to invent one of your own. When doing so it's customary to prefix the header with X-, such as X-Request-ID. The following list represents the most common headers:

  • Cache-Control: specifies the cache policy, e.g. no-cache if resource shouldn't be cached
  • Content-Language: the language of the content, e.g. en-US
  • Content-Length: the size in bytes of the response body, if known ahead of time
  • Content-Type: the content type of the body, e.g. application/json
  • Date: date and time of the server
  • Expires: date and time when content should expire
  • Server: a mostly useless field used to identify the server

This article is based on content from my book Advanced Microservices.There's also an accompanying HTTP API Design Presentation.

Tags: #apis
Thomas Hunter II Avatar

Thomas has contributed to dozens of enterprise Node.js services and has worked for a company dedicated to securing Node.js. He has spoken at several conferences on Node.js and JavaScript and is an O'Reilly published author.