Monthly Archives: October 2016

Should I PUT or should I POST? (Darling you gotta let me know)

(yes, it doesn’t rhyme however I couldn’t resist the association)

Selecting the proper methods (e.g. GET, POST, PUT, …) to use when designing HTTP based APIS is typically a subject of much debate, and eventually some bike-shedding. In this post I briefly present the rules that I normally follow when presented with this design task.

Don’t go against the HTTP specification

First and foremost, make sure the properties of the chosen methods aren’t violated on the scenario under analysis. The typical offender is using GET for an interaction that requests a state change on the server.
This is because GET is defined to have the safe property, defined as

Request methods are considered “safe” if their defined semantics are essentially read-only; i.e., the client does not request, and does not expect, any state change on the origin server as a result of applying a safe method to a target resource.

Another example is choosing PUT for requests that aren’t idempotent, such as appending an item to a collection.
The idempotent property is defined by RFC 7231 as

A request method is considered “idempotent” if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request.

Violating these properties is harmful because there may exist system components whose correct behavior depends on them being true. An example is a crawler program that freely follows all GET links in a document, assuming that no state change will be performed by these requests, and that ends up changing the system state.

Another example is an intermediary (e.g. reverse proxy) that automatically retries any failed PUT request (e.g. timeout), assuming they are idempotent. If the PUT is appending items to a collection (append is not idempotent), and the first PUT request was successfully performed and only the response message was lost, then the retry will end up adding two replicated items to the collection.

This violation can also have security implications. For instance, most server frameworks don’t protect GET requests agains CSRF (Cross-Site Request Forgery) because this method is not supposed to change state and reads are already protected by the same-origin browser policy.

Take advantage of the method properties

After ensuring the correctness concerns, i.e., ensuring requests don’t violate any property of chosen methods, we can revert our analysis and check if there aren’t any methods that best fit the intended functionality. After having ensured correctness, in this stage our main concern is going to be optimization.

For instance, if a request defines the complete state for a resource and is idempotent, perhaps a PUT is a best fit than a POST. This is not because a POST will produce incorrect behavior but because using a PUT may induce better system properties. For instance, an intermediary (e.g. reverse proxy or framework middleware) may automatically retry failed requests, and by this provide some fault recovery.

When nothing else fits, use POST

Contrary to some HTTP myths, the POST is not solely intended to create resources. In fact, the new RFC 7231 states

The POST method requests that the target resource process the representation enclosed in the request according to the resource’s own specific semantics

The “according to the resource’s own specific semantics” effectively allows us to use POST for requests with any semantics. However the fact that it allows us doesn’t mean that we always should. Again, if another method (e.g. GET or PUT) best fits the request purpose, not choosing it may mean throwing away interesting properties, such as caching or fault recovery.

Does my API look RESTful in this method?

One thing that I always avoid is deciding based on the apparent “RESTfullness” of the method – For instance, an API doesn’t have to use PUT to be RESTful.

First and foremost we should think in terms of system properties and use HTTP accordingly. That implies:

  • Not violating its rules – what can go wrong if I choose PUT for this request?
  • Taking advantage of its benefits – what do I loose if I don’t choose PUT for this request?

Hope this helps.
Cheers.

Health check APIs, 500 status codes and media types

A status or health check resource (or endpoint, to use the more popular terminology) is a common way for a system to provide an aggregated representation of its operational status. This status representation typically includes a list with the individual system components or health check points and their individual status (e.g. database connectivity, memory usage threshold, deadlocked threads).

For instance, the popular Dropwizard Java framework already provides an out-of-the-box health check resource, located by default on the /healthcheck URI of the administration port, for this purpose.

The following is an example of such representation, defined by a JSON object containing a field by each health check verification.

{
    "deadlocks":{
        "healthy":true
    },
    "database":{
        "healthy":true
    }
}

Apparently, it is also a common practice for a GET request to these resources to return a 500 status code if any of the internal components reports a problem. For instance, the Dropwizard documentation states

If all health checks report success, a 200 OK is returned. If any fail, a 500 Internal Server   Error is returned with the error messages and exception stack traces (if an exception was  thrown).

In my opinion, this practice goes against the HTTP status code semantics because the server  was indeed capable of processing the request and producing a valid response with a correct resource state representation, that is, a correct representation of the system status. The fact that this status includes the information of an error does not changes that.

So, why is this incorrect practice used so often? My conjecture has two reasons for it.

  • First, an incomplete knowledge of the HTTP status code semantics that may induce the following reasoning: if the response contains an error then a 500 must be used.
  •  Second, and perhaps more important, because this practice really comes in handy when using external monitoring systems (e.g. nagios) to periodically check these statuses. Since these monitoring systems do not commonly understand the healthcheck representation, namely because each API or framework uses a different one, the easier solution is to rely solely on the status code: 200 if everything is apparently working properly, 500 if something is not ok.

Does this difference between a 200 and a 500 matters, or are we just being pedantic here? Well, I do think it really matters: by returning a 500 status code on a correctly handled request, the status resource is hiding errors on its own behaviour. For instance, lets consider the common scenario where the status resource is implemented by a third-party provider. A failure of this provider will be indistinguishable of a failure on the system under checking, because a 500 will be returned in both cases.

This example shows the consequences of the lack of effort on designing and standardizing media types. The availability of a standard media type would allow a many-to-many relation between monitoring systems and health check resources.

  • A health check resource could easily be monitored/queried by any monitoring system.
  • A monitoring system could easily inspect multiple health check resources, implemented over different technologies.

 

monitoring

Also, by a using a media-type, the monitoring result could be much richer than “ok” vs. “not ok”.

To conclude with a call-to-action, we really need to create a media type to represent health check or status outcomes, eventually based on an already existing media type:

  • E.g. building upon the “application/problem+json” (RFC 7807), extended to represent multiple problem status (e.g example).
  • E.g. building upon the “application/status+json” media type proposal.

Comments are welcomed.