Skip to content

Commit

Permalink
RFC 5988 compatible Link header parsing
Browse files Browse the repository at this point in the history
The hateoas interceptor now parses Link response headers indexing them
under response.links. Multiple Link headers are supported.

The value of the Link header must match the grammar defined in rfc5988. If
the grammar is incompatible, the link is skipped.

http://tools.ietf.org/html/rfc5988

PEG.js (http://pegjs.majda.cz/) is used to generate the parser for the
rfc defined grammer. The generated parser is wrapped in UMD and checked
into the repo to avoid a run/build-time dependency on PEG.js.
  • Loading branch information
scothis committed May 7, 2013
1 parent 1cd6c35 commit 24a35c2
Show file tree
Hide file tree
Showing 9 changed files with 1,387 additions and 33 deletions.
1 change: 1 addition & 0 deletions .jshintignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules
parsers
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ Change Log
----------

.next
- nothing yet
- parsing 'Link' response headers in hateoas interceptor (rfc5988)

0.9.1
- add Node 0.10 as a tested environment
Expand Down
2 changes: 2 additions & 0 deletions docs/interceptors.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@ Links are index in two ways:
1. as link's `rel` which when accessed issues a request for the linked resource. A promise for the related resource is expected to be returned.
2. as link's `rel` with 'Link' appended, as a reference to the link object.

The 'Link' response header is also parsed for related resources following rfc5988. The values parsed from the headers are indexed into the response.links object.

Also defines a `clientFor` factory function that creates a new client configured to communicate with a related resource.

The client for the resource reference and the `clientFor` function can be provided by the `client` config property. This method is also useful if the request for the resource
Expand Down
25 changes: 24 additions & 1 deletion interceptor/hateoas.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@

define(function (require) {

var interceptor, pathPrefix, cycleFlag;
var interceptor, pathPrefix, rfc5988LinkParser, cycleFlag;

interceptor = require('../interceptor');
pathPrefix = require('./pathPrefix');
rfc5988LinkParser = require('../parsers/rfc5988');

cycleFlag = '__rest_hateoas_seen__';

Expand All @@ -31,6 +32,10 @@
* 2. as link's 'rel' with 'Link' appended, as a reference to the link
* object
*
* The 'Link' response header is also parsed for related resources
* following rfc5988. The values parsed from the headers are indexed
* into the response.links object.
*
* Also defines a 'clientFor' factory function that creates a new
* client configured to communicate with a related resource.
*
Expand Down Expand Up @@ -113,6 +118,24 @@
delete obj[cycleFlag];
}

function parseLinkHeaders(headers) {
var links = [];
[].concat(headers).forEach(function (header) {
try {
links = links.concat(rfc5988LinkParser.parse(header));
}
catch (e) {
// ignore
// TODO consider a debug mode that logs
}
});
return links;
}

if (response.headers && response.headers.Link) {
response.links = response.links || {};
apply(response.links, parseLinkHeaders(response.headers.Link));
}
walk(response);

return response;
Expand Down
9 changes: 9 additions & 0 deletions parsers/_template.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
(function (define) {
define(function (require, exports, module) {

// pegjs output goes here

});
}(
typeof define === 'function' && define.amd ? define : function (factory) { factory(require, module.exports, module); }
));
Loading

0 comments on commit 24a35c2

Please sign in to comment.