Please join me at my new location

Wednesday, March 25, 2009

GET Dirty!

Recently I've been working to design some RESTful APIs and I've come into a situation where it makes sense to update server state in response to a GET method. "What? Change state on a GET!? Are you mad? Are you insane? Have you even read the HTTP spec?" I hear you saying. But just hear me out, it's not as bad as you're thinking.

According to the HTTP 1.1 Specification GET is supposed to be both a safe and idempotent method, meaning that it doesn't have side effects and requesting once or a million times doesn't make any difference. So how is it that I can convince myself that it's OK to change state on a GET? Quite simply, by using a little used (in my experience) status code: 202 Accepted.

The HTTP 1.1 specification has the following to say about 202 Accepted (emphasis mine):

The request has been accepted for processing, but the processing has not been completed. The request might or might not eventually be acted upon, as it might be disallowed when processing actually takes place. There is no facility for re-sending a status code from an asynchronous operation such as this.

The 202 response is intentionally non-committal. Its purpose is to allow a server to accept a request for some other process (perhaps a batch-oriented process that is only run once per day) without requiring that the user agent's connection to the server persist until the process is completed. The entity returned with this response SHOULD include an indication of the request's current status and either a pointer to a status monitor or some estimate of when the user can expect the request to be fulfilled.

In essence, if a POST is made that returns a status code of 202 Accepted the data can be acted upon at some indeterminate time in the future. That time in the future might just so happen to be right before the GET is processed. In this way, the GET is both safe and idempotent since the state change is only tied to the GET in that it's used as a trigger for processing some previously POSTed data.