Monday, 29 October 2012
OPTIONS is Not the Method You're Looking For
Once in a while, people ask me whether they should use the OPTIONS HTTP method, and whether we should try to define formats for discovering resource capabilities with it.
I usually say “no.” This is a personal position, nothing “official”. That said, the conversation usually goes like this:
What’s Wrong with OPTIONS?
A few things. First and foremost, it can’t be cached. Usually, people want to use OPTIONS to discover some metadata about the server (the “OPTIONS *” case) or a specific resource (e.g.’, “OPTIONS /foo”), and they need some way to keep that state “fresh” on the client, so that it can be used throughout the interaction. To make OPTIONS work well, you’d be forced to design your own caching model – silly when HTTP already has one.
Likewise, you can’t easily work with OPTIONS in a browser; there isn’t a link for the OPTIONS representation, so you need to have a different way to talk about it. This is because it effectively creates a separate, alternate “silent” representation for a resource.
Finally, for better or worse, it’s still difficult to use OPTIONS with many implementations, both client and server.
Why is HTTPbis leaving OPTIONS in, then?
OPTIONS is used out there (e.g. by WebDAV, and unfortunately, CORS too), so we can’t just remove it. There are also some very specific cases where it might be appropriate; e.g., a browser discovering a proxy’s capabilities (in conjunction with max-forwards).
What should I use instead?
For server-wide metadata, have a look at creating a well-known URI, or using an already existing one if it’s appropriate. This gives you an easy, unambiguous way to link to the site metadata, and it’s cacheable to boot. Instead of OPTIONS on a specific resource, try using a Link header on its responses, or a link in the representation format for that resource; by linking to the metadata for the resource, you give it identity, making it cacheable and linkable. For example, a response for /foo could point to its metadata with:
Link: </foo.md>; rel="describedby"
Here, it’s important to use an appropriate link relation type; “describedby” is often appropriate here, but have a look at the registry first. If someone wants to discover a resource’s capabilities before they interact with it, they can use HEAD.
Finally, if there’s a deterministic mapping for looking up metadata for resources on your server, you might consider putting a URI Template into a well-known location, so that clients know where to find it without any per-request overhead. This is the approach that hostmeta effectively takes.