Dropbox Sparks Controversy With API Design Decision

Popular file storage and synchronization service Dropbox has sparked controversy with its decision to use the HTTP POST method with an API Endpoint.

On the Dropbox Developer Blog, F. Metsys detailed how the HTTP GET method is supposed to be used: "As a rule, HTTP GET requests should not modify server state. This rule is useful because it lets intermediaries infer something about the request just by looking at the HTTP method."

Metsys continued:

The Dropbox API tries to use GET for calls that don’t modify server state, but unfortunately this isn’t always possible. GET requests don’t have a request body, so all parameters must appear in the URL or in a header. While the HTTP standard doesn’t define a limit for how long URLs or headers can be, most HTTP clients and servers have a practical limit somewhere between 2 kB and 8 kB.

According to Metsys, this limit "is rarely a problem," but Dropbox did run into it when it was developing its /delta API endpoint, which allows developers to identify changes to files and folders in a user's Dropbox.

So what did Dropbox decide to do? "We could have somehow contorted /delta to mesh better with the HTTP worldview, but there are other things to consider when designing an API, like performance, simplicity, and developer ergonomics," Metsys explained. "In the end, we decided the benefits of making /delta more HTTP-like weren’t worth the costs and just switched it to HTTP POST."

A Controversial Decision?

Observing that HTTP, by nature, won't "fit every API perfectly," Metsys suggests, "Maybe we shouldn't let HTTP's restrictions influence our API design too much."

Such a suggestion isn't without criticism. As programmer Evert Pot sees it, Dropbox's decision represents "poor API design." On his blog, he explains, "Switching to POST discards a number of very useful features. ... POST is defined as a non-safe, non-idempotent method. This means that if a POST request fails, an intermediate (such as a proxy) cannot just assume they can make the same request again. It also ensures that HTTP caches no longer work out of the box for those requests."

According to Pot, Dropbox could have looked at using the REPORT HTTP method, which, while not well-known, is safe and idempotent, and can contain a request body. Alternatively, Pot suggests that Dropbox could have created two endpoints: a POST endpoint for submitting queries and a GET endpoint for retrieving query results. Although Pot acknowledges that this is "a bit more complicated," he argues that "REST services are not meant to be simple. They are meant to be robust and long-lasting, just like the web itself."

On Hacker News, Pot found some support. Calling Pot's alternative approach "pretty clever," one commenter noted, "If the query result is [its] own Resource, you get async for free (the POST can return the URI it will be at before it's ready), the server can cache the result indefinitely if wanted, and the client can treat the API as an immutable dataset."

But by and large, commenters sided with Dropbox. Some noted that use of the REPORT HTTP method, because of its obscurity, would simply confuse developers. "We use POST when we need to because it's an understood solution. I really wish we had a better option," one commenter wrote. Another chimed in, "While I really like my REST, I see why you'd use POST in this case."

That last comment explains why, as Steve Klabnik observed, "99.99% of the RESTful APIs out there aren’t fully compliant with Roy Fielding’s conception of REST." Of course, the questionable use of an HTTP method or the failure to comply with the HATEOAS constraint is often intentional, the result of a need to balance technical perfection with usability. APIs are used by software applications, but they're developed and integrated by people, and as long as that is the case, API providers like Dropbox will inevitably find themselves in situations that call for potentially controversial API design decisions.

Be sure to read the next API Design article: Docker Extends API Reach via SocketPlane Acquisition