Skip to content
This repository was archived by the owner on Feb 5, 2020. It is now read-only.

Commit 3096dec

Browse files
committed
Use XMLHttpRequest instead of jQuery.
1 parent d194260 commit 3096dec

File tree

2 files changed

+47
-32
lines changed

2 files changed

+47
-32
lines changed

lib/browser/.eslintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
globals: {
3-
jQuery: true,
3+
XMLHttpRequest: true,
44
},
55
}
66

lib/browser/Request.js

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*! @license MIT ©2013-2016 Ruben Verborgh - Ghent University / iMinds */
2-
/* Single-function HTTP(S) request module for browsers using jQuery */
2+
/* Single-function HTTP(S) request module for browsers */
33

44
var EventEmitter = require('events').EventEmitter,
55
AsyncIterator = require('asynciterator'),
@@ -9,57 +9,72 @@ var EventEmitter = require('events').EventEmitter,
99
require('setimmediate');
1010

1111
// Headers we cannot send (see https://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader()-method)
12-
var UNSAFE_REQUEST_HEADERS = ['accept-encoding', 'user-agent', 'referer'];
13-
// Headers we need to obtain
14-
var RESPONSE_HEADERS = ['content-type', 'content-location', 'link', 'memento-datetime'];
12+
var UNSAFE_REQUEST_HEADERS = _.object(['accept-encoding', 'user-agent', 'referer']);
1513

1614
// Resources that were already time-negotiated
1715
var negotiatedResources = Object.create(null);
1816

1917
// Creates an HTTP request with the given settings
2018
function createRequest(settings) {
21-
var request = new EventEmitter();
22-
2319
// PERFORMANCE HACK:
2420
// Reduce OPTIONS preflight requests by removing the Accept-Datetime header
2521
// on requests for resources that are presumed to have been time-negotiated
2622
if (negotiatedResources[removeQuery(settings.url)])
2723
delete settings.headers['accept-datetime'];
2824

29-
// Delegate the request to jQuery's AJAX module
30-
var jqXHR = jQuery.ajax({
31-
url: settings.url,
32-
timeout: settings.timeout,
33-
type: settings.method,
34-
headers: _.omit(settings.headers, UNSAFE_REQUEST_HEADERS),
35-
});
36-
// Emit the result as a readable response iterator
37-
jqXHR.then(function () {
38-
var response = AsyncIterator.single(jqXHR.responseText || '');
39-
response.statusCode = jqXHR.status;
40-
response.headers = _.object(RESPONSE_HEADERS, RESPONSE_HEADERS.map(jqXHR.getResponseHeader));
41-
request.emit('response', response);
25+
// Create the actual XMLHttpRequest
26+
var request = new XMLHttpRequest(), reqHeaders = settings.headers;
27+
request.open(settings.method, settings.url, true);
28+
request.timeout = settings.timeout;
29+
for (var header in reqHeaders) {
30+
if (!(header in UNSAFE_REQUEST_HEADERS) && reqHeaders[header])
31+
request.setRequestHeader(header, reqHeaders[header]);
32+
}
33+
34+
// Create a proxy for the XMLHttpRequest
35+
var requestProxy = new EventEmitter();
36+
requestProxy.abort = function () { request.abort(); };
37+
38+
// Handle the arrival of a response
39+
request.onload = function () {
40+
// Convert the response into an iterator
41+
var response = AsyncIterator.single(request.responseText || '');
42+
response.statusCode = request.status;
43+
44+
// Parse the response headers
45+
var resHeaders = response.headers = {},
46+
rawHeaders = request.getAllResponseHeaders() || '',
47+
headerMatcher = /^([^:\n\r]+):[ \t]*([^\r\n]*)$/mg, match;
48+
while (match = headerMatcher.exec(rawHeaders))
49+
resHeaders[match[1].toLowerCase()] = match[2];
50+
51+
// Emit the response
52+
requestProxy.emit('response', response);
4253

43-
// If the resource was time-negotiated, store its "base" URI (= no query string)
44-
if (settings.headers['accept-datetime'] && response.headers['memento-datetime']) {
45-
var resource = removeQuery(response.headers['content-location'] || settings.url);
54+
// If the resource was time-negotiated, store its queryless URI
55+
// to enable the PERFORMANCE HACK explained above
56+
if (reqHeaders['accept-datetime'] && resHeaders['memento-datetime']) {
57+
var resource = removeQuery(resHeaders['content-location'] || settings.url);
4658
if (!negotiatedResources[resource]) {
4759
// Ensure the resource is not a timegate
48-
var links = response.headers.link && parseLink(response.headers.link),
60+
var links = resHeaders.link && parseLink(resHeaders.link),
4961
timegate = removeQuery(links && links.timegate && links.timegate.url);
5062
if (resource !== timegate)
5163
negotiatedResources[resource] = true;
5264
}
5365
}
54-
},
55-
// Emit an error if the request fails
56-
function () {
57-
request.emit('error', new Error('Error requesting ' + settings.url));
58-
});
59-
// Aborts the request
60-
request.abort = function () { jqXHR.abort(); };
66+
};
67+
// Report errors and timeouts
68+
request.onerror = function () {
69+
requestProxy.emit('error', new Error('Error requesting ' + settings.url));
70+
};
71+
request.ontimeout = function () {
72+
requestProxy.emit('error', new Error('Timeout requesting ' + settings.url));
73+
};
6174

62-
return request;
75+
// Execute the request
76+
request.send();
77+
return requestProxy;
6378
}
6479

6580
// Removes the query string from a URL

0 commit comments

Comments
 (0)