diff options
Diffstat (limited to 'node_modules/http-basic')
| -rw-r--r-- | node_modules/http-basic/.npmignore | 14 | ||||
| -rw-r--r-- | node_modules/http-basic/.travis.yml | 3 | ||||
| -rw-r--r-- | node_modules/http-basic/LICENSE | 19 | ||||
| -rw-r--r-- | node_modules/http-basic/README.md | 89 | ||||
| -rw-r--r-- | node_modules/http-basic/index.js | 280 | ||||
| -rw-r--r-- | node_modules/http-basic/lib/cache-utils.js | 29 | ||||
| -rw-r--r-- | node_modules/http-basic/lib/file-cache.js | 62 | ||||
| -rw-r--r-- | node_modules/http-basic/lib/memory-cache.js | 39 | ||||
| -rw-r--r-- | node_modules/http-basic/package.json | 63 | ||||
| -rw-r--r-- | node_modules/http-basic/test/gzip.js | 10 | ||||
| -rw-r--r-- | node_modules/http-basic/test/index.js | 89 |
11 files changed, 697 insertions, 0 deletions
diff --git a/node_modules/http-basic/.npmignore b/node_modules/http-basic/.npmignore new file mode 100644 index 0000000..c26f2b4 --- /dev/null +++ b/node_modules/http-basic/.npmignore @@ -0,0 +1,14 @@ +/cache +lib-cov +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.gz +pids +logs +results +npm-debug.log +node_modules diff --git a/node_modules/http-basic/.travis.yml b/node_modules/http-basic/.travis.yml new file mode 100644 index 0000000..6e5919d --- /dev/null +++ b/node_modules/http-basic/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - "0.10" diff --git a/node_modules/http-basic/LICENSE b/node_modules/http-basic/LICENSE new file mode 100644 index 0000000..27cc9f3 --- /dev/null +++ b/node_modules/http-basic/LICENSE @@ -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.
\ No newline at end of file diff --git a/node_modules/http-basic/README.md b/node_modules/http-basic/README.md new file mode 100644 index 0000000..2d92928 --- /dev/null +++ b/node_modules/http-basic/README.md @@ -0,0 +1,89 @@ +# 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) + - `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. + +**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 two methods: + + - `getResponse(url, callback)` - retrieve a cached response object + - `setResponse(url, response)` - cache a response object + +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`). + +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 diff --git a/node_modules/http-basic/index.js b/node_modules/http-basic/index.js new file mode 100644 index 0000000..621d95f --- /dev/null +++ b/node_modules/http-basic/index.js @@ -0,0 +1,280 @@ +'use strict'; + +var parseUrl = require('url').parse; +var resolveUrl = require('url').resolve; +var zlib = require('zlib'); +var protocols = {http: require('http'), https: require('https')}; +var PassThrough = require('stream').PassThrough; +var Response = require('http-response-object'); +var caseless = require('caseless'); +var cacheUtils = require('./lib/cache-utils.js'); +var builtinCaches = { + memory: new (require('./lib/memory-cache.js'))(), + file: new (require('./lib/file-cache.js'))(__dirname + '/cache') +}; + +module.exports = request; +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.'); + } + 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)'); + } + + method = method.toUpperCase(); + var urlString = url; + url = parseUrl(urlString); + + if (!url.protocol || !protocols[url.protocol.replace(/\:$/, '')]) { + throw new TypeError('The protocol "' + url.protocol + '" is not supported, cannot load "' + urlString + '"'); + } + + var rawHeaders = options.headers || {}; + var headers = caseless(rawHeaders); + if (url.auth) { + headers.set('Authorization', 'Basic ' + (new Buffer(url.auth)).toString('base64')); + } + var agent = 'agent' in options ? options.agent : false; + + var cache = options.cache; + if (typeof cache === 'string' && cache in builtinCaches) { + cache = builtinCaches[cache]; + } + if (cache && !(typeof cache === 'object' && typeof cache.getResponse === 'function' && typeof cache.setResponse === 'function')) { + throw new TypeError(cache + ' is not a valid cache, caches must have `getResponse` and `setResponse` methods.'); + } + + var duplex = !(method === 'GET' || method === 'DELETE' || method === 'HEAD'); + + if (options.gzip) { + headers.set('Accept-Encoding', headers.has('Accept-Encoding') ? headers.get('Accept-Encoding') + ',gzip,deflate' : 'gzip,deflate'); + return request(method, urlString, { + allowRedirectHeaders: options.allowRedirectHeaders, + 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); + switch (res.headers['content-encoding']) { + case 'gzip': + delete res.headers['content-encoding']; + res.body = res.body.pipe(zlib.createGunzip()); + break; + case 'deflate': + delete res.headers['content-encoding']; + res.body = res.body.pipe(zlib.createInflate()); + break; + } + return callback(err, res); + }); + } + if (options.followRedirects) { + return request(method, urlString, { + allowRedirectHeaders: options.allowRedirectHeaders, + 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 (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 = new Error('Maximum number of redirects exceeded'); + err.res = res; + return callback(err, res); + } + var opts = {}; + Object.keys(options).forEach(function (key) { + opts[key] = options[key]; + }); + options = opts; + if (options.maxRedirects && options.maxRedirects !== Infinity) { + 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 = caseless(options.headers), redirectHeaders = {}; + if (options.allowRedirectHeaders) { + var headerName, headerValue; + for (var i = 0; i < options.allowRedirectHeaders.length; i++) { + headerName = options.allowRedirectHeaders[i]; + headerValue = headers.get(headerName); + if (headerValue) { + redirectHeaders[headerName] = headerValue; + } + } + } + options.headers = redirectHeaders; + return request(duplex ? 'GET' : method, resolveUrl(urlString, res.headers.location), options, callback); + } else { + return callback(null, res); + } + }); + } + if (cache && method === 'GET') { + var timestamp = Date.now(); + return cache.getResponse(urlString, function (err, cachedResponse) { + if (err) { + console.warn('Error reading from cache: ' + err.message); + } + if (cachedResponse && (cache.isMatch ? cache : cacheUtils).isMatch(rawHeaders, cachedResponse)) { + if (!(cache.isExpired ? cache : cacheUtils).isExpired(cachedResponse)) { + var res = new Response(cachedResponse.statusCode, cachedResponse.headers, cachedResponse.body); + res.url = urlString; + res.fromCache = true; + res.fromNotModified = false; + return callback(null, res); + } else if (cachedResponse.headers['etag']) { + headers.set('If-None-Match', cachedResponse.headers['etag']); + } + } + request('GET', urlString, { + 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.statusCode === 304 && cachedResponse) { // Not Modified + // prevent leakage of file handles + res.body.resume(); + res = new Response(cachedResponse.statusCode, cachedResponse.headers, cachedResponse.body); + res.url = urlString; + res.fromCache = true; + res.fromNotModified = true; + return callback(null, res); + } else if ((cache.canCache ? cache : cacheUtils).canCache(res)) { + // prevent leakage of file handles + cachedResponse && cachedResponse.body.resume(); + var cachedResponseBody = new PassThrough(); + var resultResponseBody = new PassThrough(); + res.body.on('data', function (data) { cachedResponseBody.write(data); resultResponseBody.write(data); }); + res.body.on('end', function () { cachedResponseBody.end(); resultResponseBody.end(); }); + var responseToCache = new Response(res.statusCode, res.headers, cachedResponseBody); + var resultResponse = new Response(res.statusCode, res.headers, resultResponseBody); + responseToCache.requestHeaders = rawHeaders; + responseToCache.requestTimestamp = timestamp; + cache.setResponse(urlString, responseToCache); + return callback(null, resultResponse); + } else { + // prevent leakage of file handles + cachedResponse && cachedResponse.body.resume(); + return callback(null, res); + } + }); + }); + } + + function attempt(n) { + request(method, urlString, { + allowRedirectHeaders: options.allowRedirectHeaders, + headers: rawHeaders, + agent: agent, + timeout: options.timeout + }, function (err, res) { + var retry = err || 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 options.retryDelay === 'function') { + delay = options.retryDelay(err, res, n + 1); + } + delay = delay || 200; + setTimeout(function () { + attempt(n + 1); + }, delay); + } else { + callback(null, res); + } + }); + } + if (options.retry && method === 'GET') { + return attempt(0); + } + + var responded = false; + + var req = protocols[url.protocol.replace(/\:$/, '')].request({ + host: url.hostname, + port: url.port, + path: url.path, + method: method, + headers: rawHeaders, + agent: agent + }, function (res) { + var end = Date.now(); + if (responded) return res.resume(); + responded = true; + var result = new Response(res.statusCode, res.headers, res); + result.url = urlString; + callback(null, result); + }).on('error', function (err) { + if (responded) return; + responded = true; + callback(err); + }); + + var start = Date.now(); + function onTimeout() { + if (responded) return; + responded = true; + 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) { + setTimeout(onTimeout, options.timeout); + } + if (duplex) { + return req; + } else { + req.end(); + } +} + +function isRedirect(statusCode) { + return statusCode === 301 || statusCode === 302 || statusCode === 303 || statusCode === 307 || statusCode === 308; +} diff --git a/node_modules/http-basic/lib/cache-utils.js b/node_modules/http-basic/lib/cache-utils.js new file mode 100644 index 0000000..3f76b0f --- /dev/null +++ b/node_modules/http-basic/lib/cache-utils.js @@ -0,0 +1,29 @@ +'use strict'; + +exports.isMatch = function (requestHeaders, cachedResponse) { + if (cachedResponse.headers['vary'] && cachedResponse.requestHeaders) { + return cachedResponse.headers['vary'].split(',').map(function (header) { return header.trim().toLowerCase(); }).every(function (header) { + return requestHeaders[header] === cachedResponse.requestHeaders[header]; + }); + } else { + return true; + } +}; +exports.isExpired = function (cachedResponse) { + var match + if (cachedResponse.headers['cache-control'] && (match = /^public\, *max\-age\=(\d+)$/.exec(cachedResponse.headers['cache-control']))) { + var time = (Date.now() - cachedResponse.requestTimestamp) / 1000; + if ((+match[1]) > time) { + return false; + } + } + if (cachedResponse.statusCode === 301 || cachedResponse.statusCode === 308) return false; + return true; +}; +exports.canCache = function (res) { + if (res.headers['etag']) return true; + if (/^public\, *max\-age\=(\d+)$/.test(res.headers['cache-control'])) return true; + if (res.statusCode === 301 || res.statusCode === 308) return true; + + return false; +}; diff --git a/node_modules/http-basic/lib/file-cache.js b/node_modules/http-basic/lib/file-cache.js new file mode 100644 index 0000000..9b90582 --- /dev/null +++ b/node_modules/http-basic/lib/file-cache.js @@ -0,0 +1,62 @@ +'use strict'; + +var fs = require('fs'); +var path = require('path'); +var crypto = require('crypto'); +var Response = require('http-response-object'); + +module.exports = FileCache; +function FileCache(location) { + this._location = location; +} + +FileCache.prototype.getResponse = function (url, callback) { + var key = path.resolve(this._location, getCacheKey(url)); + + fs.readFile(key + '.json', 'utf8', function (err, res) { + if (err && err.code === 'ENOENT') return callback(null, null); + else if (err) return callback(err); + try { + res = JSON.parse(res); + } catch (ex) { + return callback(ex); + } + var body = fs.createReadStream(key + '.body'); + res.body = body; + callback(null, res); + }); +}; +FileCache.prototype.setResponse = function (url, response) { + var key = path.resolve(this._location, getCacheKey(url)); + var errored = false; + + fs.mkdir(this._location, 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); + } + }); + } + }); + }); +}; + +function getCacheKey(url) { + var hash = crypto.createHash('sha512') + hash.update(url) + return hash.digest('hex') +} diff --git a/node_modules/http-basic/lib/memory-cache.js b/node_modules/http-basic/lib/memory-cache.js new file mode 100644 index 0000000..cf1f5a9 --- /dev/null +++ b/node_modules/http-basic/lib/memory-cache.js @@ -0,0 +1,39 @@ +'use strict'; + +var PassThrough = require('stream').PassThrough; +var concat = require('concat-stream'); +var Response = require('http-response-object'); + +module.exports = MemoryCache; +function MemoryCache() { + this._cache = {}; +} + +MemoryCache.prototype.getResponse = function (url, callback) { + var cache = this._cache; + if (cache[url]) { + var body = new 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.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 + }; + })); +}; diff --git a/node_modules/http-basic/package.json b/node_modules/http-basic/package.json new file mode 100644 index 0000000..dcd8d55 --- /dev/null +++ b/node_modules/http-basic/package.json @@ -0,0 +1,63 @@ +{ + "_from": "http-basic@^2.5.1", + "_id": "[email protected]", + "_inBundle": false, + "_integrity": "sha1-jORHvbW2xXf4pj4/p4BW7Eu02/s=", + "_location": "/http-basic", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "http-basic@^2.5.1", + "name": "http-basic", + "escapedName": "http-basic", + "rawSpec": "^2.5.1", + "saveSpec": null, + "fetchSpec": "^2.5.1" + }, + "_requiredBy": [ + "/then-request" + ], + "_resolved": "https://registry.npmjs.org/http-basic/-/http-basic-2.5.1.tgz", + "_shasum": "8ce447bdb5b6c577f8a63e3fa78056ec4bb4dbfb", + "_spec": "http-basic@^2.5.1", + "_where": "E:\\Documents\\GitHub\\s5nical\\node_modules\\then-request", + "author": { + "name": "ForbesLindesay" + }, + "bugs": { + "url": "https://github.com/ForbesLindesay/http-basic/issues" + }, + "bundleDependencies": false, + "dependencies": { + "caseless": "~0.11.0", + "concat-stream": "^1.4.6", + "http-response-object": "^1.0.0" + }, + "deprecated": false, + "description": "Very low level wrapper arround http.request/https.request", + "devDependencies": {}, + "homepage": "https://github.com/ForbesLindesay/http-basic#readme", + "keywords": [ + "http", + "https", + "request", + "fetch", + "gzip", + "deflate", + "redirect", + "cache", + "etag", + "cache-control" + ], + "license": "MIT", + "name": "http-basic", + "repository": { + "type": "git", + "url": "git+https://github.com/ForbesLindesay/http-basic.git" + }, + "scripts": { + "test": "node test" + }, + "version": "2.5.1" +} diff --git a/node_modules/http-basic/test/gzip.js b/node_modules/http-basic/test/gzip.js new file mode 100644 index 0000000..086f23c --- /dev/null +++ b/node_modules/http-basic/test/gzip.js @@ -0,0 +1,10 @@ +'use strict'; + +var assert = require('assert'); +var request = require('../'); + +request('GET', 'https://www.yahoo.com', {cache: 'file', followRedirects: true, gzip: true}, function (err, res) { + if (err) throw err; + assert(res.statusCode === 200); + res.body.pipe(process.stdout); +}); diff --git a/node_modules/http-basic/test/index.js b/node_modules/http-basic/test/index.js new file mode 100644 index 0000000..d5c8242 --- /dev/null +++ b/node_modules/http-basic/test/index.js @@ -0,0 +1,89 @@ +'use strict'; + +var assert = require('assert'); +var request = require('../'); + +request('GET', 'http://example.com', function (err, res) { + if (err) throw err; + + console.log('response A'); + assert(res.statusCode === 200); + res.body.resume(); +}); + +request('GET', 'http://example.com:80', function (err, res) { + if (err) throw err; + + console.log('response A1'); + assert(res.statusCode === 200); + res.body.resume(); +}); + + +request('GET', 'https://www.promisejs.org', function (err, res) { + if (err) throw err; + + console.log('response B'); + assert(res.statusCode === 200); + res.body.resume(); +}); + +request('GET', 'https://promisejs.org', {followRedirects: true}, function (err, res) { + if (err) throw err; + + console.log('response C'); + assert(res.statusCode === 200); + res.body.resume(); +}); + +var CACHED = 'https://www.promisejs.org/polyfills/promise-done-1.0.0.js'; + +request('GET', CACHED, {cache: 'memory'}, function (err, res) { + if (err) throw err; + + console.log('response D (populate cache)'); + assert(res.statusCode === 200); + res.body.on('data', function () {}); + res.body.on('end', function () { + request('GET', CACHED, {cache: 'memory'}, function (err, res) { + if (err) throw err; + + console.log('response E (from cache)'); + assert(res.fromCache === true); + assert(res.fromNotModified === false); + assert(res.statusCode === 200); + res.body.resume(); + }); + }); +}); + + + +request('GET', CACHED, {cache: 'file'}, function (err, res) { + if (err) throw err; + + console.log('response G (populate file cache)'); + assert(res.statusCode === 200); + res.body.on('data', function () {}); + res.body.on('end', function () { + setTimeout(function () { + request('GET', CACHED, {cache: 'file'}, function (err, res) { + if (err) throw err; + + console.log('response H (from file cache)'); + assert(res.fromCache === true); + assert(res.fromNotModified === false); + assert(res.statusCode === 200); + res.body.resume(); + }); + }, 1000); + }); +}); + +request('GET', 'https://api.github.com/repos/isaacs/npm', {allowRedirectHeaders: ['User-Agent'], followRedirects: true, headers: {'User-Agent': 'http-basic'}}, function (err, res) { + if (err) throw err; + + console.log('response I'); + assert(res.statusCode === 200); + res.body.resume(); +});
\ No newline at end of file |