What is a RESTful way to check if a client can access a resource?

I am trying to determine the best practice in the REST API to determine if a client can access a specific resource. Two quick scenarios:

Phone book search service. The client looks at the phone number, for example, referring to. GET http://host/directoryEntries/numbers/12345
... where 12345 is the phone number that can be found in the directory. If it exists, it will return information such as the name and address of the person whose phone number.

Video format transfer service. The client sends the video in one format, for example. POST http://host/videos/
... and receives the "video GUID" that was generated by the server for this video. Then the client checks, for example.
GET http://host/videos/[GUID]/flv
... to get video converted to FLV format if a converted version exists.

You will notice that in both cases above I did not mention what should happen if the resource being checked does not exist. This is my question here. I read in various other places that the correct RESTful way for a client to check if a resource exists here is to call HEAD (or possibly GET ) on the resource, and if the resource does not exist, it should expect a 404 response. That would be nice , except that 404 is widely regarded as a “mistake”; the HTTP / 1.1 specification states that the 4xx status code class is designed for cases where the client seems to be wrong. But wait; in these examples, the client probably was not mistaken. He expects that he will be able to return 404 (or others, perhaps 403, if he does not have access to this resource), and he was not mistaken in requesting the resource. 404 is not intended to indicate an “error condition”, it is simply information - “this does not exist”.

And browsers behave as the HTTP spec indicates, as if the 404 response is a genuine error. Both the Google Chrome console and Firebug cause a large red “404 Not Found” error message in the Javascript console every time a 404 is received by an XHR request, regardless of whether it was processed by the error handler or not, and there is no way to disable it. This is not a problem for the user, because they do not see the console, but as a developer I do not want to see a bunch of 404 errors (or 403, etc.) in my JS console, when I know perfectly well that they are not errors, and the information is processed my javascript code. This is linear noise. In the second example that I gave, it is linear noise to the extreme, because the client will most likely poll the server for this /flv , as it may take some time to compile, and the client wants to display "not compiled" yet gets non-404. A 404 error may appear that appears in the JS console every second or two.

So, is this the best or most correct way that we have with REST to check for a resource? How do we get around line noise in the JS console? It is possible that in my second example, another URI may be requested to check the compilation status, for example:
GET http://host/videos/[GUID]/compileStatus
... however, this seems to violate the REST principle a bit; you do not use HTTP completely and paying attention to HTTP headers, but instead create your own protocol by which you return information in the body telling you what you want to know, and always return HTTP 200 to close the browser. It was serious criticism of SOAP - it tries to "get around" HTTP, rather than using it fully. According to this principle, why should you ever return a 404 status code? You can always return 200 - of course, 200 indicates that information about the status of the resource is available, and status information tells you what you really wanted to know - the resource was not found. Of course, the RESTful path should be to return a 404 status code.

This mechanism seems even more invented if we apply it to the first of the above examples; the client may request:
GET http://host/directoryEntries/numberStatuses/12345
... and, of course, get 200; there is information about the status of number 12345 and reports ... that the number was not found in the directory. This would mean that ANY number queried would be "200 OK", although it might not exist - does it look like a good REST interface?

Am I missing something? Is there a better way to determine if a RESTfully or HTTP resource exists, is possibly being updated to indicate that non-2xx status codes need not be considered “errors” and are merely information? Should browsers be configured to not always display non-2xx status responses as “errors” in the JS console?

PS. If you read this, thanks .; -)

+6
source share
4 answers

I think you have changed the semantics of the request. With a RESTful architecture, you are requesting a resource. Therefore, a request for a resource that does not exist or is not found is considered an error.

I use:

  • 404 if GET http://host/directoryEntries/numbers/12345 does not exist.

  • 400 is really a bad request 400 Bad Request

Perhaps in your case, you might think about searching instead. Searches are performed with query parameters in the resource collection.

What do you want GET http://host/directoryEntries/numbers?id=1234 Which will return 200 and an empty list if they do not exist or a list of matches.

+2
source

It is entirely possible to use 404 to indicate that a resource was not found. Some quotes from the book "RESTful Web Services" (a very good book about REST by the way):

404 indicates that the server cannot match the client URIs with the resource. [...] The web service can use the 404 response as a signal to the client that the URI is "free"; the client can then create a new resource by sending a PUT request to this URI. Remember that 404 may be a lie to hide 403 or 401. It may be that the resource exists, but the server does not want the client to know about it.

Use 404 when the service cannot find the requested resource, do not abuse the indication of errors that are actually not related to the existence of the resource. In addition, a client can “request” a service to find out if this URI is free or not.

Performing lengthy operations such as encoding video files

HTTP has a synchronous request-response model. The client opens the Internet socket to the server, executes its request and saves the socket until the server sends a response. [...]

The problem is not that all operations can be completed in a time when we expect an HTTP request. Some operations take hours or days. An HTTP request would undoubtedly be disconnected after this kind of inaction. Even if this is not the case, who wants to keep the socket open for several days just waiting for a server response? Is there a way to operate asynchronously via HTTP?

Exists, but this requires that the operation be divided into two or more synchronous requests. The first request generates an operation and subsequent requests allow the client to find out about the status of the operation. The secret is status code 202 (Accepted).

So, you can do POST /videos to create a video encoding task. The service will accept the task, respond with 202, and provide a link to a resource describing the state of the task.

 202 Accepted Location: http://tasks.example.com/video/task45543 

The client can request this URI to see the status of the task. When the task is completed, the resource view will be available.

+4
source

IMO client really made a mistake in requesting a nonexistent resource. In both examples, the service can be designed differently, so the error can be avoided on the client side. For example, in the video conversion service, as the GUID has already been assigned, the message body in video / id may contain a flag indicating whether the conversion was performed or not.

Similarly, in the phone book example, you are looking for a resource, and this can be handled with something like / numbers /? search_number = 12345, etc., so that the server returns a list of relevant resources, which can then be requested further.

Browsers are designed to work with the HTTP specification, and showing an error is a genuine answer (very useful). However, you need to think of your Javascript code as a separate object from the browser. So you have a Javascript REST client that knows what a service is and a browser that is dumb regarding your service.

In addition, REST in theory is protocol independent. HTTP is the most common protocol that uses REST. Another example I can think of is an Android content provider whose design is RESTful, but not HTTP dependent.

+2
source

I just saw GET / HEAD requests return 404 (Not Found) when the resource does not exist. I think that if you just try to get the status of a resource, the chapter request will be fine, since it should not return the body of the resource. Thus, you can distinguish between queries in which you are trying to find a resource and queries where you are trying to verify their existence.

http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

Edit: I remember reading about an alternative solution, adding a header to the original request, which indicated how the server should handle 404 errors. Something similar to 200 response, but empty body.

0
source

Source: https://habr.com/ru/post/913790/


All Articles