mirror of
https://github.com/Instadapp/Swap-Aggregator-Subgraph.git
synced 2024-07-29 21:57:12 +00:00
362 lines
9.5 KiB
JavaScript
362 lines
9.5 KiB
JavaScript
function parseJSON(s) {
|
|
try {
|
|
return JSON.parse(s);
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
var querystring = require('querystring'),
|
|
http = require('./http'),
|
|
fs = require('fs'),
|
|
path = require('path'),
|
|
url = require('url'),
|
|
stream = require('readable-stream'),
|
|
HttpDuplex = require('./http_duplex'),
|
|
debug = require('debug')('modem'),
|
|
util = require('util'),
|
|
splitca = require('split-ca'),
|
|
JSONStream = require('JSONStream'),
|
|
isWin = require('os').type() === 'Windows_NT';
|
|
|
|
var defaultOpts = function() {
|
|
var split;
|
|
var opts = {};
|
|
|
|
if (!process.env.DOCKER_HOST) {
|
|
// Windows socket path: //./pipe/docker_engine ( Windows 10 )
|
|
// Linux & Darwin socket path: /var/run/docker.sock
|
|
opts.socketPath = isWin ? '//./pipe/docker_engine' : '/var/run/docker.sock';
|
|
} else if (process.env.DOCKER_HOST.indexOf('unix://') === 0) {
|
|
// Strip off unix://, fall back to default of /var/run/docker.sock if
|
|
// unix:// was passed without a path
|
|
opts.socketPath = process.env.DOCKER_HOST.substring(7) || '/var/run/docker.sock';
|
|
} else {
|
|
split = /(?:tcp:\/\/)?(.*?):([0-9]+)/g.exec(process.env.DOCKER_HOST);
|
|
|
|
if (!split || split.length !== 3) {
|
|
throw new Error('DOCKER_HOST env variable should be something like tcp://localhost:1234');
|
|
}
|
|
|
|
opts.port = split[2];
|
|
|
|
if (process.env.DOCKER_TLS_VERIFY === '1' || opts.port === '2376') {
|
|
opts.protocol = 'https';
|
|
} else {
|
|
opts.protocol = 'http';
|
|
}
|
|
|
|
opts.host = split[1];
|
|
|
|
if (process.env.DOCKER_CERT_PATH) {
|
|
opts.ca = splitca(path.join(process.env.DOCKER_CERT_PATH, 'ca.pem'));
|
|
opts.cert = fs.readFileSync(path.join(process.env.DOCKER_CERT_PATH, 'cert.pem'));
|
|
opts.key = fs.readFileSync(path.join(process.env.DOCKER_CERT_PATH, 'key.pem'));
|
|
}
|
|
|
|
if (process.env.DOCKER_CLIENT_TIMEOUT) {
|
|
opts.timeout = parseInt(process.env.DOCKER_CLIENT_TIMEOUT, 10);
|
|
}
|
|
}
|
|
|
|
return opts;
|
|
};
|
|
|
|
var Modem = function(opts) {
|
|
if (!opts || (Object.keys(opts).length === 0 && opts.constructor === Object)) {
|
|
opts = defaultOpts();
|
|
}
|
|
|
|
this.socketPath = opts.socketPath;
|
|
this.host = opts.host;
|
|
this.port = opts.port;
|
|
this.version = opts.version;
|
|
this.key = opts.key;
|
|
this.cert = opts.cert;
|
|
this.ca = opts.ca;
|
|
this.timeout = opts.timeout;
|
|
this.checkServerIdentity = opts.checkServerIdentity;
|
|
|
|
if (this.key && this.cert && this.ca) {
|
|
this.protocol = 'https';
|
|
}
|
|
this.protocol = opts.protocol || this.protocol || 'http';
|
|
};
|
|
|
|
Modem.prototype.dial = function(options, callback) {
|
|
var opts, address, data;
|
|
var self = this;
|
|
|
|
if (options.options) {
|
|
opts = options.options;
|
|
}
|
|
|
|
// Prevent credentials from showing up in URL
|
|
if (opts && opts.authconfig) {
|
|
delete opts.authconfig;
|
|
}
|
|
|
|
if (this.version) {
|
|
options.path = '/' + this.version + options.path;
|
|
}
|
|
|
|
if (this.host) {
|
|
var parsed = url.parse(self.host);
|
|
address = url.format({
|
|
'protocol': parsed.protocol || self.protocol,
|
|
'hostname': parsed.hostname || self.host,
|
|
'port': self.port
|
|
});
|
|
address = url.resolve(address, options.path);
|
|
} else {
|
|
address = options.path;
|
|
}
|
|
|
|
if (options.path.indexOf('?') !== -1) {
|
|
if (opts && Object.keys(opts).length > 0) {
|
|
address += this.buildQuerystring(opts._query || opts);
|
|
} else {
|
|
address = address.substring(0, address.length - 1);
|
|
}
|
|
}
|
|
|
|
var optionsf = {
|
|
path: address,
|
|
method: options.method,
|
|
headers: options.headers || {},
|
|
key: self.key,
|
|
cert: self.cert,
|
|
ca: self.ca
|
|
};
|
|
|
|
if (this.checkServerIdentity) {
|
|
optionsf.checkServerIdentity = this.checkServerIdentity;
|
|
}
|
|
|
|
if (options.authconfig) {
|
|
optionsf.headers['X-Registry-Auth'] = options.authconfig.key || options.authconfig.base64 ||
|
|
new Buffer(JSON.stringify(options.authconfig)).toString('base64');
|
|
}
|
|
|
|
if (options.registryconfig) {
|
|
optionsf.headers['X-Registry-Config'] = options.registryconfig.base64 ||
|
|
new Buffer(JSON.stringify(options.registryconfig)).toString('base64');
|
|
}
|
|
|
|
if (options.file) {
|
|
if (typeof options.file === 'string') {
|
|
data = fs.createReadStream(path.resolve(options.file));
|
|
} else {
|
|
data = options.file;
|
|
}
|
|
optionsf.headers['Content-Type'] = 'application/tar';
|
|
} else if (opts && options.method === 'POST') {
|
|
data = JSON.stringify(opts._body || opts);
|
|
if(options.allowEmpty) {
|
|
optionsf.headers['Content-Type'] = 'application/json';
|
|
} else {
|
|
if (data !== '{}' && data !== '""') {
|
|
optionsf.headers['Content-Type'] = 'application/json';
|
|
} else {
|
|
data = undefined;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (typeof data === "string") {
|
|
optionsf.headers['Content-Length'] = Buffer.byteLength(data);
|
|
} else if (Buffer.isBuffer(data) === true) {
|
|
optionsf.headers['Content-Length'] = data.length;
|
|
} else if (optionsf.method === 'PUT' || options.hijack || options.openStdin) {
|
|
optionsf.headers['Transfer-Encoding'] = 'chunked';
|
|
}
|
|
|
|
if (options.hijack) {
|
|
optionsf.headers.Connection = 'Upgrade';
|
|
optionsf.headers.Upgrade = 'tcp';
|
|
}
|
|
|
|
if (this.socketPath) {
|
|
optionsf.socketPath = this.socketPath;
|
|
} else {
|
|
var urlp = url.parse(address);
|
|
optionsf.hostname = urlp.hostname;
|
|
optionsf.port = urlp.port;
|
|
optionsf.path = urlp.path;
|
|
}
|
|
|
|
this.buildRequest(optionsf, options, data, callback);
|
|
};
|
|
|
|
Modem.prototype.buildRequest = function(options, context, data, callback) {
|
|
var self = this;
|
|
var req = http[self.protocol].request(options, function() {});
|
|
|
|
debug('Sending: %s', util.inspect(options, {
|
|
showHidden: true,
|
|
depth: null
|
|
}));
|
|
|
|
if (self.timeout) {
|
|
req.on('socket', function(socket) {
|
|
socket.setTimeout(self.timeout);
|
|
socket.on('timeout', function() {
|
|
debug('Timeout of %s ms exceeded', self.timeout);
|
|
req.abort();
|
|
});
|
|
});
|
|
}
|
|
|
|
if (context.hijack === true) {
|
|
req.on('upgrade', function(res, sock, head) {
|
|
return callback(null, sock);
|
|
});
|
|
}
|
|
|
|
req.on('response', function(res) {
|
|
if (context.isStream === true) {
|
|
self.buildPayload(null, context.isStream, context.statusCodes, context.openStdin, req, res, null, callback);
|
|
} else {
|
|
var chunks = [];
|
|
res.on('data', function(chunk) {
|
|
chunks.push(chunk);
|
|
});
|
|
|
|
res.on('end', function() {
|
|
var buffer = Buffer.concat(chunks);
|
|
var result = buffer.toString();
|
|
|
|
debug('Received: %s', result);
|
|
|
|
var json = parseJSON(result) || result;
|
|
self.buildPayload(null, context.isStream, context.statusCodes, false, req, res, json, callback);
|
|
});
|
|
}
|
|
});
|
|
|
|
req.on('error', function(error) {
|
|
self.buildPayload(error, context.isStream, context.statusCodes, false, {}, {}, null, callback);
|
|
});
|
|
|
|
if (typeof data === "string" || Buffer.isBuffer(data)) {
|
|
req.write(data);
|
|
} else if (data) {
|
|
data.pipe(req);
|
|
}
|
|
|
|
if (!context.hijack && !context.openStdin && (typeof data === "string" || data === undefined || Buffer.isBuffer(data))) {
|
|
req.end();
|
|
}
|
|
};
|
|
|
|
Modem.prototype.buildPayload = function(err, isStream, statusCodes, openStdin, req, res, json, cb) {
|
|
if (err) return cb(err, null);
|
|
|
|
if (statusCodes[res.statusCode] !== true) {
|
|
getCause(isStream, res, json, function(err, cause) {
|
|
var msg = new Error(
|
|
'(HTTP code ' + res.statusCode + ') ' +
|
|
(statusCodes[res.statusCode] || 'unexpected') + ' - ' +
|
|
(cause.message || cause) + ' '
|
|
);
|
|
msg.reason = statusCodes[res.statusCode];
|
|
msg.statusCode = res.statusCode;
|
|
msg.json = json;
|
|
cb(msg, null);
|
|
});
|
|
} else {
|
|
if (openStdin) {
|
|
cb(null, new HttpDuplex(req, res));
|
|
} else if (isStream) {
|
|
cb(null, res);
|
|
} else {
|
|
cb(null, json);
|
|
}
|
|
}
|
|
|
|
function getCause(isStream, res, json, callback) {
|
|
var chunks = '';
|
|
if (isStream) {
|
|
res.on('data', function(chunk) {
|
|
chunks += chunk;
|
|
});
|
|
res.on('end', function() {
|
|
callback(null, parseJSON(chunks) || chunks);
|
|
});
|
|
} else {
|
|
callback(null, json);
|
|
}
|
|
}
|
|
};
|
|
|
|
Modem.prototype.demuxStream = function(stream, stdout, stderr) {
|
|
var header = null;
|
|
|
|
stream.on('readable', function() {
|
|
header = header || stream.read(8);
|
|
while (header !== null) {
|
|
var type = header.readUInt8(0);
|
|
var payload = stream.read(header.readUInt32BE(4));
|
|
if (payload === null) break;
|
|
if (type == 2) {
|
|
stderr.write(payload);
|
|
} else {
|
|
stdout.write(payload);
|
|
}
|
|
header = stream.read(8);
|
|
}
|
|
});
|
|
};
|
|
|
|
Modem.prototype.followProgress = function(stream, onFinished, onProgress) {
|
|
var parser = JSONStream.parse(),
|
|
output = [];
|
|
|
|
parser.on('data', onStreamEvent);
|
|
parser.on('error', onStreamError);
|
|
parser.on('end', onStreamEnd);
|
|
|
|
stream.pipe(parser);
|
|
|
|
function onStreamEvent(evt) {
|
|
if (!(evt instanceof Object)) {
|
|
evt = {};
|
|
}
|
|
|
|
output.push(evt);
|
|
|
|
if (evt.error) {
|
|
return onStreamError(evt.error);
|
|
}
|
|
|
|
if (onProgress) {
|
|
onProgress(evt);
|
|
}
|
|
}
|
|
|
|
function onStreamError(err) {
|
|
parser.removeListener('data', onStreamEvent);
|
|
parser.removeListener('error', onStreamError);
|
|
parser.removeListener('end', onStreamEnd);
|
|
onFinished(err, output);
|
|
}
|
|
|
|
function onStreamEnd() {
|
|
onFinished(null, output);
|
|
}
|
|
};
|
|
|
|
Modem.prototype.buildQuerystring = function(opts) {
|
|
var clone = {};
|
|
|
|
// serialize map values as JSON strings, else querystring truncates.
|
|
Object.keys(opts).map(function(key, i) {
|
|
clone[key] = (opts[key] && typeof opts[key] === 'object' && key !== 't') ?
|
|
JSON.stringify(opts[key]) : opts[key];
|
|
});
|
|
|
|
return querystring.stringify(clone);
|
|
};
|
|
|
|
module.exports = Modem;
|