diff options
| author | 8cy <[email protected]> | 2020-04-03 02:37:42 -0700 |
|---|---|---|
| committer | 8cy <[email protected]> | 2020-04-03 02:37:42 -0700 |
| commit | 60867fb030bae582082340ead7dbc7efdc2f5398 (patch) | |
| tree | 4c6a7356351be2e4914e15c4703172597c45656e /node_modules/snekfetch/src/node/index.js | |
| parent | commenting (diff) | |
| download | s5nical-60867fb030bae582082340ead7dbc7efdc2f5398.tar.xz s5nical-60867fb030bae582082340ead7dbc7efdc2f5398.zip | |
2020/04/03, 02:34, v1.2.0
Diffstat (limited to 'node_modules/snekfetch/src/node/index.js')
| -rw-r--r-- | node_modules/snekfetch/src/node/index.js | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/node_modules/snekfetch/src/node/index.js b/node_modules/snekfetch/src/node/index.js new file mode 100644 index 0000000..ae9cbc0 --- /dev/null +++ b/node_modules/snekfetch/src/node/index.js @@ -0,0 +1,151 @@ +const zlib = require('zlib'); +const http = require('http'); +const https = require('https'); +const URL = require('url'); +const Stream = require('stream'); +const FormData = require('./FormData'); + +const Package = require('../../package.json'); + +const transports = { + 'http:': http, + 'https:': https, + 'file:': require('./transports/file'), +}; + +function buildRequest(method, url) { + /* istanbul ignore next */ + this._read = () => { + this.resume(); + if (this._response) + return; + this.catch((err) => this.emit('error', err)); + }; + + this.options.lastBuiltUrl = url; + + const options = URL.parse(url); + options.encoding = 'utf8'; + + if (!options.protocol) + throw new Error('URL must have a valid protocol'); + + const transport = transports[options.protocol]; + options.method = method.toUpperCase(); + + if (this.options.headers) + options.headers = this.options.headers; + + if (this.options.agent) + options.agent = this.options.agent; + else if (transport.Agent && this.options.followRedirects !== false) + options.agent = new transport.Agent({ keepAlive: true }); + + if (options.port) + options.port = parseInt(options.port); + + this.options._req = options; + const request = transport.request(options); + if (request.setNoDelay) + request.setNoDelay(true); + return request; +} + +function finalizeRequest() { + return new Promise((resolve, reject) => { + const request = this.request; + + let socket; + + const handleError = (err) => { + if (!err) + err = new Error('Unknown error occured'); + err.request = request; + reject(err); + if (socket) + socket.removeListener('error', handleError); + }; + + request.once('abort', handleError); + request.once('error', handleError); + request.once('socket', (s) => { + socket = s; + s.once('error', handleError); + }); + + request.once('response', (response) => { + if (socket) + socket.removeListener('error', handleError); + let stream = response; + if (shouldUnzip(response)) { + stream = response.pipe(zlib.createUnzip({ + flush: zlib.Z_SYNC_FLUSH, + finishFlush: zlib.Z_SYNC_FLUSH, + })); + } + + if (this.options.followRedirects !== false && [301, 302, 303, 307, 308].includes(response.statusCode)) { + resolve({ + response, + redirect: URL.resolve(this.options.lastBuiltUrl, response.headers.location), + }); + response.destroy(); + } else { + const body = []; + + stream.on('data', (chunk) => { + if (!this.push(chunk)) + this.pause(); + body.push(chunk); + }); + + stream.once('end', () => { + this.push(null); + const raw = Buffer.concat(body); + resolve({ response, raw, redirect: false }); + }); + } + }); + + if (!this.request.getHeader('user-agent')) + this.set('User-Agent', `snekfetch/${Package.version} (${Package.homepage})`); + + this._finalizeRequest(); + let data = this.data; + if (data && data.end) + data = data.end(); + if (Array.isArray(data)) { + for (const chunk of data) + request.write(chunk); + request.end(); + } else if (data instanceof Stream) { + data.pipe(request); + } else if (data instanceof Buffer) { + request.end(data); + } else if (data) { + request.end(data); + } else { + request.end(); + } + }); +} + +function shouldSendRaw(data) { + return data instanceof Buffer || data instanceof Stream; +} + +function shouldUnzip(res) { + if (res.statusCode === 204 || res.statusCode === 304) + return false; + if (res.headers['content-length'] === '0') + return false; + return /^\s*(?:deflate|gzip)\s*$/.test(res.headers['content-encoding']); +} + +module.exports = { + buildRequest, finalizeRequest, shouldSendRaw, + METHODS: http.METHODS, + STATUS_CODES: http.STATUS_CODES, + FormData, + Extension: Stream.Readable, +}; |