HTTP status code for a partial successful request
Asked Answered
R

6

163

I have an application that sends messages to users. In a POST request, an XML string is transferred that consists of all the users that should receive that particular message. If any of the users in the list do not exist I give the list of missing users back to the client for further evaluation.

Now I'm asking myself what would be the proper status code for the application saying that the request was accepted but there were things that couldn't be done.

The problem would be avoided if it weren't allowed to include missing users in the list. Then the sending attempt would just get an 4xx error. But there is no point in forming the API this way. On the other hand, I could consider the error condition to be purely application-specific. But sending a 200 just does not feel right. And it would be nice to give the client a hint when to look deeply into the error response. e.g. to avoid sending messages to users over and over.

Renfrew answered 12/12, 2011 at 10:33 Comment(0)
J
101

I've dealt with a very similar issue. In this case, I returned a

207 Multi-Status

Now, this isn't strict HTTP, it's part of the WebDAV extension, so if you don't have control over the client too, then this isn't good for you. If you do, you could do something like so:

   <?xml version="1.0" encoding="utf-8" ?>
   <D:multistatus xmlns:D='DAV:'>
     <D:response>
       <D:user>user-123</D:user>
       <D:status>success</D:status>
     </D:response>
     <D:response>
       <D:user>user-789</D:user>
       <D:status>failure</D:status>
     </D:response>
   </D:multistatus>

But again, this is an HTTP extension, and you need to have control of the client as well.

Jolo answered 12/12, 2011 at 13:5 Comment(6)
I thought about using this but I wasn't quite comfortable with it. Thanks!Renfrew
The nice thing about it is that you can return as much or little of pertinent data as you want - which is especially useful for mixed-data sets, i.e.: where some fail and some pass.Jolo
I understand. I'm just trying to avoid an extra level of status handling (which is not nice IMHO). Most of my code works with HTTP ones. And I think my described use case will do fine without.Renfrew
You can always send a body back - send a 200 with a JSON response or whatever you want in it to determine which ones were successful.Jolo
Yes, I know. But if you return a body you need to parse it. And at that moment you introduce a second layer of application logic handling. This raises complexity and you need a good reason to do it then.Renfrew
207 Status Code ReferenceSingh
A
91

I've had the same problem, and I've ended up using two different solutions:

  • HTTP return code 202: Accepted, indicating that the request was ok, but there's no guarantee everything actually went as it should.
  • Return a normal 200 in the response, but include a list of what didn't pan out in the response body.

The second one usually works best, but the first one is great if you're lazy or use a queue for processing.

Asir answered 7/4, 2014 at 12:6 Comment(3)
Isn't 202 referring more to something like queueing?Sourpuss
Yes, @Sinaesthetic. From the most recent HTTP 1.1 spec, "(...) the request has been accepted for processing, but the processing has not been completed". So, for partial success, 202 is not appropriate.Boland
IMO 200 explicitly allows for partial success as the intended meaning of the payload is specified as status for POST, PUT and DELETE. tools.ietf.org/html/rfc7231#section-6.3.1 Status 202 is successful start of an asynchronous call whose result is not known yet. Similar to getting a promise/future. The response should tell how to get the actual result or at least monitor the status.Pessimism
R
5

I needed the same issue and after reading a bit of the documentation, the best solution to this problem seems to respond with an non-standard 2xx response. A generic client will treat this as success but a specific client can understand what has happened. You may also support this with custom headers in form X-failed: thispart code. You probably should include what is the problem with the operation as text so that generic clients will be able to display nature of what has happened. Here is what I have done where a file is uploaded but the processing cannot be done at this moment:

HTTP/1.1 210 Partial success
X-failed: processing
X-reason: server busy

File has been uploaded, however, the task associated with the 
file has not started as the server is busy. Re-request processing
at a later time.
Ramiform answered 14/5, 2022 at 11:55 Comment(0)
L
5

I agree with accepted answer from Kylar but I found it a bit confusing since the answer is talking about webdav and XML. The OP asked about XML, but hopefully this help someone with json.

HTTP/1.1 207 Multi-Status
Content-Type: application/json

{
  "results": [
    { "id": 1, "status": "created" },
    { "id": 2, "status": "failed", "error": "email address not valid"},
    { "id": 3, "status": "failed", "error": "user does not exist" },
    { "id": 4, "status": "created" }
  ]
}
Leuctra answered 7/7, 2023 at 8:19 Comment(0)
D
-8

What about using 206 Partial Content. I know 206 is more about ranges, but what if it could indicate a partially successfully request?

Demonize answered 16/2, 2019 at 20:56 Comment(2)
MDN states as follows: "The HTTP 206 Partial Content success status response code indicates that the request has succeeded and has the body contains the requested ranges of data, as described in the Range header of the request." As far as I understand, 206 Partial Content is strictly for requests with a content range.Grain
The W3C RFC doc also specifies that 206 is for a partially-fulfilled GET request, not POST. The server has fulfilled the partial GET request for the resource. The request MUST have included a Range header field (section 14.35) indicating the desired range, and MAY have included an If-Range header field (section 14.27) to make the request conditional. w3.org/Protocols/rfc2616/rfc2616-sec10.htmlElisabeth
J
-14

The HyperText Transfer Protocol deals with the transmission side of things. It doesn't have error codes to deal with application level errors.

Returning 200 is the right thing to do here. As far as HTTP is concerned the request was received properly, handled properly and you're sending the response back. So, on the HTTP level everything is OK. Any errors or warnings related to the application which running on top of http should be inside the response. Doing so will also prevent some nasty issues you might run into with proxy servers which might not handle certain responses the way you expect.

Jimenez answered 12/12, 2011 at 10:54 Comment(9)
HTTP is an application level protocol. You cannot put it simply on transport and application level. If you think about OSI then HTTP is on layers 5-7. HTTP is somewhat different. Most of the headers and return codes are indeed application specific. The codes just depend on the information given in the HTTP protocol entities and not on custom application format things. Regarding the 200 I would say that your definition is purely wrong if it is applied to verbs not being POST. But POST changes the game a little bit and in this context your assumption "handled properly" is not sure, eitherRenfrew
Stricly speaking OSI considers HTTP a application level protocol and when talking to a 'normal' webserver this is true. But in your case you are running your own protocol on top of HTTP, like lots of applications do these days. In that type of usage HTTP just provides the transport. (Your application is sending messages to users, not transferring hypertext...)Jimenez
Just to be clear. HTTP in a REST way is resource centric. In this context 200 means identity (the resource you specified) instead of 3xx which points in direction of the identity. Using POST turns the resource URI into a processing URI and there error codes need to cope with that. The context shifts a bit and the defintion of things get a bit blurry or at least hard to understandRenfrew
The context shift also means there are no suitable error codes, since the protocol was never designed with that context in mind ;-) I also think you should be careful with using error codes since proxy servers tend to run with them replacing your response with a custom error page, this can be a real PITA.Jimenez
Where is the difference between sending messages and transferring hypertext? These are just invocations of the entity(URI) with a verb(http method) and meta-data(headers etc.). It becomes hypertext when you add the corresponing Content-Type header otherwise there is no single difference.Renfrew
I think the error codes are still suitable if you are using POST. It is just a lot harder not to make mistakes about the context your are serving. So I'm still not convinced what is the best thing to do :) But I'm sure I won't weaken my own software just to cover the broken behaviour of a proxy.Renfrew
Anyway, thanks for answering my question. I just discovered stackoverflow is bad chat client :)Renfrew
Technically TCP is the protocol that deals with the transmission of things. HTTP can be and should be used well to indicate and understand the response if an API. a 200 with an error code is not of much use. As its specifically part of the OK responses suggested by the HTTP RFC.Garzon
HTTP is the "application" only with respect to the TLS over TCP/IP "transport". To the REST service "application" (or a web UI or ...), HTTP(S) can be considered a transport. Mapping HTTP methods and response codes to application semantics is always an approximation. REST provides a set of guidelines for that mapping. But application designers can and should diverge from these guidelines when necessary to deliver on application requirements.Fantasist

© 2022 - 2024 — McMap. All rights reserved.