Ross Tuck: HTTP and your Angry Dog
Ross Tuck (@rosstuck) was talking about HTTP at Whisky Web II, these are my notes from his talk.
As developers we'd rather buy our head in the sand than deal with HTTP, we need to get along.
HTTP
Client server protocol, request is a plain text format. We worry about the body and tend to ignore the header - aka the Good Stuff.
Request
- Verb + URL
- Key value pairs
Response
- Status code
- Body
Status codes
Don't worry too much about status codes - get it in the right range rather than exactly right. If in doubt then round down to the nearest hundred:
2xx
OK3xx
Over there4xx
Client screwed up5xx
Server screwed up
Content negotiation
Don't use file extensions - file.json !== file.xml Imagine the URL as your primary key. Query did not count toward the URL - it now does. Query params are illegal on a POST.
We use Accept:
header to specify which format we want. There are several methods of determining the way the accept header is negotiated. Normally decided by the server.
Can send query params to accept but only q
is allowed: text/plain;q=0.1
This is used to define the priority of what we want.
Accept language is another example of this - much better than trying to geolocate.
The server will send back Content-[type]
to show what it is returning.
Resource vs Representation
/dog/corgi
is the resource. JSON or XML is the representation.
Accept header can be used to version the API: Accept: application/vnd.dogipedia-vX+json
The future
Can't get away from HTTP1.1 - it's here to stay for now.
Vary header
This is useful for proxy severs and caching. Proxy servers need to know that you are doing content negotiation so it needs to know that the content might not always be the same for a given URL. The generating server uses the Vary:
header to define which request headers will change the content returned to the client.
Internet explorer does odd things - it's why we can't have nice things on the internet.
Caching
Three headers define caching:
- Expires (HTTP: 1.0)
- Pragma - DON'T USE THIS
- Cache-Control (HTTP: 1.1)
Expires is a timestamp at which the cached copy becomes invalid. Uses an odd date format that will do odd things if you get it wrong.
Cache-Control is a number of seconds until the cached copy becomes invalid. Use cache control and a post-dispatch handler to add expires. s-maxage
and others can describe what caches and proxies should do. Mark Nottingham's Caching Tutorial is worth reading.
Conditional requests (The part about ETags)
You can create conditional conditions but don't. An ETag is a string that represents the current state. Usually the server takes something and hashes it but you can use anything as long as its for the current representation: v14-json-en
!== v14-xml-en
The vary header is not a bad place to start but don't cross the streams.
Caching with conditionals
Caching with ETags is a common use case. Requesting the same content each time isn't a win for anyone, if the ETag is set then we should remeber it and send it with a If-None-Match
header. If the ETag hasn't changed on the server it will send a 304 (Not Modifed)
status code and won't send the body of the request because you have said it cached. Not every server supports ETags, if it doesn't send one then it doesn't support them. Might not be supported for every resource.
The fastest request is one you didn't make. If you send a cache control header the client doesn't have to make the request.
More fun with ETags
Optimistic Concurrency Control - version control. 412 (Precondition failed)
can be used to indicate that a record has changed between read and write. 412
specifically indicates an ETag conflict. 428 (Precondition requried)
says that you need to send an ETag when modifiying a resource to indicate you have at least read the request first.
Tools
- Firebug
- Chrome web inspector
Summary
HTTP has a ton of features - use them but only take what you need to survive.