Add files
This commit is contained in:
commit
a2f355ac82
1757 changed files with 320133 additions and 0 deletions
19
node_modules/@derhuerst/http-basic/LICENSE
generated
vendored
Normal file
19
node_modules/@derhuerst/http-basic/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2014 Forbes Lindesay
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
97
node_modules/@derhuerst/http-basic/README.md
generated
vendored
Normal file
97
node_modules/@derhuerst/http-basic/README.md
generated
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
# http-basic
|
||||
|
||||
Simple wrapper arround http.request/https.request
|
||||
|
||||
[](https://travis-ci.org/ForbesLindesay/http-basic)
|
||||
[](https://david-dm.org/ForbesLindesay/http-basic)
|
||||
[](https://www.npmjs.org/package/http-basic)
|
||||
|
||||
## Installation
|
||||
|
||||
npm install http-basic
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var request = require('http-basic');
|
||||
|
||||
var options = {followRedirects: true, gzip: true, cache: 'memory'};
|
||||
|
||||
var req = request('GET', 'http://example.com', options, function (err, res) {
|
||||
if (err) throw err;
|
||||
console.dir(res.statusCode);
|
||||
res.body.resume();
|
||||
});
|
||||
req.end();
|
||||
```
|
||||
|
||||
**method:**
|
||||
|
||||
The http method (e.g. `GET`, `POST`, `PUT`, `DELETE` etc.)
|
||||
|
||||
**url:**
|
||||
|
||||
The url as a string (e.g. `http://example.com`). It must be fully qualified and either http or https.
|
||||
|
||||
**options:**
|
||||
|
||||
- `headers` - (default `{}`) http headers
|
||||
- `agent` - (default: `false`) controlls keep-alive (see http://nodejs.org/api/http.html#http_http_request_options_callback)
|
||||
- `duplex` - (default: `true` except for `GET`, `OPTIONS` and `HEAD` requests) allows you to explicitly set a body on a request that uses a method that normally would not have a body
|
||||
- `followRedirects` - (default: `false`) - if true, redirects are followed (note that this only affects the result in the callback)
|
||||
- `maxRedirects` - (default: `Infinity`) - limit the number of redirects allowed.
|
||||
- `allowRedirectHeaders` (default: `null`) - an array of headers allowed for redirects (none if `null`).
|
||||
- `gzip` (default: `false`) - automatically accept gzip and deflate encodings. This is kept completely transparent to the user.
|
||||
- `cache` - (default: `null`) - `'memory'` or `'file'` to use the default built in caches or you can pass your own cache implementation.
|
||||
- `timeout` (default: `false`) - times out if no response is returned within the given number of milliseconds.
|
||||
- `socketTimeout` (default: `false`) - calls `req.setTimeout` internally which causes the request to timeout if no new data is seen for the given number of milliseconds.
|
||||
- `retry` (default: `false`) - retry GET requests. Set this to `true` to retry when the request errors or returns a status code greater than or equal to 400 (can also be a function that takes `(err, req, attemptNo) => shouldRetry`)
|
||||
- `retryDelay` (default: `200`) - the delay between retries (can also be set to a function that takes `(err, res, attemptNo) => delay`)
|
||||
- `maxRetries` (default: `5`) - the number of times to retry before giving up.
|
||||
- `ignoreFailedInvalidation` (default: `false`) - whether the cache should swallow errors if there is a problem removing a cached response. Note that enabling this setting may result in incorrect, cached data being returned to the user.
|
||||
- `isMatch` - `(requestHeaders: Headers, cachedResponse: CachedResponse, defaultValue: boolean) => boolean` - override the default behaviour for testing whether a cached response matches a request.
|
||||
- `isExpired` - `(cachedResponse: CachedResponse, defaultValue: boolean) => boolean` - override the default behaviour for testing whether a cached response has expired
|
||||
- `canCache` - `(res: Response<NodeJS.ReadableStream>, defaultValue: boolean) => boolean` - override the default behaviour for testing whether a response can be cached
|
||||
|
||||
**callback:**
|
||||
|
||||
The callback is called with `err` as the first argument and `res` as the second argument. `res` is an [http-response-object](https://github.com/ForbesLindesay/http-response-object). It has the following properties:
|
||||
|
||||
- `statusCode` - a number representing the HTTP Status Code
|
||||
- `headers` - an object representing the HTTP headers
|
||||
- `body` - a readable stream respresenting the request body.
|
||||
- `url` - the URL that was requested (in the case of redirects, this is the final url that was requested)
|
||||
|
||||
**returns:**
|
||||
|
||||
If the method is `GET`, `DELETE` or `HEAD`, it returns `undefined`.
|
||||
|
||||
Otherwise, it returns a writable stream for the body of the request.
|
||||
|
||||
## Implementing a Cache
|
||||
|
||||
A `Cache` is an object with three methods:
|
||||
|
||||
- `getResponse(url, callback)` - retrieve a cached response object
|
||||
- `setResponse(url, response)` - cache a response object
|
||||
- `invalidateResponse(url, callback)` - remove a response which is no longer valid
|
||||
|
||||
A cached response object is an object with the following properties:
|
||||
|
||||
- `statusCode` - Number
|
||||
- `headers` - Object (key value pairs of strings)
|
||||
- `body` - Stream (a stream of binary data)
|
||||
- `requestHeaders` - Object (key value pairs of strings)
|
||||
- `requestTimestamp` - Number
|
||||
|
||||
`getResponse` should call the callback with an optional error and either `null` or a cached response object, depending on whether the url can be found in the cache. Only `GET`s are cached.
|
||||
|
||||
`setResponse` should just swallow any errors it has (or resport them using `console.warn`).
|
||||
|
||||
`invalidateResponse` should call the callback with an optional error if it is unable to invalidate a response.
|
||||
|
||||
A cache may also define any of the methods from `lib/cache-utils.js` to override behaviour for what gets cached. It is currently still only possible to cache "get" requests, although this could be changed.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
9
node_modules/@derhuerst/http-basic/lib/CachedResponse.d.ts
generated
vendored
Normal file
9
node_modules/@derhuerst/http-basic/lib/CachedResponse.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { Headers } from './Headers';
|
||||
interface CachedResponse {
|
||||
statusCode: number;
|
||||
headers: Headers;
|
||||
body: NodeJS.ReadableStream;
|
||||
requestHeaders: Headers;
|
||||
requestTimestamp: number;
|
||||
}
|
||||
export { CachedResponse };
|
2
node_modules/@derhuerst/http-basic/lib/CachedResponse.js
generated
vendored
Normal file
2
node_modules/@derhuerst/http-basic/lib/CachedResponse.js
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
"use strict";
|
||||
exports.__esModule = true;
|
3
node_modules/@derhuerst/http-basic/lib/Callback.d.ts
generated
vendored
Normal file
3
node_modules/@derhuerst/http-basic/lib/Callback.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
import Response = require('http-response-object');
|
||||
declare type Callback = (err: NodeJS.ErrnoException | null, response?: Response<NodeJS.ReadableStream>) => void;
|
||||
export { Callback };
|
2
node_modules/@derhuerst/http-basic/lib/Callback.js
generated
vendored
Normal file
2
node_modules/@derhuerst/http-basic/lib/Callback.js
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
"use strict";
|
||||
exports.__esModule = true;
|
11
node_modules/@derhuerst/http-basic/lib/FileCache.d.ts
generated
vendored
Normal file
11
node_modules/@derhuerst/http-basic/lib/FileCache.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { ICache } from './ICache';
|
||||
import { CachedResponse } from './CachedResponse';
|
||||
export default class FileCache implements ICache {
|
||||
private readonly _location;
|
||||
constructor(location: string);
|
||||
getResponse(url: string, callback: (err: null | Error, response: null | CachedResponse) => void): void;
|
||||
setResponse(url: string, response: CachedResponse): void;
|
||||
updateResponseHeaders(url: string, response: Pick<CachedResponse, 'headers' | 'requestTimestamp'>): void;
|
||||
invalidateResponse(url: string, callback: (err: NodeJS.ErrnoException | null) => void): void;
|
||||
getCacheKey(url: string): string;
|
||||
}
|
107
node_modules/@derhuerst/http-basic/lib/FileCache.js
generated
vendored
Normal file
107
node_modules/@derhuerst/http-basic/lib/FileCache.js
generated
vendored
Normal file
|
@ -0,0 +1,107 @@
|
|||
'use strict';
|
||||
exports.__esModule = true;
|
||||
var fs = require("fs");
|
||||
var path_1 = require("path");
|
||||
var crypto_1 = require("crypto");
|
||||
function jsonParse(data, cb) {
|
||||
var result = null;
|
||||
try {
|
||||
result = JSON.parse(data);
|
||||
}
|
||||
catch (ex) {
|
||||
return cb(ex);
|
||||
}
|
||||
cb(null, result);
|
||||
}
|
||||
var FileCache = /** @class */ (function () {
|
||||
function FileCache(location) {
|
||||
this._location = location;
|
||||
}
|
||||
FileCache.prototype.getResponse = function (url, callback) {
|
||||
var key = path_1.resolve(this._location, this.getCacheKey(url));
|
||||
fs.readFile(key + '.json', 'utf8', function (err, data) {
|
||||
if (err && err.code === 'ENOENT')
|
||||
return callback(null, null);
|
||||
else if (err)
|
||||
return callback(err, null);
|
||||
jsonParse(data, function (err, response) {
|
||||
if (err) {
|
||||
return callback(err, null);
|
||||
}
|
||||
var body = fs.createReadStream(key + '.body');
|
||||
response.body = body;
|
||||
callback(null, response);
|
||||
});
|
||||
});
|
||||
};
|
||||
FileCache.prototype.setResponse = function (url, response) {
|
||||
var key = path_1.resolve(this._location, this.getCacheKey(url));
|
||||
var errored = false;
|
||||
fs.mkdir(this._location, { recursive: true }, function (err) {
|
||||
if (err && err.code !== 'EEXIST') {
|
||||
console.warn('Error creating cache: ' + err.message);
|
||||
return;
|
||||
}
|
||||
response.body.pipe(fs.createWriteStream(key + '.body')).on('error', function (err) {
|
||||
errored = true;
|
||||
console.warn('Error writing to cache: ' + err.message);
|
||||
}).on('close', function () {
|
||||
if (!errored) {
|
||||
fs.writeFile(key + '.json', JSON.stringify({
|
||||
statusCode: response.statusCode,
|
||||
headers: response.headers,
|
||||
requestHeaders: response.requestHeaders,
|
||||
requestTimestamp: response.requestTimestamp
|
||||
}, null, ' '), function (err) {
|
||||
if (err) {
|
||||
console.warn('Error writing to cache: ' + err.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
FileCache.prototype.updateResponseHeaders = function (url, response) {
|
||||
var key = path_1.resolve(this._location, this.getCacheKey(url));
|
||||
fs.readFile(key + '.json', 'utf8', function (err, data) {
|
||||
if (err) {
|
||||
console.warn('Error writing to cache: ' + err.message);
|
||||
return;
|
||||
}
|
||||
var parsed = null;
|
||||
try {
|
||||
parsed = JSON.parse(data);
|
||||
}
|
||||
catch (ex) {
|
||||
console.warn('Error writing to cache: ' + ex.message);
|
||||
return;
|
||||
}
|
||||
fs.writeFile(key + '.json', JSON.stringify({
|
||||
statusCode: parsed.statusCode,
|
||||
headers: response.headers,
|
||||
requestHeaders: parsed.requestHeaders,
|
||||
requestTimestamp: response.requestTimestamp
|
||||
}, null, ' '), function (err) {
|
||||
if (err) {
|
||||
console.warn('Error writing to cache: ' + err.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
FileCache.prototype.invalidateResponse = function (url, callback) {
|
||||
var key = path_1.resolve(this._location, this.getCacheKey(url));
|
||||
fs.unlink(key + '.json', function (err) {
|
||||
if (err && err.code === 'ENOENT')
|
||||
return callback(null);
|
||||
else
|
||||
callback(err || null);
|
||||
});
|
||||
};
|
||||
FileCache.prototype.getCacheKey = function (url) {
|
||||
var hash = crypto_1.createHash('sha512');
|
||||
hash.update(url);
|
||||
return hash.digest('hex');
|
||||
};
|
||||
return FileCache;
|
||||
}());
|
||||
exports["default"] = FileCache;
|
2
node_modules/@derhuerst/http-basic/lib/Headers.d.ts
generated
vendored
Normal file
2
node_modules/@derhuerst/http-basic/lib/Headers.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
import { IncomingHttpHeaders } from 'http';
|
||||
export declare type Headers = IncomingHttpHeaders;
|
2
node_modules/@derhuerst/http-basic/lib/Headers.js
generated
vendored
Normal file
2
node_modules/@derhuerst/http-basic/lib/Headers.js
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
"use strict";
|
||||
exports.__esModule = true;
|
2
node_modules/@derhuerst/http-basic/lib/HttpVerb.d.ts
generated
vendored
Normal file
2
node_modules/@derhuerst/http-basic/lib/HttpVerb.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
declare type HttpVerb = ('GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'CONNECT' | 'OPTIONS' | 'TRACE' | 'PATCH');
|
||||
export { HttpVerb };
|
2
node_modules/@derhuerst/http-basic/lib/HttpVerb.js
generated
vendored
Normal file
2
node_modules/@derhuerst/http-basic/lib/HttpVerb.js
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
"use strict";
|
||||
exports.__esModule = true;
|
8
node_modules/@derhuerst/http-basic/lib/ICache.d.ts
generated
vendored
Normal file
8
node_modules/@derhuerst/http-basic/lib/ICache.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { CachedResponse } from './CachedResponse';
|
||||
interface ICache {
|
||||
getResponse(url: string, cb: (err: Error | null, response: CachedResponse | null) => void): void;
|
||||
setResponse(url: string, response: CachedResponse | null): void;
|
||||
updateResponseHeaders?: (url: string, response: Pick<CachedResponse, 'headers' | 'requestTimestamp'>) => void;
|
||||
invalidateResponse(url: string, cb: (err: Error | null) => void): void;
|
||||
}
|
||||
export { ICache };
|
2
node_modules/@derhuerst/http-basic/lib/ICache.js
generated
vendored
Normal file
2
node_modules/@derhuerst/http-basic/lib/ICache.js
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
"use strict";
|
||||
exports.__esModule = true;
|
8
node_modules/@derhuerst/http-basic/lib/MemoryCache.d.ts
generated
vendored
Normal file
8
node_modules/@derhuerst/http-basic/lib/MemoryCache.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { CachedResponse } from './CachedResponse';
|
||||
export default class MemoryCache {
|
||||
private readonly _cache;
|
||||
getResponse(url: string, callback: (err: null | Error, response: null | CachedResponse) => void): void;
|
||||
updateResponseHeaders(url: string, response: Pick<CachedResponse, 'headers' | 'requestTimestamp'>): void;
|
||||
setResponse(url: string, response: CachedResponse): void;
|
||||
invalidateResponse(url: string, callback: (err: NodeJS.ErrnoException | null) => void): void;
|
||||
}
|
56
node_modules/@derhuerst/http-basic/lib/MemoryCache.js
generated
vendored
Normal file
56
node_modules/@derhuerst/http-basic/lib/MemoryCache.js
generated
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
'use strict';
|
||||
var __assign = (this && this.__assign) || Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
exports.__esModule = true;
|
||||
var stream_1 = require("stream");
|
||||
var concat = require("concat-stream");
|
||||
var MemoryCache = /** @class */ (function () {
|
||||
function MemoryCache() {
|
||||
this._cache = {};
|
||||
}
|
||||
MemoryCache.prototype.getResponse = function (url, callback) {
|
||||
var cache = this._cache;
|
||||
if (cache[url]) {
|
||||
var body = new stream_1.PassThrough();
|
||||
body.end(cache[url].body);
|
||||
callback(null, {
|
||||
statusCode: cache[url].statusCode,
|
||||
headers: cache[url].headers,
|
||||
body: body,
|
||||
requestHeaders: cache[url].requestHeaders,
|
||||
requestTimestamp: cache[url].requestTimestamp
|
||||
});
|
||||
}
|
||||
else {
|
||||
callback(null, null);
|
||||
}
|
||||
};
|
||||
MemoryCache.prototype.updateResponseHeaders = function (url, response) {
|
||||
this._cache[url] = __assign({}, this._cache[url], { headers: response.headers, requestTimestamp: response.requestTimestamp });
|
||||
};
|
||||
MemoryCache.prototype.setResponse = function (url, response) {
|
||||
var cache = this._cache;
|
||||
response.body.pipe(concat(function (body) {
|
||||
cache[url] = {
|
||||
statusCode: response.statusCode,
|
||||
headers: response.headers,
|
||||
body: body,
|
||||
requestHeaders: response.requestHeaders,
|
||||
requestTimestamp: response.requestTimestamp
|
||||
};
|
||||
}));
|
||||
};
|
||||
MemoryCache.prototype.invalidateResponse = function (url, callback) {
|
||||
var cache = this._cache;
|
||||
delete cache[url];
|
||||
callback(null);
|
||||
};
|
||||
return MemoryCache;
|
||||
}());
|
||||
exports["default"] = MemoryCache;
|
25
node_modules/@derhuerst/http-basic/lib/Options.d.ts
generated
vendored
Normal file
25
node_modules/@derhuerst/http-basic/lib/Options.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { Agent } from 'http';
|
||||
import { Headers } from './Headers';
|
||||
import { ICache } from './ICache';
|
||||
import Response = require('http-response-object');
|
||||
import { CachedResponse } from './CachedResponse';
|
||||
interface Options {
|
||||
agent?: Agent | boolean;
|
||||
allowRedirectHeaders?: string[];
|
||||
cache?: 'file' | 'memory' | ICache;
|
||||
duplex?: boolean;
|
||||
followRedirects?: boolean;
|
||||
gzip?: boolean;
|
||||
headers?: Headers;
|
||||
ignoreFailedInvalidation?: boolean;
|
||||
maxRedirects?: number;
|
||||
maxRetries?: number;
|
||||
retry?: boolean | ((err: NodeJS.ErrnoException | null, res: Response<NodeJS.ReadableStream> | void, attemptNumber: number) => boolean);
|
||||
retryDelay?: number | ((err: NodeJS.ErrnoException | null, res: Response<NodeJS.ReadableStream> | void, attemptNumber: number) => number);
|
||||
socketTimeout?: number;
|
||||
timeout?: number;
|
||||
isMatch?: (requestHeaders: Headers, cachedResponse: CachedResponse, defaultValue: boolean) => boolean;
|
||||
isExpired?: (cachedResponse: CachedResponse, defaultValue: boolean) => boolean;
|
||||
canCache?: (res: Response<NodeJS.ReadableStream>, defaultValue: boolean) => boolean;
|
||||
}
|
||||
export { Options };
|
2
node_modules/@derhuerst/http-basic/lib/Options.js
generated
vendored
Normal file
2
node_modules/@derhuerst/http-basic/lib/Options.js
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
"use strict";
|
||||
exports.__esModule = true;
|
14
node_modules/@derhuerst/http-basic/lib/cache-control-utils.d.ts
generated
vendored
Normal file
14
node_modules/@derhuerst/http-basic/lib/cache-control-utils.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { CachedResponse } from './CachedResponse';
|
||||
import Response = require('http-response-object');
|
||||
export declare type Policy = {
|
||||
maxage: number | null;
|
||||
};
|
||||
/**
|
||||
* returns true if this response is cacheable (according to cache-control headers)
|
||||
*/
|
||||
export declare function isCacheable<T>(res: Response<T> | CachedResponse): boolean;
|
||||
/**
|
||||
* if the response is cacheable, returns an object detailing the maxage of the cache
|
||||
* otherwise returns null
|
||||
*/
|
||||
export declare function cachePolicy<T>(res: Response<T> | CachedResponse): Policy | null;
|
53
node_modules/@derhuerst/http-basic/lib/cache-control-utils.js
generated
vendored
Normal file
53
node_modules/@derhuerst/http-basic/lib/cache-control-utils.js
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var parseCacheControl = require('parse-cache-control');
|
||||
function parseCacheControlHeader(res) {
|
||||
var cacheControl = res.headers['cache-control'];
|
||||
var normalisedCacheControl = typeof cacheControl === 'string' ? cacheControl.trim() : ''; // must be normalised for parsing (e.g. parseCacheControl)
|
||||
if (!cacheControl) {
|
||||
return null;
|
||||
}
|
||||
return parseCacheControl(cacheControl);
|
||||
}
|
||||
// for the purposes of this library, we err on the side of caution and do not cache anything except public (or implicit public)
|
||||
var nonCaching = ['private', 'no-cache', 'no-store', 'no-transform', 'must-revalidate', 'proxy-revalidate'];
|
||||
function isCacheControlCacheable(parsedCacheControl) {
|
||||
if (!parsedCacheControl) {
|
||||
return false;
|
||||
}
|
||||
if (parsedCacheControl.public) {
|
||||
return true;
|
||||
}
|
||||
// note that the library does not currently support s-maxage
|
||||
if (parsedCacheControl["max-age"]) {
|
||||
// https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.3
|
||||
// The max-age directive on a response implies that the response is cacheable (i.e., "public") unless some other, more restrictive cache directive is also present.
|
||||
for (var i = 0; i < nonCaching.length; i++) {
|
||||
if (parsedCacheControl[nonCaching[i]]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* returns true if this response is cacheable (according to cache-control headers)
|
||||
*/
|
||||
function isCacheable(res) {
|
||||
return isCacheControlCacheable(parseCacheControlHeader(res));
|
||||
}
|
||||
exports.isCacheable = isCacheable;
|
||||
function buildPolicy(parsedCacheControl) {
|
||||
// note that the library does not currently support s-maxage
|
||||
return { maxage: parsedCacheControl['max-age'] || null };
|
||||
}
|
||||
/**
|
||||
* if the response is cacheable, returns an object detailing the maxage of the cache
|
||||
* otherwise returns null
|
||||
*/
|
||||
function cachePolicy(res) {
|
||||
var parsed = parseCacheControlHeader(res);
|
||||
return parsed && isCacheControlCacheable(parsed) ? buildPolicy(parsed) : null;
|
||||
}
|
||||
exports.cachePolicy = cachePolicy;
|
6
node_modules/@derhuerst/http-basic/lib/cache-utils.d.ts
generated
vendored
Normal file
6
node_modules/@derhuerst/http-basic/lib/cache-utils.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
import Response = require('http-response-object');
|
||||
import { Headers } from './Headers';
|
||||
import { CachedResponse } from './CachedResponse';
|
||||
export declare function isMatch(requestHeaders: Headers, cachedResponse: CachedResponse): boolean;
|
||||
export declare function isExpired(cachedResponse: CachedResponse): boolean;
|
||||
export declare function canCache<T>(res: Response<T>): boolean;
|
44
node_modules/@derhuerst/http-basic/lib/cache-utils.js
generated
vendored
Normal file
44
node_modules/@derhuerst/http-basic/lib/cache-utils.js
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var cache_control_utils_1 = require("./cache-control-utils");
|
||||
function isMatch(requestHeaders, cachedResponse) {
|
||||
var vary = cachedResponse.headers['vary'];
|
||||
if (vary && cachedResponse.requestHeaders) {
|
||||
vary = '' + vary;
|
||||
return vary.split(',').map(function (header) { return header.trim().toLowerCase(); }).every(function (header) {
|
||||
return requestHeaders[header] === cachedResponse.requestHeaders[header];
|
||||
});
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
exports.isMatch = isMatch;
|
||||
;
|
||||
function isExpired(cachedResponse) {
|
||||
var policy = cache_control_utils_1.cachePolicy(cachedResponse);
|
||||
if (policy) {
|
||||
var time = (Date.now() - cachedResponse.requestTimestamp) / 1000;
|
||||
if (policy.maxage !== null && policy.maxage > time) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (cachedResponse.statusCode === 301 || cachedResponse.statusCode === 308)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
exports.isExpired = isExpired;
|
||||
;
|
||||
function canCache(res) {
|
||||
if (res.headers['etag'])
|
||||
return true;
|
||||
if (res.headers['last-modified'])
|
||||
return true;
|
||||
if (cache_control_utils_1.isCacheable(res))
|
||||
return true;
|
||||
if (res.statusCode === 301 || res.statusCode === 308)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
exports.canCache = canCache;
|
||||
;
|
16
node_modules/@derhuerst/http-basic/lib/index.d.ts
generated
vendored
Normal file
16
node_modules/@derhuerst/http-basic/lib/index.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { Callback } from './Callback';
|
||||
import { CachedResponse } from './CachedResponse';
|
||||
import { HttpVerb } from './HttpVerb';
|
||||
import { ICache } from './ICache';
|
||||
import { Options } from './Options';
|
||||
import Response = require('http-response-object');
|
||||
import { URL } from 'url';
|
||||
declare function request(method: HttpVerb, url: string | URL, options: Options | null | void, callback: Callback): void | NodeJS.WritableStream;
|
||||
declare function request(method: HttpVerb, url: string | URL, callback: Callback): void | NodeJS.WritableStream;
|
||||
export default request;
|
||||
export { HttpVerb };
|
||||
export { Options };
|
||||
export { Callback };
|
||||
export { Response };
|
||||
export { CachedResponse };
|
||||
export { ICache };
|
380
node_modules/@derhuerst/http-basic/lib/index.js
generated
vendored
Normal file
380
node_modules/@derhuerst/http-basic/lib/index.js
generated
vendored
Normal file
|
@ -0,0 +1,380 @@
|
|||
"use strict";
|
||||
var __assign = (this && this.__assign) || Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
exports.__esModule = true;
|
||||
var cacheUtils = require("./cache-utils");
|
||||
var FileCache_1 = require("./FileCache");
|
||||
var MemoryCache_1 = require("./MemoryCache");
|
||||
var http_1 = require("http");
|
||||
var zlib_1 = require("zlib");
|
||||
var url_1 = require("url");
|
||||
var stream_1 = require("stream");
|
||||
var https_1 = require("https");
|
||||
var Response = require("http-response-object");
|
||||
exports.Response = Response;
|
||||
var caseless = require('caseless');
|
||||
var fileCache = new FileCache_1["default"](__dirname + '/cache');
|
||||
var memoryCache = new MemoryCache_1["default"]();
|
||||
function requestProtocol(protocol, options, callback) {
|
||||
if (protocol === 'http') {
|
||||
return http_1.request(options, callback);
|
||||
}
|
||||
else if (protocol === 'https') {
|
||||
return https_1.request(options, callback);
|
||||
}
|
||||
throw new Error('Unsupported protocol ' + protocol);
|
||||
}
|
||||
function request(method, url, options, callback) {
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = null;
|
||||
}
|
||||
if (options === null || options === undefined) {
|
||||
options = {};
|
||||
}
|
||||
if (typeof options !== 'object') {
|
||||
throw new TypeError('options must be an object (or null)');
|
||||
}
|
||||
if (typeof callback !== 'function') {
|
||||
throw new TypeError('callback must be a function');
|
||||
}
|
||||
return _request(method, ((url && typeof url === 'object') ? url.href : url), options, callback);
|
||||
}
|
||||
function _request(method, url, options, callback) {
|
||||
var start = Date.now();
|
||||
if (typeof method !== 'string') {
|
||||
throw new TypeError('The method must be a string.');
|
||||
}
|
||||
if (typeof url !== 'string') {
|
||||
throw new TypeError('The URL/path must be a string or a URL object.');
|
||||
}
|
||||
method = method.toUpperCase();
|
||||
var urlObject = url_1.parse(url);
|
||||
var protocol = (urlObject.protocol || '').replace(/\:$/, '');
|
||||
if (protocol !== 'http' && protocol !== 'https') {
|
||||
throw new TypeError('The protocol "' + protocol + '" is not supported, cannot load "' + url + '"');
|
||||
}
|
||||
var rawHeaders = options.headers || {};
|
||||
var headers = caseless(rawHeaders);
|
||||
if (urlObject.auth) {
|
||||
headers.set('Authorization', 'Basic ' + (Buffer.from(urlObject.auth)).toString('base64'));
|
||||
}
|
||||
var agent = 'agent' in options ? options.agent : false;
|
||||
var cache = options.cache;
|
||||
if (typeof cache === 'string') {
|
||||
if (cache === 'file') {
|
||||
cache = fileCache;
|
||||
}
|
||||
else if (cache === 'memory') {
|
||||
cache = memoryCache;
|
||||
}
|
||||
}
|
||||
if (cache && !(typeof cache === 'object' && typeof cache.getResponse === 'function' && typeof cache.setResponse === 'function' && typeof cache.invalidateResponse === 'function')) {
|
||||
throw new TypeError(cache + ' is not a valid cache, caches must have `getResponse`, `setResponse` and `invalidateResponse` methods.');
|
||||
}
|
||||
var ignoreFailedInvalidation = options.ignoreFailedInvalidation;
|
||||
if (options.duplex !== undefined && typeof options.duplex !== 'boolean') {
|
||||
throw new Error('expected options.duplex to be a boolean if provided');
|
||||
}
|
||||
var duplex = options.duplex !== undefined ? options.duplex : !(method === 'GET' || method === 'DELETE' || method === 'HEAD');
|
||||
var unsafe = !(method === 'GET' || method === 'OPTIONS' || method === 'HEAD');
|
||||
if (options.gzip) {
|
||||
headers.set('Accept-Encoding', headers.has('Accept-Encoding') ? headers.get('Accept-Encoding') + ',gzip,deflate' : 'gzip,deflate');
|
||||
return _request(method, url, {
|
||||
allowRedirectHeaders: options.allowRedirectHeaders,
|
||||
duplex: duplex,
|
||||
headers: rawHeaders,
|
||||
agent: agent,
|
||||
followRedirects: options.followRedirects,
|
||||
retry: options.retry,
|
||||
retryDelay: options.retryDelay,
|
||||
maxRetries: options.maxRetries,
|
||||
cache: cache,
|
||||
timeout: options.timeout
|
||||
}, function (err, res) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
if (!res)
|
||||
return callback(new Error('Response should not be undefined if there is no error.'));
|
||||
var newHeaders = __assign({}, res.headers);
|
||||
var newBody = res.body;
|
||||
switch (newHeaders['content-encoding']) {
|
||||
case 'gzip':
|
||||
delete newHeaders['content-encoding'];
|
||||
newBody = res.body.pipe(zlib_1.createGunzip());
|
||||
break;
|
||||
case 'deflate':
|
||||
delete newHeaders['content-encoding'];
|
||||
newBody = res.body.pipe(zlib_1.createInflate());
|
||||
break;
|
||||
}
|
||||
return callback(err, new Response(res.statusCode, newHeaders, newBody, res.url));
|
||||
});
|
||||
}
|
||||
if (options.followRedirects) {
|
||||
return _request(method, url, {
|
||||
allowRedirectHeaders: options.allowRedirectHeaders,
|
||||
duplex: duplex,
|
||||
headers: rawHeaders,
|
||||
agent: agent,
|
||||
retry: options.retry,
|
||||
retryDelay: options.retryDelay,
|
||||
maxRetries: options.maxRetries,
|
||||
cache: cache,
|
||||
timeout: options.timeout
|
||||
}, function (err, res) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
if (!res)
|
||||
return callback(new Error('Response should not be undefined if there is no error.'));
|
||||
if (options.followRedirects && isRedirect(res.statusCode)) {
|
||||
// prevent leakage of file handles
|
||||
res.body.resume();
|
||||
if (method === 'DELETE' && res.statusCode === 303) {
|
||||
// 303 See Other should convert to GET for duplex
|
||||
// requests and for DELETE
|
||||
method = 'GET';
|
||||
}
|
||||
if (options.maxRedirects === 0) {
|
||||
var err_1 = new Error('Maximum number of redirects exceeded');
|
||||
err_1.res = res;
|
||||
return callback(err_1, res);
|
||||
}
|
||||
options = __assign({}, options, { duplex: false, maxRedirects: options.maxRedirects && options.maxRedirects !== Infinity ? options.maxRedirects - 1 : options.maxRedirects });
|
||||
// don't maintain headers through redirects
|
||||
// This fixes a problem where a POST to http://example.com
|
||||
// might result in a GET to http://example.co.uk that includes "content-length"
|
||||
// as a header
|
||||
var headers_1 = caseless(options.headers);
|
||||
var redirectHeaders = {};
|
||||
if (options.allowRedirectHeaders) {
|
||||
for (var i = 0; i < options.allowRedirectHeaders.length; i++) {
|
||||
var headerName = options.allowRedirectHeaders[i];
|
||||
var headerValue = headers_1.get(headerName);
|
||||
if (headerValue) {
|
||||
redirectHeaders[headerName] = headerValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
options.headers = redirectHeaders;
|
||||
var location = res.headers.location;
|
||||
if (typeof location !== 'string') {
|
||||
return callback(new Error('Cannot redirect to non string location: ' + location));
|
||||
}
|
||||
return request(duplex ? 'GET' : method, url_1.resolve(url, location), options, callback);
|
||||
}
|
||||
else {
|
||||
return callback(null, res);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (cache && method === 'GET' && !duplex) {
|
||||
var timestamp_1 = Date.now();
|
||||
return cache.getResponse(url, function (err, cachedResponse) {
|
||||
if (err) {
|
||||
console.warn('Error reading from cache: ' + err.message);
|
||||
}
|
||||
var isMatch = !!(cachedResponse && cacheUtils.isMatch(rawHeaders, cachedResponse));
|
||||
if (cachedResponse && (options.isMatch ? options.isMatch(rawHeaders, cachedResponse, isMatch) : isMatch)) {
|
||||
var isExpired = cacheUtils.isExpired(cachedResponse);
|
||||
if (!(options.isExpired ? options.isExpired(cachedResponse, isExpired) : isExpired)) {
|
||||
var res = new Response(cachedResponse.statusCode, cachedResponse.headers, cachedResponse.body, url);
|
||||
res.fromCache = true;
|
||||
res.fromNotModified = false;
|
||||
return callback(null, res);
|
||||
}
|
||||
else {
|
||||
if (cachedResponse.headers['etag']) {
|
||||
headers.set('If-None-Match', cachedResponse.headers['etag']);
|
||||
}
|
||||
if (cachedResponse.headers['last-modified']) {
|
||||
headers.set('If-Modified-Since', cachedResponse.headers['last-modified']);
|
||||
}
|
||||
}
|
||||
}
|
||||
request('GET', url, {
|
||||
allowRedirectHeaders: options.allowRedirectHeaders,
|
||||
headers: rawHeaders,
|
||||
retry: options.retry,
|
||||
retryDelay: options.retryDelay,
|
||||
maxRetries: options.maxRetries,
|
||||
agent: agent,
|
||||
timeout: options.timeout
|
||||
}, function (err, res) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
if (!res)
|
||||
return callback(new Error('Response should not be undefined if there is no error.'));
|
||||
if (res.statusCode === 304 && cachedResponse) { // Not Modified
|
||||
// prevent leakage of file handles
|
||||
res.body.resume();
|
||||
var resultBody = cachedResponse.body;
|
||||
var c = cache;
|
||||
if (c.updateResponseHeaders) {
|
||||
c.updateResponseHeaders(url, {
|
||||
headers: res.headers,
|
||||
requestTimestamp: timestamp_1
|
||||
});
|
||||
}
|
||||
else {
|
||||
var cachedResponseBody_1 = new stream_1.PassThrough();
|
||||
var newResultBody_1 = new stream_1.PassThrough();
|
||||
resultBody.on('data', function (data) {
|
||||
cachedResponseBody_1.write(data);
|
||||
newResultBody_1.write(data);
|
||||
});
|
||||
resultBody.on('end', function () {
|
||||
cachedResponseBody_1.end();
|
||||
newResultBody_1.end();
|
||||
});
|
||||
resultBody = newResultBody_1;
|
||||
cache.setResponse(url, {
|
||||
statusCode: cachedResponse.statusCode,
|
||||
headers: res.headers,
|
||||
body: cachedResponseBody_1,
|
||||
requestHeaders: cachedResponse.requestHeaders,
|
||||
requestTimestamp: timestamp_1
|
||||
});
|
||||
}
|
||||
var response = new Response(cachedResponse.statusCode, cachedResponse.headers, resultBody, url);
|
||||
response.fromCache = true;
|
||||
response.fromNotModified = true;
|
||||
return callback(null, response);
|
||||
}
|
||||
// prevent leakage of file handles
|
||||
cachedResponse && cachedResponse.body.resume();
|
||||
var canCache = cacheUtils.canCache(res);
|
||||
if (options.canCache ? options.canCache(res, canCache) : canCache) {
|
||||
var cachedResponseBody_2 = new stream_1.PassThrough();
|
||||
var resultResponseBody_1 = new stream_1.PassThrough();
|
||||
res.body.on('data', function (data) {
|
||||
cachedResponseBody_2.write(data);
|
||||
resultResponseBody_1.write(data);
|
||||
});
|
||||
res.body.on('end', function () { cachedResponseBody_2.end(); resultResponseBody_1.end(); });
|
||||
var resultResponse = new Response(res.statusCode, res.headers, resultResponseBody_1, url);
|
||||
cache.setResponse(url, {
|
||||
statusCode: res.statusCode,
|
||||
headers: res.headers,
|
||||
body: cachedResponseBody_2,
|
||||
requestHeaders: rawHeaders,
|
||||
requestTimestamp: timestamp_1
|
||||
});
|
||||
return callback(null, resultResponse);
|
||||
}
|
||||
else {
|
||||
return callback(null, res);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
function attempt(n) {
|
||||
return _request(method, url, {
|
||||
allowRedirectHeaders: options.allowRedirectHeaders,
|
||||
headers: rawHeaders,
|
||||
agent: agent,
|
||||
timeout: options.timeout
|
||||
}, function (err, res) {
|
||||
var retry = err || !res || res.statusCode >= 400;
|
||||
if (typeof options.retry === 'function') {
|
||||
retry = options.retry(err, res, n + 1);
|
||||
}
|
||||
if (n >= (options.maxRetries || 5)) {
|
||||
retry = false;
|
||||
}
|
||||
if (retry) {
|
||||
var delay = options.retryDelay;
|
||||
if (typeof delay === 'function') {
|
||||
delay = delay(err, res, n + 1);
|
||||
}
|
||||
delay = delay || 200;
|
||||
setTimeout(function () {
|
||||
attempt(n + 1);
|
||||
}, delay);
|
||||
}
|
||||
else {
|
||||
callback(err, res);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (options.retry && method === 'GET' && !duplex) {
|
||||
return attempt(0);
|
||||
}
|
||||
var responded = false;
|
||||
var timeout = null;
|
||||
var req = requestProtocol(protocol, {
|
||||
host: urlObject.hostname,
|
||||
port: urlObject.port == null ? undefined : +urlObject.port,
|
||||
path: urlObject.path,
|
||||
method: method,
|
||||
headers: rawHeaders,
|
||||
agent: agent
|
||||
}, function (res) {
|
||||
var end = Date.now();
|
||||
if (responded)
|
||||
return res.resume();
|
||||
responded = true;
|
||||
if (timeout !== null)
|
||||
clearTimeout(timeout);
|
||||
var result = new Response(res.statusCode || 0, res.headers, res, url);
|
||||
if (cache && unsafe && res.statusCode && res.statusCode < 400) {
|
||||
cache.invalidateResponse(url, function (err) {
|
||||
if (err && !ignoreFailedInvalidation) {
|
||||
callback(new Error('Error invalidating the cache for' + url + ': ' + err.message), result);
|
||||
}
|
||||
else {
|
||||
callback(null, result);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
callback(null, result);
|
||||
}
|
||||
}).on('error', function (err) {
|
||||
if (responded)
|
||||
return;
|
||||
responded = true;
|
||||
if (timeout !== null)
|
||||
clearTimeout(timeout);
|
||||
callback(err);
|
||||
});
|
||||
function onTimeout() {
|
||||
if (responded)
|
||||
return;
|
||||
responded = true;
|
||||
if (timeout !== null)
|
||||
clearTimeout(timeout);
|
||||
req.abort();
|
||||
var duration = Date.now() - start;
|
||||
var err = new Error('Request timed out after ' + duration + 'ms');
|
||||
err.timeout = true;
|
||||
err.duration = duration;
|
||||
callback(err);
|
||||
}
|
||||
if (options.socketTimeout) {
|
||||
req.setTimeout(options.socketTimeout, onTimeout);
|
||||
}
|
||||
if (options.timeout) {
|
||||
timeout = setTimeout(onTimeout, options.timeout);
|
||||
}
|
||||
if (duplex) {
|
||||
return req;
|
||||
}
|
||||
else {
|
||||
req.end();
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
function isRedirect(statusCode) {
|
||||
return statusCode === 301 || statusCode === 302 || statusCode === 303 || statusCode === 307 || statusCode === 308;
|
||||
}
|
||||
exports["default"] = request;
|
||||
module.exports = request;
|
||||
module.exports["default"] = request;
|
||||
module.exports.Response = Response;
|
50
node_modules/@derhuerst/http-basic/package.json
generated
vendored
Normal file
50
node_modules/@derhuerst/http-basic/package.json
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
"name": "@derhuerst/http-basic",
|
||||
"version": "8.2.1",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"description": "Very low level wrapper arround http.request/https.request",
|
||||
"keywords": [
|
||||
"http",
|
||||
"https",
|
||||
"request",
|
||||
"fetch",
|
||||
"gzip",
|
||||
"deflate",
|
||||
"redirect",
|
||||
"cache",
|
||||
"etag",
|
||||
"cache-control"
|
||||
],
|
||||
"dependencies": {
|
||||
"caseless": "^0.12.0",
|
||||
"concat-stream": "^1.6.2",
|
||||
"http-response-object": "^3.0.1",
|
||||
"parse-cache-control": "^1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/concat-stream": "^1.6.0",
|
||||
"@types/node": "^11.9.0",
|
||||
"flowgen2": "^2.2.1",
|
||||
"rimraf": "^2.5.4",
|
||||
"serve-static": "^1.11.1",
|
||||
"typescript": "^2.3.4"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc && flowgen lib/**/*",
|
||||
"pretest": "npm run build",
|
||||
"test": "node test/index && node test/cache && node test/cache-invalidation && rimraf lib/cache"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ForbesLindesay/http-basic.git"
|
||||
},
|
||||
"author": "ForbesLindesay",
|
||||
"license": "MIT"
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue