resthateoas

HATEOAS: absolute or relative URLs?


In designing a RESTful Web Service using HATEOAS, what are the pros and cons of showing a link as

  1. a complete URL. e.g. http://server:port/application/customers/1234
  2. just the path. e.g. /application/customers/1234

?


Solution

  • There is a subtle conceptual ambiguity when people say "relative URI".

    By RFC3986's definition, a generic URI contains:

      URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
    
      hier-part   = "//" authority path-abempty
                  / path-absolute
                  / path-rootless
                  / path-empty
    
         foo://example.com:8042/over/there?name=ferret#nose
         \_/   \______________/\_________/ \_________/ \__/
          |           |            |            |        |
       scheme     authority       path        query   fragment
    

    The tricky thing is, when scheme and authority are omitted, the "path" part itself can be either an absolute path (starts with /) or a "rootless" relative path. Examples:

    1. An absolute URI or a full URI: "http://example.com:8042/over/there?name=ferret"
    2. And this is a relative uri, with absolute path: /over/there
    3. And this is a relative uri, with relative path: here or ./here or ../here or etc.

    So, if the question was "whether a server should produce relative path in restful response", the answer is "No" and the detail reason is available here. I think most people (include me) against "relative URI" are actually against "relative path".

    And in practice, most server-side MVC framework can easily generate relative URI with absolute path such as /absolute/path/to/the/controller, and the question becomes "whether the server implementation should prefix a scheme://hostname:port in front of the absolute path". Like the OP's question. I am not quite sure about this one.

    On the one hand, I still think server returning a full uri is recommended. However, the server should never hardcode the hostname:port thing inside source code like this (otherwise I would rather fallback to relative uri with absolute path). Solution is server-side always obtaining that prefix from HTTP request's "Host" header. Not sure whether this works for every situations though.

    On the other hand, it seems not very troublesome for the client to concatenate the http://example.com:8042 and the absolute path. After all, the client already know that scheme and domain name when it send the request to the server right?

    All in all, I would say, recommend to use absolute URI, possibly fallback to relative URI with absolute path, never use relative path.