summaryrefslogtreecommitdiff
path: root/node_modules/snekfetch/src/node/transports
diff options
context:
space:
mode:
author8cy <[email protected]>2020-04-03 02:37:42 -0700
committer8cy <[email protected]>2020-04-03 02:37:42 -0700
commit60867fb030bae582082340ead7dbc7efdc2f5398 (patch)
tree4c6a7356351be2e4914e15c4703172597c45656e /node_modules/snekfetch/src/node/transports
parentcommenting (diff)
downloads5nical-60867fb030bae582082340ead7dbc7efdc2f5398.tar.xz
s5nical-60867fb030bae582082340ead7dbc7efdc2f5398.zip
2020/04/03, 02:34, v1.2.0
Diffstat (limited to 'node_modules/snekfetch/src/node/transports')
-rw-r--r--node_modules/snekfetch/src/node/transports/ResponseStream.js24
-rw-r--r--node_modules/snekfetch/src/node/transports/file.js113
-rw-r--r--node_modules/snekfetch/src/node/transports/http2.js102
3 files changed, 239 insertions, 0 deletions
diff --git a/node_modules/snekfetch/src/node/transports/ResponseStream.js b/node_modules/snekfetch/src/node/transports/ResponseStream.js
new file mode 100644
index 0000000..1d40101
--- /dev/null
+++ b/node_modules/snekfetch/src/node/transports/ResponseStream.js
@@ -0,0 +1,24 @@
+const Stream = require('stream');
+
+class ResponseStream extends Stream.Readable {
+ constructor() {
+ super();
+ this.statusCode = 200;
+ this.status = 'OK';
+ }
+
+ error(code, message) {
+ this.statusCode = code;
+ this.status = message;
+ return this;
+ }
+
+ on(event, handler) {
+ if (['end', 'open'].includes(event))
+ handler();
+ }
+
+ _read() {} // eslint-disable-line no-empty-function
+}
+
+module.exports = ResponseStream;
diff --git a/node_modules/snekfetch/src/node/transports/file.js b/node_modules/snekfetch/src/node/transports/file.js
new file mode 100644
index 0000000..a30c5fe
--- /dev/null
+++ b/node_modules/snekfetch/src/node/transports/file.js
@@ -0,0 +1,113 @@
+const fs = require('fs');
+const path = require('path');
+const mime = require('../mime');
+const EventEmitter = require('events');
+const ResponseStream = require('./ResponseStream');
+
+const methods = {
+ GET: (filename, req) => {
+ req.end = () => {
+ const stream = should404(filename) ?
+ new ResponseStream().error(404, `ENOENT: no such file or directory, open '${filename}'`) :
+ fs.createReadStream(filename);
+ req.res = stream;
+ stream.headers = {
+ 'content-length': 0,
+ 'content-type': mime.lookup(path.extname(filename)),
+ };
+ stream.on('open', () => {
+ req.emit('response', stream);
+ });
+ if (stream instanceof ResponseStream)
+ return;
+ stream.statusCode = 200;
+ stream.on('end', () => {
+ stream.headers['content-length'] = stream.bytesRead;
+ });
+ /* istanbul ignore next */
+ stream.on('error', (err) => {
+ stream.statusCode = 400;
+ stream.status = err.message;
+ });
+ };
+ },
+ POST: (filename, req) => {
+ const chunks = [];
+ /* istanbul ignore next */
+ req.write = (data) => {
+ chunks.push(data);
+ };
+ req.end = (data) => {
+ chunks.push(data);
+ const stream = fs.createWriteStream(filename);
+ const standin = new ResponseStream();
+ req.res = standin;
+ standin.headers = {
+ 'content-length': 0,
+ 'content-type': mime.lookup(path.extname(filename)),
+ };
+ stream.on('finish', () => {
+ req.emit('response', standin);
+ });
+ stream.on('open', () => {
+ (function write() {
+ const chunk = chunks.shift();
+ if (!chunk)
+ return;
+ /* istanbul ignore next */
+ if (!stream.write(chunk))
+ stream.once('drain', write);
+ else
+ write();
+ }());
+ stream.end();
+ });
+ };
+ },
+ DELETE: (filename, req) => {
+ req.end = () => {
+ const stream = new ResponseStream();
+ req.res = stream;
+ stream.headers = {
+ 'content-length': 0,
+ 'content-type': mime.lookup(path.extname(filename)),
+ };
+ fs.unlink(filename, (err) => {
+ req.emit('response', err ? stream.error(400, err.message) : stream);
+ });
+ };
+ },
+};
+
+class Req extends EventEmitter {
+ constructor() {
+ super();
+ this._headers = {};
+ }
+
+ setHeader() {} // eslint-disable-line no-empty-function
+ getHeader() {} // eslint-disable-line no-empty-function
+}
+
+function request(options) {
+ const method = methods[options.method];
+ if (!method)
+ throw new Error(`Invalid request method for file: "${options.method}"`);
+ const filename = options.href.replace('file://', '');
+
+ const req = new Req();
+ method(filename, req, options);
+ return req;
+}
+
+function should404(p) {
+ try {
+ return fs.lstatSync(p).isDirectory();
+ } catch (err) {
+ return true;
+ }
+}
+
+module.exports = {
+ request,
+};
diff --git a/node_modules/snekfetch/src/node/transports/http2.js b/node_modules/snekfetch/src/node/transports/http2.js
new file mode 100644
index 0000000..326b32e
--- /dev/null
+++ b/node_modules/snekfetch/src/node/transports/http2.js
@@ -0,0 +1,102 @@
+const http = require('http');
+const Stream = require('stream');
+const EventEmitter = require('events');
+const http2 = (() => {
+ try {
+ const h2 = require('http2');
+ if (!h2.constants)
+ throw new Error('DAMN_YOU_NPM_HTTP2');
+ return h2;
+ } catch (err) {
+ return {
+ constants: {},
+ connect: () => {
+ throw new Error('Please run node with --expose-http2 to use the http2 request transport');
+ },
+ };
+ }
+})();
+
+const {
+ HTTP2_HEADER_PATH,
+ HTTP2_HEADER_METHOD,
+ HTTP2_HEADER_STATUS,
+} = http2.constants;
+
+class Http2Request extends EventEmitter {
+ constructor(options) {
+ super();
+ this.options = options;
+ this._headers = {
+ [HTTP2_HEADER_PATH]: options.pathname,
+ [HTTP2_HEADER_METHOD]: options.method.toUpperCase(),
+ };
+ }
+
+ setHeader(name, value) {
+ this._headers[name.toLowerCase()] = value;
+ }
+
+ getHeader(name) {
+ return this._headers[name];
+ }
+
+ getHeaders() {
+ return this._headers;
+ }
+
+ get path() {
+ return this._headers[HTTP2_HEADER_PATH];
+ }
+
+ set path(path) {
+ this._headers[HTTP2_HEADER_PATH] = path;
+ }
+
+ end(data) {
+ const options = this.options;
+ const client = http2.connect(`${options.protocol}//${options.hostname}`);
+ const req = client.request(this._headers);
+ const stream = new Stream.PassThrough();
+
+ client.once('error', (e) => this.emit('error', e));
+ client.once('frameError', (e) => this.emit('error', e));
+
+ req.once('error', (e) => this.emit('error', e));
+
+ req.once('response', (headers) => {
+ stream.headers = headers;
+ stream.statusCode = headers[HTTP2_HEADER_STATUS];
+ stream.status = http.STATUS_CODES[stream.statusCode];
+
+ this.emit('response', stream);
+ this.response = stream;
+
+ req.on('data', (chunk) => {
+ if (!stream.push(chunk))
+ req.pause();
+ });
+
+ req.once('end', () => {
+ stream.push(null);
+ client.destroy();
+ });
+
+ stream.once('error', (err) => {
+ stream.statusCode = 400;
+ stream.status = err.message;
+ });
+ });
+
+ req.end(data);
+
+ return req;
+ }
+}
+
+
+function request(options) {
+ return new Http2Request(options);
+}
+
+module.exports = { request };