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 status201 Created
: resource has been created202 Accepted
: successfully created or modified resource but change is asynchronous204 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 location302 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 failure401 Unauthorized
: client needs to provide an authorization header403 Forbidden
: client isn't allowed to access a resource404 Not Found
: resource can't be found, doesn't exist405 Method Not Allowed
: the endpoint exists but doesn't support the requested method406 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 error501 Not Implemented
: the server does not yet support this method/endpoint combination503 Service Unavailable
: the server is temporarily unavailable, e.g. database disconnected521 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 cachedContent-Language
: the language of the content, e.g. en-USContent-Length
: the size in bytes of the response body, if known ahead of timeContent-Type
: the content type of the body, e.g. application/jsonDate
: date and time of the serverExpires
: date and time when content should expireServer
: 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.