Skip to content

Commit bc38da0

Browse files
goofballLogicdlongley
authored andcommitted
Add headers and request option for node doc loader.
- Add facility for passing headers as part of the options hash for the node document loader. - Add regression test covering no options hash. - Update docs to reflect passing of headers object.
1 parent aa2cc8e commit bc38da0

File tree

4 files changed

+152
-5
lines changed

4 files changed

+152
-5
lines changed

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ test-coverage:
5353
./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- \
5454
-u exports -R $(REPORTER) $(TESTS)
5555

56+
test-local:
57+
./node_modules/.bin/mocha
58+
5659
clean:
5760
rm -rf coverage
5861

59-
.PHONY: test test-node test-browser test-local-node test-local-browser test-normalization-node test-normalization-browser test-coverage clean
62+
.PHONY: test test-node test-browser test-local-node test-local-browser test-normalization-node test-normalization-browser test-coverage test-local clean

js/jsonld.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1734,6 +1734,10 @@ jsonld.documentLoaders.jquery = function($, options) {
17341734
* false not to (default: true).
17351735
* maxRedirects: the maximum number of redirects to permit, none by
17361736
* default.
1737+
* request: the object which will make the request, default is
1738+
* provided by request.js
1739+
* headers: an array of headers which will be passed as request
1740+
* headers for the requested document. Accept is not allowed.
17371741
* usePromise: true to use a promises API, false for a
17381742
* callback-continuation-style API; false by default.
17391743
*
@@ -1743,7 +1747,8 @@ jsonld.documentLoaders.node = function(options) {
17431747
options = options || {};
17441748
var strictSSL = ('strictSSL' in options) ? options.strictSSL : true;
17451749
var maxRedirects = ('maxRedirects' in options) ? options.maxRedirects : -1;
1746-
var request = require('request');
1750+
var request = ('request' in options) ? options.request : require('request');
1751+
var acceptHeader = 'application/ld+json, application/json';
17471752
var http = require('http');
17481753
// TODO: disable cache until HTTP caching implemented
17491754
//var cache = new jsonld.DocumentCache();
@@ -1754,6 +1759,13 @@ jsonld.documentLoaders.node = function(options) {
17541759
return jsonld.promisify(loadDocument, url, []);
17551760
});
17561761
}
1762+
var headers = options.headers || {};
1763+
if( 'Accept' in headers || 'accept' in headers ) {
1764+
1765+
throw new RangeError( 'Accept header may not be specified as an option' +
1766+
'; only "' + acceptHeader + '" is supported.' );
1767+
1768+
}
17571769
return queue.wrapLoader(function(url, callback) {
17581770
loadDocument(url, [], callback);
17591771
});
@@ -1778,11 +1790,11 @@ jsonld.documentLoaders.node = function(options) {
17781790
if(doc !== null) {
17791791
return callback(null, doc);
17801792
}
1793+
var headers = { 'Accept': acceptHeader };
1794+
for( var k in options.headers ) { headers[ k ] = options.headers[ k ]; }
17811795
request({
17821796
url: url,
1783-
headers: {
1784-
'Accept': 'application/ld+json, application/json'
1785-
},
1797+
headers: headers,
17861798
strictSSL: strictSSL,
17871799
followRedirect: false
17881800
}, handleResponse);

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"jsonld"
5555
],
5656
"scripts": {
57+
"test-local": "make test-local",
5758
"test-node": "make test-node",
5859
"test-browser": "make test-browser",
5960
"test": "make test",

test/node-document-loader-tests.js

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/**
2+
* Local tests for the node.js document loader
3+
*
4+
* @author goofballLogic
5+
*/
6+
7+
var jsonld = require( "../js/jsonld" );
8+
var assert = require( "assert" );
9+
10+
describe( "For the node.js document loader", function() {
11+
12+
var documentLoaderType = "node";
13+
var requestMock = function( options, callback ) {
14+
15+
requestMock.calls.push( [].slice.call( arguments, 0 ) ); // store these for later inspection
16+
callback( null, { headers: {} }, "" );
17+
18+
};
19+
20+
describe( "When built with no options specified", function() {
21+
22+
var options = {};
23+
it( "loading should work", function( callback ) {
24+
25+
jsonld.useDocumentLoader( documentLoaderType );
26+
jsonld.expand( "http://schema.org/", callback );
27+
28+
} );
29+
30+
} );
31+
32+
describe( "When built with no explicit headers", function() {
33+
34+
var options = { request: requestMock };
35+
36+
it( "loading should pass just the ld Accept header", function( callback ) {
37+
38+
jsonld.useDocumentLoader( documentLoaderType, options );
39+
requestMock.calls = [];
40+
var iri = "http://some.thing.test.com/my-thing.jsonld";
41+
jsonld.documentLoader( iri, e => {
42+
43+
if( e ) { callback( e ); }
44+
else {
45+
46+
var actualOptions = ( requestMock.calls[ 0 ] || {} )[ 0 ] || {};
47+
var actualHeaders = actualOptions.headers;
48+
var expectedHeaders = { "Accept": "application/ld+json, application/json" };
49+
assert.deepEqual( actualHeaders, expectedHeaders );
50+
callback();
51+
52+
}
53+
54+
} );
55+
56+
} );
57+
58+
} );
59+
60+
describe( "When built using options containing a headers object", function() {
61+
62+
var options = { request: requestMock };
63+
options.headers = {
64+
65+
"x-test-header-1": "First value",
66+
"x-test-two": 2.34,
67+
"Via": "1.0 fred, 1.1 example.com (Apache/1.1)",
68+
"Authorization": "Bearer d783jkjaods9f87o83hj"
69+
70+
};
71+
72+
it( "loading should pass the headers through on the request", function( callback ) {
73+
74+
jsonld.useDocumentLoader( documentLoaderType, options );
75+
requestMock.calls = [];
76+
var iri = "http://some.thing.test.com/my-thing.jsonld";
77+
jsonld.documentLoader( iri, e => {
78+
79+
if( e ) { callback( e ); }
80+
else {
81+
82+
var actualOptions = ( requestMock.calls[ 0 ] || {} )[ 0 ] || {};
83+
var actualHeaders = actualOptions.headers;
84+
var expectedHeaders = Object.assign(
85+
86+
{ "Accept": "application/ld+json, application/json" },
87+
options.headers
88+
89+
);
90+
assert.deepEqual( actualHeaders, expectedHeaders );
91+
callback();
92+
93+
}
94+
95+
} );
96+
97+
} );
98+
99+
} );
100+
101+
describe( "When built using headers that already contain an Accept header", function() {
102+
103+
var options = { request: requestMock };
104+
options.headers = {
105+
106+
"x-test-header-3": "Third value",
107+
"Accept": "video/mp4"
108+
109+
};
110+
111+
it( "constructing the document loader should fail", function() {
112+
113+
var expectedMessage = "Accept header may not be specified as an option; only \"application/ld+json, application/json\" is supported.";
114+
assert.throws(
115+
116+
jsonld.useDocumentLoader.bind( jsonld, documentLoaderType, options ),
117+
err => {
118+
119+
assert.ok( err instanceof RangeError, "A range error should be thrown" );
120+
assert.equal( err.message, expectedMessage );
121+
return true;
122+
123+
}
124+
125+
);
126+
127+
} );
128+
129+
} );
130+
131+
} );

0 commit comments

Comments
 (0)