mark nottingham

OPTIONS is Not the Method You're Looking For

Monday, 29 October 2012

HTTP HTTP APIs

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.


8 Comments

jaaju said:

Mark, thanks for the post.

The alternate approaches you recommend for metadata discovery seem good. As for the couple of use cases that OPTIONS serves, will it benefit from allowing the server to define cache control? It appears proxy capability as well as methods allowed on a resource should be fairly static information and can benefit from caching. More specifically, do you know the reasoning behind declaring OPTIONS not cacheable? Some light on that will be helpful.

Thanks, jay

Tuesday, October 30 2012 at 3:05 AM

Mike Schinkel said:

Mark,

Thanks for the reply.

To someone less-steeped in W3 architecture like me, that seems like an arbitrary distinction? Why can’t OPTIONS imply a representation of the meta for a resource? I understand if the answer is “because it’s was defined that way” but am curious if it could have been/still could be?

As for hypermedia != HTML, I was thinking about JSON when I wrote the question. :)

As for PROPFIND I assume that it being webdav disqualifies it for use as a standard metadata access method for RESTful web services, right?

Again, appreciate the answers.

-Mike

Tuesday, October 30 2012 at 3:39 AM

Mike Schinkel said:

Hi @Mark,

Thanks for this writeup. Your posts are typically really helped.

I’ve been considering OPTIONS ever since Keith Casey of Twilo talked about[1] it at RESTFest, kinda sad to hear “it’s not the method I’m looking for.” :( Just curious, why isn’t it cacheable? Was it an arbitrary decision in the spec or is there a reason why it can’t or should not be? Seems like it would make a really obvious good way to handle metadata if it weren’t for these issues.

Also, what are your thoughts on link headers and the hypermedia constraint of REST; are link headers valid or does that violate Roy’s view of REST (if you can’t speak to that because you are not Roy, I understand. :) Of course link headers are invisible to us API surfers via browser so that sux, but one nice thing is they bypass the hypermedia content type wars that are currently raging in the small.

-Mike [1] http://vimeo.com/channels/restfest/49613738

Tuesday, October 30 2012 at 11:00 AM

Doug Moscrop said:

An interesting read.

When you say Likewise, you can’t easily work with OPTIONS in a browser doesn’t that kind of contradict your HTTP != HTML point? Why should HTTP let the browser dictate anything? I would use XHR for the OPTIONS, in an ideal world.

I don’t want to cache OPTIONS. My OPTIONS could change, could they not? If I was in a browser, I would use OPTIONS to discover what abilities I have for a particular resource and base my client-side template accordingly. Should those OPTIONS change, well, sure, I have to handle that.

I may have been able to GET and POST to /foo but now someone has revoked my right to POST. I have to handle that no matter what. I don’t see what caching gets you in that case. In that sense, actually, the client-side template is the cache, and there’s nothing easier about maintaining an “external link” (you even changed the URI in your description - why does foo.md describe the foo resource? why not a different representation of said resource? What happens when the metadata changes?). Would you not, possibly use some form of browser events to detect when OPTIONS could change and update yourself accordingly? If your answer is “yes, but…” then isn’t that same “yes, but…” applicable to caching the representation of a metadata resource (which itself puts, in my opinion, an additional issue of tracking metadata resources with actual resources).

Perhaps I am way off here, and what you mean is don’t use OPTIONS for [specific thing] but still use it for [other thing]. I would like to use OPTIONS to find out if I am able to GET or POST to a particular resource. Is that wrong?

Wednesday, October 31 2012 at 3:01 AM

Tomás Senart said:

What do you suggest in order to cache CORS OPTIONS requests?

Sunday, November 4 2012 at 8:21 AM

Romain said:

Hi, thanks a lot for this blog post - a great read as usual!

I’ve been struggling with the idea of using OPTIONS to expose API requirements, which would seem to be what it’s designed for, but with the fact OPTIONS responses are not cacheable.

I’ve tried to articulate it in the following gist (too long for a comment), I’d really appreciate if you have a few seconds to let me know what you would use instead, if OPTIONS aren’t the way to go:

https://gist.github.com/rprieto/66fa68f89d9ded2e9020

Thanks Mark!

Friday, February 20 2015 at 7:35 AM