Use of Link header in requests

75 views
Skip to first unread message

Neil Brewster

unread,
May 2, 2015, 10:01:18 AM5/2/15
to api-...@googlegroups.com

We are considering the use of the RFC5988 Link header in out HTTP requests. I’m interested in the community’s thoughts on this.


The use case (minus the specific details, sorry) is as follows. The REST API in question is part of what is essentially a business logic application server that performs provisioning operations in various network elements of a customer’s network. The resources it’s acting on may reside on one of several servers in that network. The API aims to abstract this away, resolving the target server automatically.


Unfortunately, there are use cases where the server is unable to resolve the target server automatically. These are cases where legacy functionality is being used, that is incapable of the automatic resolution. They’re not intended to exist long term… but you know how it goes.


Fortunately, in these scenarios, the API client already knows the ID of the target server. This presents us with a solution: we can let the client tell us what server the resource resides on.


I’ve looked at several options, described below, and we’ve settled on the idea of having the client provide the information via a Link header. This doesn’t really seem to fit with the designed purpose of this header (as I understand it).


Alternatives:


  1. Just don’t do it. If the API is not supposed to expose the fact that resources might reside on one of several servers, then, don’t expose it.

    1. I wish this was an option for us :) It isn’t.

  2. Expose it, via the resource URI. If you’re going to expose the fact that resources may be on one of several servers, be explicit about it in the URI. So instead of:

DELETE /api/resourceType/{+resourceId}

… you have:

DELETE /api/servers/{+serverId}/resourceType/{+resourceId}

    1. This presents multiple issues. First, our long-term API design does NOT want to expose this. Further, some of our resources are composite - internally (hidden from the client), they may be composed of 2 resources on 2 totally different network elements. Putting /servers/{+serverId} in the URI limits us to allowing the client to specify the target server for only one type of network element.

  1. Expose it, via the request body.

    1. This doesn’t work for requests with no body - GET, DELETE, etc.

  2. Expose it, via a URI query parameter, e.g. add an optional “{?serverId}” on every request URI.

    1. First, to me, this just smells bad… but that’s not reason enough.

    2. Further, what this does is make every resource be addressable by more than one URI - either with, or without, the ?server parameter.

    3. It is, however, probably the simplest solution, from both the client and server perspective.

  3. Embed it in the resource ID. For example, instead of:

/api/resourceType/foo

you would have:

/api/resourceType/server1-foo

    1. This is technically possible; however, our resource IDs are server-generated, and the ID (the whole URI) is supposed to be opaque to the client. We explicitly do NOT want clients trying to gather several pieces of information and construct the resource ID for a request themselves. Thus, this option is not a viable way to enable the client to tell us what server a resource is on.

  1. Expose it, via an optional Link header on every request. So a client can optionally include, on any request, something like this:

Link: <http://api.example.com/api/network-elements/someElementType/{+serverId}>;rel="http://api.example.com/rels/someElementTypeId"

    1. This allows us a client to optionally provide this information, in any request… without compromising the long-term goals of our API design (and also without a lot of code change, which is a bonus).


What’s your gut feel, about the idea of using a Link header in the request this way? If it seems wrong to you, why - and, do you have other suggestions?


(my only other thought so far is to use an application-specific header, which we haven’t really explored, since Link headers seem to fit the bill).


Neil.


Peter Williams

unread,
May 4, 2015, 7:50:25 PM5/4/15
to api-...@googlegroups.com
A `Link` header is theoretically equivalent to just adding a link to the entity of the request. It seems rather dubious to have a `Link` header (or any other entity header, for that matter) on a bodiless request. Though it would likely work in practice, i think intermediates would be well within their rights to strip such headers.

I'd probably go with the query param because it is the easiest to implement and none of the options are particularly appealing. Ugly stuff is more likely to get cleaned up, and since this is a legacy interface you hope to eliminate it having a smell might be a feature rather than a bug.

Peter

--
You received this message because you are subscribed to the Google Groups "API Craft" group.
To unsubscribe from this group and stop receiving emails from it, send an email to api-craft+...@googlegroups.com.
Visit this group at http://groups.google.com/group/api-craft.
For more options, visit https://groups.google.com/d/optout.

Message has been deleted

Johan Groenen

unread,
May 5, 2015, 11:42:08 AM5/5/15
to api-...@googlegroups.com
For the "temporary" problem, I would suggest a "temporary" solution.

You are building an abstraction layer in which the resource location is not exposed. So what you are basically doing is making one api endpoint instead of one for each resource:

DELETE https://server1_api.yourdomain.com/<resourceType>/<resourceId>
DELETE https://server2_api.yourdomain.com/<resourceType>/<resourceId>

=>

DELETE https://generic_api.yourdomain.com/<resourceType>/<resourceId>

So I guess you can fall back on the "server1_api" solution in case you need to and afterwards remove those api locations.

A lot of work, though, and no real added value...

If you want a quick fix, just pass the serverId to the query parameters:

DELETE https://generic_api.yourdomain.com/<resourceType>/<resourceId>?serverId=101

(PS. The "smells bad" argument is not valid: it's not the solution that creates the "smell", but the restrictions created by the legacy code.)


Op zaterdag 2 mei 2015 16:01:18 UTC+2 schreef Neil Brewster:

Jeferson Daniel

unread,
May 5, 2015, 9:56:51 PM5/5/15
to api-...@googlegroups.com
The client can register a permanent/temporary resource, receive an ID and then work normally. Is that feasible?

Neil Brewster

unread,
May 15, 2015, 12:01:41 PM5/15/15
to api-...@googlegroups.com
Doh, seems I had an old filter redirecting api-craft to a folder I don't monitor. And here I thought nobody cared about my question :)

Thanks everyone for the thoughtful replies. In the end I think that either the Link header, or the idea of selecting the target server based on hostname portion of the URI, are our best choices. As much as I want this to be temporary, I can see scenarios where people want to use it in future (even when the legacy code goes away).

Thanks,
Neil.
Reply all
Reply to author
Forward
0 new messages