HTTP verb and response code mismatches

18 Dec 2015

Recently I ran across a web app bug that I caused by breaking a route. I had changed a match to a get in my config/routes.rb and I should have changed it to a post instead. So we fixed the bug and backfilled a routing test, etc.

The interesting thing was that we were aided in finding it by checking the logs and noticing a mismatch in the HTTP request verbs and the response codes. In this case, we found requests using the POST verb that were resulting in a 404 response code. That got us looking in the right direction.

If a client is doing a POST to a resource and getting a 404 in return, that means that the client somehow got hold of a resource identifier that is no longer there. Of course, if a client is URL hacking, that's going to happen. But in a normal day to day flow I wouldn't expect to see that. If I do, that might indicate there's either some bug in the page or perhaps a missing abstraction in an API.

The "bug in the page" case might be straightforward. We might have a list of notes on a page, and when a customer deletes one we're not removing it from the page. Then the customer attempts to update the note and gets an error. That might be a PUT or PATCH verb, but same idea.

Another more interesting scenario might be a nested parent resource that can be removed. Suppose we have projects that can have many notes and the note resource is nested under it, so creating a new note involves a POST to a URL like /projects/42/notes. If a project gets deleted while a customer is looking at a page, you could imagine a POST getting a 404 in response. That would be unpleasant, but if it only happens once in a blue moon it might not be a real problem. At the very least it would be a low-priority bug on the list to fix, though.

The API scenario is a little more open-ended. A POST to a URL with a 404 response could indicate a bug in an API client where they're just using the wrong ids. Or it could indicate a client that's just not paying attention to response codes and is iterating through a list. Depending on how much contact you have with your API consumers it might be worthy of a conversation though.

So we've established that a POST that gets a 404 should be an indicator that something's wrong. There are some other combinations that also seem like potential issues:

  • A POST with a 301 response: generally Rails responds with a 302; I checked a somewhat busy Rails app for this combination and found no hits.
  • A POST or a PUT with a 401 response: why is the client not passing the appropriate authentication credentials?
  • A POST or a PUT with a 403 response: why is the client attempting to modify a resource that it doesn't have access to? Is this a hack attempt or just a confused client?
  • Any non-GET with a 404 response seems like an avoidable issue; it's a client error, but is there anything we can do to help the client avoid stumbling into that error?

Can you think of any other combinations of verb / response code mismatches? Let me know!