4

We are trying to build a REST interface that allows users to test the existence of a specific resource. Let's assume we're selling domain names: the user needs to determine if the domain is available.

An HTTP GET combined with 200 and 404 response codes seems sensible at first glance.

The problem we have is discriminating between a request successfully served by our lookup service, and a request served under exceptional behaviour from other components. For example:

  1. 404 and 200 can be returned by intermediary proxies that actually block the request. This can be due to proxy misconfiguration, or even external infrastructure such as coffee shop Wifi using poor forms-based authentication.

  2. Clients could be using broken URLs. This could occur through deprecation or (again) by misconfiguration. We could combat the former through 301, however.

What is the current best practice for discriminating between responses that have been successfully fulfilled against the client's intention for that request, and responses served through exceptional behaviour?

The problem is eliminated by tunnelling responses through the response body, as we can ensure these are unique to our service. However, doesn't seem very RESTful!

Lawrence Wagerfield
  • 6,471
  • 5
  • 42
  • 84

2 Answers2

2

Simply have your application add some content to its HTTP responses that will distinguish them from the responses thrown by intermediaries. Any or all of these would work:

  • Information about the error in the response content that is recognizable as your application's content (for example, Application error: Domain name not found (404))
  • A Content-Type header in the response that indicates that the response content should be decoded as an application error (for example, Content-Type: application/vnd.domain-finder.error+json)
  • A custom header in the response that indicates it is an application error

Once you implement a scheme like this, your API clients will need to be aware of the mechanism you choose if they want to react differently to application errors versus infrastructure errors, so just document it clearly.

Brian Kelly
  • 19,067
  • 4
  • 53
  • 55
  • Thanks for the suggestions - I hadn't thought of the last two (we were also considering using sub status codes!). However, all these approaches make the HTTP status code redundant to our client, as it will only need to check one of the above mechanisms. This begs the question: if we're not using the HTTP status code to drive our application's logic, then what's the point in using them at all? Who is genuinely going to benefit? – Lawrence Wagerfield Apr 25 '14 at 08:53
  • IMO you should still use them because response codes are extremely helpful if they're accurate (especially in log analysis, operational tools, etc). It's tempting to want to fall into the trap of "return 200 OK each time and stuff the error into the response" but then you'll be taking the SOAP approach. Plus you'll force every REST API client programmer out there to adapt to your model rather than use the existing standard techniques with which they're already familiar. – Brian Kelly Apr 25 '14 at 10:51
  • Good point regarding log analysis. However, I believe your last point is moot: your answer already establishes that clients can only determine an accurate result by checking the content-type/body/whatever, meaning the service has no reason (other than for log analysis) to return a status code. – Lawrence Wagerfield Apr 25 '14 at 12:50
  • Not quite: if I was writing a client I would check for an error code first, and if I found a 400- or 500-range code I would then check the response body to determine if it was an application error or something thrown by an intermediary. However if you force me as a client to *always* check the response body, my code will get ugly. REST API clients can be written more cleanly if 200-range codes really mean "success", because some client helper libraries have handlers that allow you to focus "try-catch" style on success, and not always checking for failure with each call. – Brian Kelly Apr 25 '14 at 14:07
0

I tend to follow the "do what's RESTful as long as it makes sense" line of thinking.

Let's say you have an API that looks like this:

/api/v1/domains/<name>/

Hitting /api/v1/domain/exists.com/ could then return a 200 with some whois information.

Hitting /api/v1/domain/doesnt.com/ could return a 404 with links to purchase options.

That would probably work. If the returned content follows a strict format (e.g. a JSON response with a results key) then your API's responses can be differentiated from your proxies' responses.

Alternatively, you could offer

/api/v1/domains/?search=maybe
/api/v1/domains/?lookup=maybe.com

This is now slightly less RESTful but it's still self-describing and (in my opinion) not that bad. Now every response can be a 200 and your content can reveal the results.

WilliamMayor
  • 745
  • 6
  • 15