Sudhakar Reddy D V
Sudhakar Reddy D V

Reputation: 21

What is the location-header response body for OData actions when invoked asynchronously

I am looking at this OData spec and trying to follow - Asynchronous Requests.

As per the spec, when client polls for status using “location-header” then:

1. Success case Spec says “A GET request to the status monitor resource returns 200 OK once the asynchronous processing has completed. This response MUST include a Content-Type header with value application/http as described in [RFC7230]. The response body MUST enclose a single HTTP response which is the response to the initial Data Service Request.

Question_1: So, my understanding is the response body should return the API response parameters like below. Is my understanding correct?

Response

HTTP/1.1 OK
OData-Version: 4.0
Content-Type: application/http

{

    "Property1": "foo",
    "Property2": "bar"    
}

Question_2: Follow up for above #1: In Location Header API response, can we put:

  1. Any other useful additional params
  2. the initial API response params can be put in different format (nested object)?

Example:

locationHeaderResponse for API_1

{

    “ApiResponse” :
         {
              “api1_param1”: “value”,
              “api1_param2”: “value”
          },

     “additional useful param”: “value”       
}

locationHeaderResponse for API_2

{

    “ApiResponse” :
         {
              “api2_param1”: “value”,
              “api2_param2”: “value”
          },

     “additional useful param”: “value”       
}

2. Failure case Spec says “If an asynchronous request is cancelled for reasons other than the consumers issuing a DELETE request against the status monitor resource, a GET request to the status monitor resource returns 200 OK with a response body containing a single HTTP response with a status code in the 5xx Server Error range indicating that the operation was cancelled.

Question_3: In this case, action failed during execution bcoz of some error. So question is what is the expected response payload? Is there any standard here (or) can we send any payload telling the status ?

Example:

Response
HTTP/1.1 OK
OData-Version: 4.0
Content-Type: application/http

{

     “http status”: 5xx,
     “status”: “failed”,
     “error code”: 0x1234,
     “message”: “xyz error text message”,
     “some other param”:  “some other text” 
}

Upvotes: 2

Views: 500

Answers (1)

Michael Pizzo - MSFT
Michael Pizzo - MSFT

Reputation: 26

If you return your response as application/http, then the response body needs to be formatted as an HTTP message type according to https://www.rfc-editor.org/rfc/rfc7230, not as json. So, the wrapper would contain application/http and the body of the response would contain a full http response message including status line, response headers, content-type of application/json, etc. along with the body. Something like:

HTTP/1.1 200 OK
Content-Type: application/http

HTTP/1.1 201 CREATED
Location: myresources(10)
OData-Version: 4.0
Content-Type: application/json

{

    "Property1": "foo",
    "Property2": "bar"    
}

Or, for an error:

HTTP/1.1 200 OK
Content-Type: application/http

HTTP/1.1 5xxx
OData-Version: 4.0
Content-Type: application/json

{
     “code”: "5xx",
     “message”: “xyz error text message”
}

This was done because we needed to differentiate between the response to the status monitor (which was successful, hence the 200 response code) and the final outcome of the original asynchronous request (which could be any variety of success/failure codes). So, by returning the response body encoded as application/http, we were able to represent the full error or success response "wrapped" in the outer response.

In 4.01 we made this much simpler by saying that, if the app doesn't explicitly request application/http (for backward compatibility), you can return the final response to the status monitor using the content-type of the response to the original request (i.e., application/json) along with an AsyncResult header (https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_HeaderAsyncResult). Thus, the response is what you would have gotten if the original request had completed synchronously, except that the status code (success or failure) is in the AsyncResult header, rather than the status code of the response (which continues to be 200).

So, for, i.e., a successful create that doesn't specify Accept:application/http or specifies OData-MaxVersion 4.01 or greater, you would simply return something like:

HTTP/1.1 OK
OData-Version: 4.01
Content-Type: application/json
Location: myResource/10
AsyncResult: 201

{

    "Property1": "foo",
    "Property2": "bar"    
}

And for an error something like:

HTTP/1.1 200 OK
OData-Version: 4.01
Content-Type: application/json
AsynResult: 5xx

{
     “code”: "5xx",
     “message”: “xyz error text message”
}

I think that answers #1 and #3.

Regarding #2, if you are asking if the locationheader for the status monitor can encode additional query parameters then yes, that's fine. The location header for the status monitor should be opaque to the client and contain whatever information the service needs to get the status of the initial asynchronous request. Note, however, that the location header of the status monitor is not returned in the final response. For example, if the initial request was a create that completed successfully, then the final response contains the location header of the created resource (in the nested message in 4.0 or the top level response in 4.01).

Does that make sense? The 4.0 format is a bit confusing because it is wrapping a response within a response, but the 4.01 should be much more straight-forward.

Upvotes: 1

Related Questions