52

Our service is in 5 cities right now. If someone tries to call our service API from any other city, we want to throw this error Service not available in your area.

The question is, what is the appropriate http code would be for this error?

  • 503: Service Unavailable
  • 403: Forbidden

or something else?

Greg Burghardt
  • 34,276
  • 8
  • 63
  • 114
Shaharyar
  • 865
  • 2
  • 7
  • 12
  • This is an interesting question. I'm not sure they thought much about localization when dreaming up HTTP status codes. – Greg Burghardt Jul 12 '18 at 12:58
  • @GregBurghardt Off course they haven't. But I want to know what others have preferred in this case. Its a common scenario now a days. – Shaharyar Jul 12 '18 at 13:05
  • It probably repends on the reason why it is unavailable. Could you clarify it a bit more? – max630 Jul 12 '18 at 13:06
  • 1
    @max630 Its a ride hailing app. I hope it defines everything – Shaharyar Jul 12 '18 at 13:07
  • Is the unavailability of a service in an area driven by business constraints (you just don't have the info) or legal constraints? Do you have different subscription plans giving you access to one area but not another? – Greg Burghardt Jul 12 '18 at 14:12
  • Also, the API calls. What kind of request are they (GET, POST, PUT, DELETE)? This can make a difference too. – Greg Burghardt Jul 12 '18 at 15:19
  • On a REST service with the city being the queried entity, 404 would be the most appropriate. – Bergi Jul 12 '18 at 15:32
  • 52
    "If someone tries to call our service API from any other city" note that IP geolocation is very often wrong, if you forbid any user whose IP geolocates to a different city you will very likely be locking out legitimate users. – Peter Green Jul 12 '18 at 16:54
  • 1
    Why not simply return an empty set of results? – chrylis -cautiouslyoptimistic- Jul 12 '18 at 19:31
  • 43
    Am I not allowed to hail a ride for my child, who is in another city and needs to come to the airport in order to visit me? – Dawood ibn Kareem Jul 12 '18 at 20:01
  • 30
    While not an answer to the question, HTTP 451 (RFC 7725) may be useful to future readers who find this question. It's main purpose is to indicate content is not available due to a legal request, action, or restriction (copyright, court order, etc.) – Tyzoid Jul 12 '18 at 20:20
  • 35
    If there is nothing wrong with the network connectivity, authentication, no errors internally in the application, and syntactically valid input there shouldn't be an error message. With "we don't offer our service in this area" you've left technology issues and gone into business issues, so I'm not sure a HTTP error would be appropriate. I think you should give a 200 and (or 302 and redirect to) an appropriate message about "sorry our service isn't available in your area - yet. But we're expanding - Check back in late 2019!" or whatever the marketing dept comes up with. – ivanivan Jul 12 '18 at 21:59
  • 7
    It's unclear from the question whether you mean to block all access to the API based on the client computer's location (geo IP?) or if you're asking for the response code for a particular failed API request (e.g. book?address=123_example_st_london). Is the location part of the input, or do you have the client's location some other way? – Ben Jul 13 '18 at 05:13
  • 2
    @DawoodibnKareem You can do this. We apply this check when user sets pickup location out of our service area. Same for the dropoff. – Shaharyar Jul 13 '18 at 06:49
  • 2
    In that case, the answer is 200. Validation errors aren't generally sent as HTTP errors. I think most respondents understood your question to relate to the actual location of the client device. – Dawood ibn Kareem Jul 13 '18 at 06:53
  • I edited the question with info from the OP's comment (2 comments up from this one). This helps provide clarity to the question. – Greg Burghardt Jul 13 '18 at 15:14
  • 1
    @GregBurghardt Edits that completely invalidate all existing answers by fundamentally changing the question are forbidden. – jpmc26 Jul 14 '18 at 23:06
  • @jpmc26: I didn't mean to offend anyone. I rolled back my edit. – Greg Burghardt Jul 15 '18 at 03:38
  • To the OP: I encourage you to ask a new question with more clarity. You meant to ask about invalid input, which is usually 400. @GregBurghardt Sorry. It's not really a question of offense; it's one of practicality. The question is fairly clearly worded to ask something *different* from what the OP wanted to ask. When almost every answer was written to answer the question as asked rather than as intended and hundreds of votes have been cast on that basis, it's not really feasible to ask everyone to go back and reevaluate their actions in light of the intended question rather than the written. – jpmc26 Jul 16 '18 at 18:14
  • 2
    @ivanivan User authentication is not a "technology issue" but is based on business requirements, yet we have 401 and 403. 402 is about *payment*, which is clearly not a technology issue. HTTP status codes are clearly not limited to "technology issues," whatever that distinction means. – jpmc26 Jul 16 '18 at 18:14
  • 1
    I think a "400 Bad Request", combined with an informative JSON payload, would be the best way to represent this. – Paul Belanger Jul 30 '18 at 19:15

10 Answers10

102

Any HTTP error code would be inappropriate. There is no error or problem of any sort from an HTTP perspective so it should be something in the 200 range. You politely inform some of your users that they will not be serviced by sending back a document that tells them so. And this all goes well.

The user will not be able to use your application. That is a conscious decision made by your business logic, not a mishap. On the HTTP level everything is honky dory.

Edit

It looks like what we are looking at here is a clash of old school versus new school. When HTTP was designed, there were no web services, there was no SOAP, no JSON, no REST principles. As a protocol above TCP this was already considered (close to) application level and many high level status codes were defined. When the web started to be used for richer, high level services and a common means to transport "envelopes" was required, designers hi-jacked HTTP rather than defining a newer and cleaner protocol, just because HTTP was ubiquitous.

So in a modern web service context, HTTP is indeed little more than a dumb transport layer and most of its codes may be considered not applicable or obsolete. Just picking one because it comes close to your application state and happens to be in that list that once meant something may seem harmless, but I think it would send a wrong message. You do not want HTTP to play that regulating role in a web service context.

Martin Maat
  • 18,218
  • 3
  • 30
  • 57
  • 2
    Especially as this is an API; it would be up to the consuming application on what to display based on the response from the service called. I could see 204 "No Content".... 451 does not fit the "no problems mean 2xx" codes. – Mad Myche Jul 12 '18 at 18:18
  • +1 ... I'm not completely against finding a meaningful status code. But, it's **far more important** (IMO) to return meaningful *content.* – svidgen Jul 12 '18 at 18:54
  • 59
    By this logic, *any* application error should be returned as 200. And all requests should be POST, even deletions. This approach treats HTTP as an opaque transport protocol - like TCP. This isn't how web service APIs are usually treated - they try to leverage HTTP semantics a a standard language for APIs. Why not return 401 for Unauthorized, rather than returning 200 with a custom, nonstandard error code? – Avner Shahar-Kashtan Jul 12 '18 at 19:17
  • 32
    By this logic, no application should ever return any response in the 400 range. This is precisely the kind of condition that the 400 range of responses is for. Also, does your first sentence apply to all future answers, as well as those that were posted before yours? – Dawood ibn Kareem Jul 12 '18 at 19:59
  • 1
    @Dawood I made the first line more future proof. For a web service (API) one could make a case for 401 or 403 but it would leave the user guessing why he is not being serviced. In this web service scenario you would send back some sort of document as a response. Since this is an application level issue I would say it is most appropriate to provide feedback on the application level. – Martin Maat Jul 12 '18 at 21:06
  • 5
    @AvnerShahar-Kashtan - no, any *business logic* issue. There is no technical error anywhere - authentication, input syntax, server side processing error, etc - simply business choices. And I'm sure the marketing dept (or equiv) would love to display a message about how "we're expanding, check back in a few months" or similar. A 302 redirect to such a message, or perhaps the 451 another answer mentions with the message content changed to "we're working on getting licensed to operate in your area". – ivanivan Jul 12 '18 at 22:08
  • @MartinMaat You can provide a response body with every code except 204 and 304. So you can use an appropriate error code and give detailed reasons in the body. This is a very common practice. – jaxad0127 Jul 12 '18 at 23:50
  • 31
    I have to agree here that this is just a plain 200. The user has asked a question, we understood it, we know the right answer, and we've provided him with the answer (which happens to be "No"). All's well in HTTP land. – Lee Daniel Crocker Jul 13 '18 at 00:02
  • 8
    Hehe ... quick journey from "this isn't really an error" to *"so, you're saying nothing is ever an error?"* – svidgen Jul 13 '18 at 01:33
  • 3
    I think you're making too strict a separation between HTTP and the app. A 401 is appropriate even if it's not the web server failing to access a file on disk, but my app code needing auth to function. A 404 can mean "entity not found in DB". When we model our web service by REST principles, our URL maps to logical entity, meaning we – Avner Shahar-Kashtan Jul 13 '18 at 04:55
  • 3
    (cont) map HTTP semantics into our application. – Avner Shahar-Kashtan Jul 13 '18 at 04:56
  • 29
    This. "You tried to access a URL that doesn't exist" is very different from "Our company doesn't operate in your area". Only one has anything to do with HTTP. – CJ Dennis Jul 13 '18 at 05:20
  • 5
    There would seem to be an ambiguity in the question that is dividing people: Is the OP wanting to block access to the API itself if the user is outside the area (eg. using GeoIP), which seems to be implied by the question (in which case an alternative HTTP status code _would_ be appropriate), OR are they determining that the user is outside the area only after a _successful_ API call? From comments by the OP on the question it would seem to be the later, the API call itself is successful (200 OK), but the API has determined (from input) that they are requesting service in an unsupported area. – MrWhite Jul 13 '18 at 08:52
  • 1
    @LeeDanielCrocker By that logic the 404 status code should not exist. The user has asked for a page, we understood it, we know the right answer, and we've provided him with the answer (which happens to be "No, it doesn't exist") All's well in HTTP land. – Mayube Jul 13 '18 at 09:55
  • 3
    @Mayube ... ? ... Not all "no" responses are 404's. A 404 indicates that the requested resource could not be found. In the OP's case, taking a REST API, for example, where the client requests `/drivers`, the resource was found -- it just happens to be an empty list ... A 404 is appropriate if the client requests `/drrrivers`, which is not a valid endpoint. A 401 is appropriate if the client requests `/drivers` before authenticating. And a 403 if the client is authenticated, but banned from using the system ... There's plenty of reasons to say "no." And therefore, plenty of *ways* to say it. – svidgen Jul 13 '18 at 15:57
  • 6
    @AvnerShahar-Kashtan I'd argue you're equating them far too much. HTTP is a transport layer. Many folks would, rightly IMO, argue that a service's business/domain layer shouldn't even *know* that the HTTP protocol *exists* ... Hence, special HTTP errors for domain-level / business-rule conditions and errors just *makes no bloody sense.* – svidgen Jul 13 '18 at 16:01
  • 1
    @svidgen HTTP is more than a transport layer - more than just TCP over port 80. It's a (low level) application protocol. Using its semantics for your services allows you to leverage tools that can speak HTTP - proxies and firewalls, devops monitoring tools and client libraries. – Avner Shahar-Kashtan Jul 13 '18 at 16:10
  • 6
    @AvnerShahar-Kashtan In the domain of networking, sure, it's not a transport layer. But, in the domain of software development, it's a transport (message passing) layer. And sure, a lot of folks build the protocol into their application. I'm simply saying that many folks (myself included) would argue that doing so is suboptimal software design. The core of my application shouldn't be useful *only over HTTP.* – svidgen Jul 13 '18 at 16:31
  • @svidgen - in the world of REST apis which directly build on http semantics, that's a ridiculous argument to make. – Davor Ždralo Jul 14 '18 at 12:36
  • 1
    @DavorŽdralo REST apis are _commonly_ build on http, they don't _have_ to be and can use all kinds of other transports. Pigeons, even, that return no error code at all on your message being eaten by raptors. – gbjbaanb Jul 14 '18 at 16:24
  • @AvnerShahar-Kashtan and Martin - you're shouting over each other. What Avner is saying - that HTTP isn't just a transport layer is true but what Martin is saying is that HTTP as more than a transport layer can't express this particular issue - so it should not be handled as such. You are not actually disagreeing over anything. – Benjamin Gruenbaum Jul 14 '18 at 16:58
  • I don't think any of us was shouting, which is quite rare in these situations. :) And even if there isn't a specific HTTP error code for this scenario, you should still return *any* HTTP error code. If some errors returned an error and some errors returned 200 Success, monitoring for errors becomes meaningless. – Avner Shahar-Kashtan Jul 14 '18 at 17:00
  • @gbjbaanb - I'm not interested in arguments about spherical cows in vacuum. In reality, 100% of apis I've worked on have been built on http, period. – Davor Ždralo Jul 14 '18 at 19:11
  • 1
    This is completely and utterly wrong. In the absolute *worst* case, you can fall back to 400, which is a generic error code indicating that the user requested something not allowed. – jpmc26 Jul 14 '18 at 22:18
  • 1
    And, "So in a modern web service context, HTTP is indeed little more than a dumb transport layer and most of its codes may be considered not applicable or obsolete," is even more wrong than the first part. All of its codes are immensely useful for identifying whether a request succeeded or not. They all have clear definitions. How is this answer not downvoted to oblivion? – jpmc26 Jul 14 '18 at 22:55
  • 1
    @DavorŽdralo well, good for you but you may have to one day. REST note says that the transport mechanism is not necessarily HTTP - [it can be SOAP, or SMTP or JMS or others](https://www.w3.org/TR/2004/NOTE-ws-arch-20040211/#gwsasd), so one day you might end up writing a REST API that is not http, and if you're relying on HTTP error codes, then you're going to be doing it incorrectly. The spec itself [explicitly says the tunnel can be SOCKS](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#tab_5_2) or FTP in later example. – gbjbaanb Jul 14 '18 at 23:48
  • 1
    @CJDennis: Now consider "you are not permitted to use this service [for any arbitrary reason we decide including your location]" and suddenly it's spot on a 403 – Lightness Races in Orbit Jul 15 '18 at 15:26
  • 2
    There is a very practical reason to use a non-200 code here: a non-200 code is more likely to trigger error-checking in a client that carelessly neglected to handle the nonavailability case. – Owen Jul 16 '18 at 03:43
  • 1
    @gbjbaanb - you need some YAGNI in your life man. – Davor Ždralo Jul 16 '18 at 20:18
  • @DavorŽdralo you need to understand what http error codes are for and write your error handling properly in the first place. They're not there to represent application errors. – gbjbaanb Jul 17 '18 at 15:06
  • @gbjbaanb Like it or not, using codes to indicate that an application *server* handling an HTTP request failed to generate a response has become industry standard. Frankly, this usage is not against the spirit of the standard and is extraordinarily practical. Do you have a better mechanism for communicating that an error occurred? I've dealt with interfaces that embed errors in a 200 response, and they're much easier to get wrong. Having a *standard* to communicate an error makes dealing with errors vastly easier. Who cares whether it's your custom code or NGinx generating the response? – jpmc26 Jul 18 '18 at 22:19
  • @jpmc26 I know, but many common practices are wrong. The best way is to return a standard code (and text) in your result, which is often some json anyway. "error" in the http transport means something went wrong with the messaging,not the app. We should think of the http error codes more like exceptions, and return normal error codes when your app fails. Its certainly not a standard when you end up bodging in your custom error as a http code that almost fits. – gbjbaanb Jul 19 '18 at 14:02
  • @gbjbaanb No. That way is madness that requires custom code for every single request you send and leads to everyone doing it differently. It is vastly more practical if your request sending library can detect that something went wrong and invoke the language's standard error mechanism (perhaps optionally). Please stop pontificating about your mental image of ideal and explain what practical problems our usage of HTTP codes in this manner causes. And even speaking idealistically, the HTTP codes are defined with business logic in mind, e.g. authentication, authorization, and payment. – jpmc26 Jul 19 '18 at 18:53
  • 2
    @jpmc26 "Do you have a better mechanism for communicating that an error occurred?" There.. is... no... error. There is a response from a service that gets delivered just fine. It is like receiving a an email back in response to a question you asked. The responding email says "I know the answer, but I am not going to tell you!". The email service has no issue with the conversation and you certainly do not want it to interfere with it. You only want to hear from your smtp server if there was some kind of delivery problem, which there is not. – Martin Maat Jul 19 '18 at 19:51
  • 2
    @MartinMaat HTTP is an [application level](https://en.wikipedia.org/wiki/Application_layer) protocol. The error is that the application on the other end failed to generate the response the user wanted. HTTP knows nothing about the network; it's entirely about what the process on the other end did. It doesn't even define a code for actually failing to get *any* response because the server is supposed to decide what the code is; failed delivery means you *don't get* an HTTP code. You're talking nonsense. – jpmc26 Jul 19 '18 at 19:57
  • @jpmc26 by "application level" they mean the browser/web server. It does not mean your application running on that platform. The codes are designed with that in mind - auth (for example) was considered in terms of authorisation at the web server level, as in .htaccess or related. Some were added by "mistake" eg 402 Payment required is "reserved for future use" and not a real code thats in use. I think they thought they'd reserve it in case. It is a bit of a mess, which is all the more reason not to use them for application errors. – gbjbaanb Jul 20 '18 at 11:19
  • @gbjbaanb A web application is nothing more than an extension/customization of a web server to allow for dynamic content, so there's no problem here. And obviously, browsers are not the only possible kind of client. The point remains: delivery of the request is clearly beyond the scope of HTTP. That's the responsibility of layer 4 (e.g., TCP) and below. – jpmc26 Jul 20 '18 at 19:38
87

5xx errors are server errors - something went wrong on the server. In particular, a 503 indicates that:

the server is currently unable to handle the request due to a temporary overload or scheduled maintenance

4xx errors are client errors - the client is making a request that the server is unable or unwilling to fulfill. In particular, a 403 indicates that

the server understood the request but refuses to authorize it. A server that wishes to make public why the request has been forbidden can describe that reason in the response payload (if any). [..] However, a request might be forbidden for reasons unrelated to the credentials.

I would argue that 503 is clearly incorrect, because this isn't a temporary issue - you don't support requests in that area, period. The argument could be made that you eventually hope to support the area, but the intent of the code is to include a header indicating when the client can try again. "In 6 months" doesn't adhere to the intent.

403 is a better choice because your service simply forbids requests from certain locales.

Eric Stein
  • 3,492
  • 12
  • 19
  • 403 is for cases where access is forbidden, and the client can't do anything about it. But in this case the client can (get in the car with your laptop or phone), so 403 is inappropriate. – gnasher729 Jul 12 '18 at 22:27
  • 2
    @gnasher729 4xx errors are for things the client might be able to fix, that includes 403. The (linked) spec specifically states the client can retry with different credentials (assuming credentials were the issue). – jaxad0127 Jul 12 '18 at 23:43
  • 23
    @gnasher729 403 does not mean the human cannot do anything about it. It means the browser cannot do anything about it. The human can always do a password reset, talk to the administrator or in this case move to another city. – slebetman Jul 13 '18 at 00:45
  • 1
    @gnasher729 The client is not the user. – Captain Man Jul 13 '18 at 12:39
  • 10
    5xx = Oops our bad, hang on while we fix the problem. 4xx = We're sorry but by policy we're unable to accommodate your request at this time. Here's why.... – candied_orange Jul 13 '18 at 13:26
  • A comment by the OP has given a little more info. The use case is when the user is trying to set a pickup or dropoff location in an unsupported city. – Greg Burghardt Jul 13 '18 at 15:27
  • @CaptainMan: So if I type a bad URL into the address bar of my browser, and get a 404 Not Found error, does that mean the browser is at fault? – Greg Burghardt Jul 13 '18 at 21:02
  • @GregBurghardt If that's the case, that's a fundamentally different question than what the OP wrote, and they should have asked a new one rather than invalidate the existing answers. – jpmc26 Jul 14 '18 at 23:04
47

Neither of those.

If your API is well-designed, the URL includes the name of the city, e.g.

http://example.com/API/Vienna/HailRide

or

http://example.com/API/HailRide?city=Vienna

since IP geolocation is unreliable, your users might be using VPNs, your users might want hail a ride for someone else, etc. Suggesting a city based on the user's location is the API client's responsibility. Usually, the client has much better resources for determining the user's location anyway (for example, a mobile device's location service).

Once you've done that, the correct answer to

http://example.com/API/SomeUnsupportedCity/HailRide

or

http://example.com/API/HailRide?city=SomeUnsupportedCity

becomes obvious: 404 Not Found: No resource for hailing a ride at SomeUnsupportedCity exists.

Heinzi
  • 9,646
  • 3
  • 46
  • 59
  • 6
    This should be the accepted answer: API design is not only about complying with old numerical codes, and the scenario about vpn's etc is quite realistic. – Edoardo Jul 13 '18 at 09:18
  • 10
    I have to disagree with this. Including the name of the city in the URL could lead to all sorts of problems down the road, because it forces the client to determine a city name based on the location, and you well may not like the result. For example, are you in Los Angeles or Beverly Hills? London or Westminster? What happens if the client thinks it's in Richardson, but you want an API to serve the entire Dallas area? It would be a better idea for the client to just supply the pickup/dropoff locations; the server can determine whether they're within the service area and respond accordingly. – Zach Lipton Jul 13 '18 at 22:42
  • 11
    @ZachLipton I'm pretty sure the city names were an example only, it depends on the OP's actual business rules how they define "city" or "location". It could as well be a coordinate. – Bergi Jul 14 '18 at 08:37
  • As an alternative, 200 with an empty set of results (or 204). – chrylis -cautiouslyoptimistic- Jul 14 '18 at 20:34
  • 1
    @ZachLipton no, the point here is not having the service use client IP to understand the location, that is just wrong – Edoardo Jul 15 '18 at 20:00
  • 3
    @eddyce I agree that using the client IP is a bad idea for many reasons. I'm saying that /API/Vienna/HailRide is also prone to problems, because it requires the client to convert locations into city names, and that's not a 1-to-1 mapping that corresponds with the areas a company does business. – Zach Lipton Jul 15 '18 at 20:15
  • @ZachLipton your view might be correct, though we were not asked to (re)design his whole API - OP wanted to know what code to use: I think a lot has being said and personally I Iike this answer that shows what kind of problems they are going to face if they proceed with IP geolocation and 1 possible (non perfect) alternative. – Edoardo Jul 16 '18 at 06:32
27

This seems like a round hole/square peg question. Why does your only response need to be an HTTP code? HTTP error codes can't possibly cover all use cases.

All of your API calls should have additional messaging that comes back - i.e. a little JSON error message. Give them an 403 (because, truly they don't have the permission to use the API given the location) and return an additional bit of information as you're suggesting.

If you don't do this then next time you'll ask what HTTP error code to return when the user asked for an SUV but only a Prius is available.

stdunbar
  • 457
  • 3
  • 4
  • 5
    +1 for your last sentence. Sums it up nicely. – LoztInSpace Jul 13 '18 at 01:05
  • 1
    Well that would pretty clearly need to be 3xx redirect of some kind. ;) – Brandon Jul 13 '18 at 21:20
  • The last case probably warrants a 4xx response of some kind: the user made a request that the server can't fulfill. It'd be 400 if the choice was some kind of invalid input or 404 if the location itself just doesn't exist. Although could be 200 if it's a search criteria and there's just no matches. – jpmc26 Jul 21 '18 at 21:25
12

A few make sense.

403 Forbidden, for the reasons that Eric Stein mentions in his answer. You can use various information provided by the request to determine where the client is and who the client is and, based on that request, the server is unable or unwilling to respond.

However, I would also put forward 451 Unavailable for Legal Reasons as a possible return status for some cases. This status does expect you to include (in the headers) a link to the relevant legislation. It's specifically for cases where it is not legal for the client to be accessing your resources, and not a more general case of the client exists in an unsupported region or area.

I would avoid the 5xx series of statuses - these often indicate server side technical issues. It does not appear to be the case here.

Thomas Owens
  • 79,623
  • 18
  • 192
  • 283
  • Probably the reason in this case is that it makes no sense to tell user about cars which are not in their city. So it is not the case for 451 – max630 Jul 12 '18 at 13:37
  • 4
    @max630 You can't assume that from the question. 403 Forbidden is *most likely* the right choice. However, if there are legal restrictions on the service, the more specific 451 can be used instead. 451 is often seen as a more specific version of 403 for very particular use cases, so it makes sense to bring it up. – Thomas Owens Jul 12 '18 at 13:39
  • 8
    @max630 - it's entirely possible that 451 is appropriate here. Many jurisdictions require operators of this kind of service to be registered with regional authorities before providing the service. They could actually be legally prohibited from processing certain requests if they originate out-of-area. – Jules Jul 12 '18 at 16:47
5

If the restriction is due to legal reasons, then the appropriate HTTP error code is HTTP 451, "Unavailable due to legal reasons."

This is typically used in the case of material that has been revoked due to DMCA action or lawsuits due to harassment campaigns or the like, but the spirit and letter of the response definition states:

This document specifies a Hypertext Transfer Protocol (HTTP) status code for use when resource access is denied as a consequence of legal demands.

The code itself is a reference to Fahrenheit 451 by Ray Bradbury.

fluffy
  • 400
  • 2
  • 7
4

People often forget that HTTP status codes are extensible.

HTTP status codes are extensible. HTTP applications are not required to understand the meaning of all registered status codes, though such understanding is obviously desirable. However, applications MUST understand the class of any status code, as indicated by the first digit, and treat any unrecognized response as being equivalent to the x00 status code of that class, with the exception that an unrecognized response MUST NOT be cached. For example, if an unrecognized status code of 431 is received by the client, it can safely assume that there was something wrong with its request and treat the response as if it had received a 400 status code. In such cases, user agents SHOULD present to the user the entity returned with the response, since that entity is likely to include human- readable information which will explain the unusual status.

https://www.rfc-editor.org/rfc/rfc2616#section-6.1.1

You can always just create your own status code in the 400 range for use by your API and client application.

RubberDuck
  • 8,911
  • 5
  • 35
  • 44
  • 1
    Hmm... may not be necessary if the request included an `Expect token;city="Albequerque"` header. Then the most appropriate response would be 417, expectation failed. https://tools.ietf.org/html/rfc2616#section-10.4.18 Assuming of course that this is for a web service. – Berin Loritsch Jul 15 '18 at 12:46
  • Maybe not necessary @BerinLoritsch, but rather than try to force fit a situation into an existing code, it *may* be better to just punt and use a custom one. – RubberDuck Jul 15 '18 at 12:59
0

At first I thought 503 because the description "service unavailable" seems to align with the issue but looking at the definitions, 503 is really specific to server unavailability. Then thinking more, you are telling the client that there is a problem with the request, not that there is a server side issue.

403 is closer because you are telling the user that you received the message and understand it but that the server is unwilling to satisfy it. This might be confusing so a textual explanation can be added to describe the scenario. Per the RFC, 404 is also a valid substitute for this code.

Unless someone has dreamed up a new code for this, 403 or 404 seem to be the closest.

JimmyJames
  • 24,682
  • 2
  • 50
  • 92
  • Definitely not a 5xx code, because that implies that trying the exact same request later might succeed. A 4xx code definitely tells the client not to try again without changing at least some of the request (in this case, the "service location" field). – Toby Speight Jul 12 '18 at 15:07
0

You should match the description of the error with the code that you are giving:

  • if you say Service not available in your area. then you should give a 404 because you claim that the service is not available.

  • if you say You are not authorized for this service in your area. then you should give a 403 because you claim that the caller is not authorized.

I'd go for the second.

Edoardo
  • 236
  • 1
  • 7
  • 6
    404 is not about *availability*, it's about *existence*. Just because a service is not available in some circumstances you shouldn't provide a 404 response unless you want people to believe that it does not exist at all. A 404 response would be meaningless for this situation. – Jules Jul 12 '18 at 16:51
  • @jules According the spec for 403 (which could be out of date): "If the server does not wish to make this information available to the client, the status code *404 (Not Found) can be used instead.*" emphasis mine. So if 403 is OK, then 404 would also be, but not necessarily for the reason given. – JimmyJames Jul 12 '18 at 17:57
  • @JimmyJames - yes, it's within the specification, but is a *really bad idea* because it makes debugging problems extremely difficult. Not what you want in an API. – Jules Jul 12 '18 at 19:28
  • 3
    @Jules The service doesn't *exist* in some areas. Much like there are many small stores that only exist in my city, so asking their address in another city the correct response is "doesn't exist." – Andy Jul 13 '18 at 00:04
  • ehmm talking about "existance" about a service url path is the least - philosophical, for the sake of clarity once you publish a path you must provide an answer, 403 is the way to go in this case, with some kind of verbal description of the situation. – Edoardo Jul 13 '18 at 09:13
  • PS: the only correct answer is the one from @Heinzi adding a city parameter https://softwareengineering.stackexchange.com/a/374067/257376 – Edoardo Jul 13 '18 at 09:20
0

There's a current Internet-Draft (that will expire on December 31, 2018) that proposes amendments to the HTTP 451 Unavailable for Legal Reasons status. The draft suggests that a 451 response should contain a geo-scope-block header that should "correspond to comma-separated list of alpha-2 country codes defined in [ISO.3166-1]". However, the draft also specifies that the code 451 should not be used "by an operator to deny access to a resource on the basis of a policy specified by the operator (as opposed to a legal demand being placed on the operator)".

So assuming you don't have a legal demand for the geoblock, 451 is not the correct code. What is the correct code then? Well, numerous other answers have already suggested 403 Forbidden, but they all seem to be "opinion based", so let's see what others are doing:

So, there's no one universal solution, you are just going to have to pick one that you feel suits your situation the best. But whichever you choose, be sure to explain the actual issue in the response body.

I'd say there would be nothing wrong in just specifying a custom HTTP status code, like RubberDuck already answered. A custom status code in the 400-range might actually even be a pretty good call, because that will definitely get the developers' attention if they see something like "HTTP status 499". A "403" is too easy to pass as "OK so I got my password wrong, let's try something else instead", and that results in wasted hours.

ZeroOne
  • 956
  • 2
  • 11
  • 14