1

REST API: how to notify a client that the request has failed when the service already returned 200 and some data?

What I am doing? I am developing a REST Web service that returns data from two sources:

  1. An CSV file from an HTTP server which changes often and sometimes is huge.
  2. A local file.

When a client invokes the service, it does this:

  1. It sends a request to the HTTP server to obtain the CSV file.
  2. After obtaining the CSV file, it combines the data from both sources.
  3. Sends the result to the client. The result is an XML document.

Problem Sometimes, after I have already returned some data to the client, the HTTP server fails so I cannot continue sending data to the client. When this happens, I would like to notify the client that there was an error. How should I do this? The service already returned the HTTP code 200 and some data. So I cannot send the client an error 500.

Should I simply write to the output an error message? The client will fail because it the XML-document will not be valid.

The service cannot wait to send the response until the entire file from the HTTP server is read. The reasons is that sometimes the file obtained from the HTTP is very big and does not fit in memory.

Environment: although I do not think this is important, this service is developed in Jersey 1.x.

Montecarlo
  • 1,239
  • 1
  • 11
  • 24
  • 1
    If you really can't figure it out before hand, I'd suggest that you just stop streaming your XML response. From the client's perspective this looks like the connection was lost before the full response could be received. Since it's XML, they will know. – WW. Apr 28 '15 at 00:45

2 Answers2

1

As you say, there are a couple options:

  • Start sending the response 200 OK before your upload request is complete, but rely on the client to detect an invalid ontent response; or
  • Wait until your request file upload is complete before sending the HTTP response. Then you can send the correct status code (2xx or 500).

I would recommend waiting until the upload is complete.

If the file cannot fit in server-side memory, then find a technique to write the stream to persistence not in memory, such as a cache, nosql db, or the filesystem. This will allow for faster processing of the file upload.

If you require additional time to process the file on the server side after upload, you can return a 202 Accepted status, with the Location: header having the resource to the long-running job. The client can keep checking if the job is complete. This will avoid having to process the whole thing in one HTTP round-trip.

some good examples of using RESTful long-operations:

Community
  • 1
  • 1
Raul Nohea Goodness
  • 2,549
  • 23
  • 24
  • thanks. Finally I will go with the first option: send 200 and rely on the client to detect an invalid content response. The idea of writing the stream to persistence is good, but in my scenario is not worth the effort. – Montecarlo May 05 '15 at 21:18
0

Replying to myself. This may be useful for someone else.

Initially, I developed this option: if there was an error generating the output of the service when the HTTP code 200 was already sent, the service would write the error message to the output and close the connection. In these cases, the XML of the response was invalid.

Later, I had to change this behavior because users complained that in this scenario, the response was an invalid XML. As a consequence, all they were seeing was the error returned by the XML parser of their applications saying that the XML was invalid, not the actual error message.

To avoid this issue, I changed the behavior of the service:

When there are no errors, the response looks like this:

<view name="demo_stats">
    <demo_stats>
        <int_type>1</int_type>
        <numeric_type>1.1</numeric_type>
    </demo_stats>
    <demo_stats>
        <int_type>2</int_type>
        <numeric_type>2.2</numeric_type>
    </demo_stats>
</view>

If there is an error generating the output of the service and the service already sent the HTTP code 200, the response looks like this:

<view name="demo_stats">
    <demo_stats>
        <int_type>1</int_type>
        <numeric_type>1.1</numeric_type>
    </demo_stats>
    <demo_stats>
        <int_type>2</int_type>
        <numeric_type>2.2</numeric_type>
    </demo_stats>
    <errors>
        <error>There was an error transforming the value of row #3</error>
    </errors>
</view>

The element errors is optional and only appears when there is an error during the generation of the output. This is a valid XML document and it allows client application to control better for this situation.

Montecarlo
  • 1,239
  • 1
  • 11
  • 24