in Uncategorized

Location vs. Content-Location

Here is a quick note on the purposes of and differences between Location and Content-Location response headers. The question came up several times, and more recently in Bill Burke's post on Atom too SOAPy for me.

Here is how HTTP 1.1 defines the Location header.

Location:

The Location response-header field is used to redirect the recipient to a Location other than the Request-URI for completion of the request or identification of a new resource.

The use of the Location header is straight-forward. The server can use this header when it creates new resource in response to a POST request, i.e. while returning response code 201. Or, it is can use this header to redirect the client to a different Location with one of the 3xx codes. The use of the Location header otherwise is unspecified. In particular, its use is not defined for GET.

Content-Location, on the other hand, has a much narrower usage.

Content-Location:

The Content-Location entity-header field MAY be used to supply the resource Location for the entity enclosed in the message when that entity is accessible from a Location separate from the requested resource’s URI.

The name of this header could be a bit confusing. One way to understand this is to relate it to other Content-xxx headers such as Content-Type, Content-Language, and Content-Encoding. Just like the way Content-Type header declares the media type of the entity in the response, the Content-Location header declares a URI for the entity in the response. Also note that the Content-Location header is not defined for PUT and POST.

Content-Location header is useful for content-negotiated responses when both server-driven and agent-driven negotiations are in use by the server. Here is an example.

GET /myResource
Accept: application/xml
200 OK
Content-Type: application/xml
Content-Location: http://example.org/myResource?format=xml

...

Here the server is telling the client that the same content (i.e. a variant of media type application/xml) is also available at http://example.org/myResource?format=xml at the time of the request. The client can use that URI in future to directly fetch the negotiated response. Caches can use this URI to associate the requested URI (i.e. http://example.org/myResource) to URIs of variants (such as http://example.org/myResource?format=xml), and flush those variants while flushing the resource, or to flush previously cached representation at the variant URI if that representation is stale.

Finally, neither header is meant for general-purpose linking.

Thanks to my colleague, Mark Nottingham for clarifying some of the finer points over several emails a few months ago.

Write a Comment

Comment

  1. My example was using Content-Location as a header within a multipart response of a GET and, I think, satisfies the paragraph you quoted. In fact the multipart RFC states:

    “The only header fields that have defined meaning for body parts are those the names of which begin with “Content-“. All other header
    fields may be ignored in body parts. Although they should generally
    be retained if at all possible, they may be discarded by gateways if
    necessary.”

    Its highly probable nobody has ever used Content-Location within a body part. Still, I’d much rather create and define my own headers then have to parse a heavyweight envelope format like Atom, which was my original point.

    BTW, HTTP 1.1 does not forbid using Content-Location within a PUT or POST, but it does state that the behavior is undefined.

  2. In the past I have attempted (incorrectly I assume) to use Content-Location in a POST request so the client can indicate where it would like the resource to be temporarily be addressable until it receives a server-assigned URI (in the response). The use case:
    Suppose I want to create resource A and resource B, both through POST requests (so the server can assign the URI), and I want to resource A to be have a link to resource B, and have resource B have a link to resource A (and I am assuming that the server can update the internal links if an alternate URI is used prior to receiving a server assigned URI). Is there a way to do this properly with HTTP?

    • Have you considered using PUT instead to create both A and B. A server can let PUT to create new resources when it can can "name" resources. Here is a possible flow.

      PUT /mypath/a

      <a>
      <link href="http://…/mypath/b" rel="blah"/>

      </a>

      PUT /mypath/b

      <b>
      <link href="http://…/mypath/a" rel="blah"/>

      </b>

      However, a problem with this model is that it creation of B fails, A will have a stale link to A, and so, the client will have to do another PUT to update A to remove that stale link.

      Alternatively you can you use AtomPub-style "Slug" header, but there is no guarantee (for the client, i.e.,) that the server will use that header while naming the new resource.

  3. Yes, I was aware that I could do this with PUT requests, but I wanted to defer to the server’s URI assignment (and therefore use POST). The Slug header sounds like a good idea, I don’t think a guarantee is necessary, I just wanted an unobtrusive way for the client to communicate such links when necessary. Thank you.

  4. Hi Subbu. Nice article. I have a problem regarding HTTP Request. I am trying to call a webservice through https but the response header location points to the same webservice but using http. This is causing Cross-Origin Request problem and hence the web service call fails in Chrome and Firefox. Could you please provide your suggestion on this?