123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- var url = require('url');
- var http = require('http');
- var https = require('https');
- var through = require('through2');
- var duplexer = require('duplexer2');
- module.exports = hyperquest;
- function bind (obj, fn) {
- var args = Array.prototype.slice.call(arguments, 2);
- return function () {
- var argv = args.concat(Array.prototype.slice.call(arguments));
- return fn.apply(obj, argv);
- }
- }
- function hyperquest (uri, opts, cb, extra) {
- if (typeof uri === 'object') {
- cb = opts;
- opts = uri;
- uri = undefined;
- }
- if (typeof opts === 'function') {
- cb = opts;
- opts = undefined;
- }
- if (!opts) opts = {};
- if (uri !== undefined) opts.uri = uri;
- if (extra) opts.method = extra.method;
-
- var req = new Req(opts);
- var ws = req.duplex && through();
- var rs = through();
-
- var dup = req.duplex ? duplexer(ws, rs) : rs;
- if (!req.duplex) {
- rs.writable = false;
- }
- dup.request = req;
- dup.setHeader = bind(req, req.setHeader);
- dup.setLocation = bind(req, req.setLocation);
-
- var closed = false;
- dup.on('close', function () { closed = true });
-
- process.nextTick(function () {
- if (closed) return;
- dup.on('close', function () { r.destroy() });
-
- var r = req._send();
- r.on('error', bind(dup, dup.emit, 'error'));
- dup.emit('request', r);
-
- r.on('response', function (res) {
- dup.response = res;
- dup.emit('response', res);
- if (req.duplex) res.pipe(rs)
- else {
- res.on('data', function (buf) { rs.push(buf) });
- res.on('end', function () { rs.push(null) });
- }
- });
-
- if (req.duplex) {
- ws.pipe(r);
- }
- else r.end();
- });
-
- if (cb) {
- dup.on('error', cb);
- dup.on('response', bind(dup, cb, null));
- }
- return dup;
- }
- hyperquest.get = hyperquest;
- hyperquest.post = function (uri, opts, cb) {
- return hyperquest(uri, opts, cb, { method: 'POST' });
- };
- hyperquest.put = function (uri, opts, cb) {
- return hyperquest(uri, opts, cb, { method: 'PUT' });
- };
- hyperquest['delete'] = function (uri, opts, cb) {
- return hyperquest(uri, opts, cb, { method: 'DELETE' });
- };
- function Req (opts) {
- this.headers = opts.headers || {};
-
- var method = (opts.method || 'GET').toUpperCase();
- this.method = method;
- this.duplex = !(method === 'GET' || method === 'DELETE'
- || method === 'HEAD');
- this.auth = opts.auth;
-
- this.options = opts;
-
- if (opts.uri) this.setLocation(opts.uri);
- }
- Req.prototype._send = function () {
- this._sent = true;
-
- var headers = this.headers || {};
- var u = url.parse(this.uri);
- var au = u.auth || this.auth;
- if (au) {
- headers.authorization = 'Basic ' + Buffer(au).toString('base64');
- }
-
- var protocol = u.protocol || '';
- var iface = protocol === 'https:' ? https : http;
- var opts = {
- scheme: protocol.replace(/:$/, ''),
- method: this.method,
- host: u.hostname,
- port: Number(u.port) || (protocol === 'https:' ? 443 : 80),
- path: u.path,
- agent: this.options.agent || false,
- headers: headers,
- withCredentials: this.options.withCredentials
- };
- if (protocol === 'https:') {
- opts.pfx = this.options.pfx;
- opts.key = this.options.key;
- opts.cert = this.options.cert;
- opts.ca = this.options.ca;
- opts.ciphers = this.options.ciphers;
- opts.rejectUnauthorized = this.options.rejectUnauthorized;
- opts.secureProtocol = this.options.secureProtocol;
- }
- var req = iface.request(opts);
- var timeout = this.options.timeout || Math.pow(2, 32) * 1000;
- if (req.setTimeout) req.setTimeout(timeout);
- return req;
- };
- Req.prototype.setHeader = function (key, value) {
- if (this._sent) throw new Error('request already sent');
- this.headers[key] = value;
- return this;
- };
- Req.prototype.setLocation = function (uri) {
- this.uri = uri;
- return this;
- };
|