git-off

git off handles large files in git repos
git clone https://noulin.net/git/git-off.git
Log | Files | Refs | README

node.js (5327B)


      1 var AWS = require('../core');
      2 var Stream = AWS.util.stream.Stream;
      3 var TransformStream = AWS.util.stream.Transform;
      4 var ReadableStream = AWS.util.stream.Readable;
      5 require('../http');
      6 
      7 /**
      8  * @api private
      9  */
     10 AWS.NodeHttpClient = AWS.util.inherit({
     11   handleRequest: function handleRequest(httpRequest, httpOptions, callback, errCallback) {
     12     var self = this;
     13     var cbAlreadyCalled = false;
     14     var endpoint = httpRequest.endpoint;
     15     var pathPrefix = '';
     16     if (!httpOptions) httpOptions = {};
     17     if (httpOptions.proxy) {
     18       pathPrefix = endpoint.protocol + '//' + endpoint.hostname;
     19       if (endpoint.port !== 80 && endpoint.port !== 443) {
     20         pathPrefix += ':' + endpoint.port;
     21       }
     22       endpoint = new AWS.Endpoint(httpOptions.proxy);
     23     }
     24 
     25     var useSSL = endpoint.protocol === 'https:';
     26     var http = useSSL ? require('https') : require('http');
     27     var options = {
     28       host: endpoint.hostname,
     29       port: endpoint.port,
     30       method: httpRequest.method,
     31       headers: httpRequest.headers,
     32       path: pathPrefix + httpRequest.path
     33     };
     34 
     35     if (useSSL && !httpOptions.agent) {
     36       options.agent = this.sslAgent();
     37     }
     38 
     39     AWS.util.update(options, httpOptions);
     40     delete options.proxy; // proxy isn't an HTTP option
     41     delete options.timeout; // timeout isn't an HTTP option
     42 
     43     var stream = http.request(options, function (httpResp) {
     44       if (cbAlreadyCalled) return; cbAlreadyCalled = true;
     45 
     46       callback(httpResp);
     47       httpResp.emit('headers', httpResp.statusCode, httpResp.headers);
     48     });
     49     httpRequest.stream = stream; // attach stream to httpRequest
     50 
     51     // timeout support
     52     stream.setTimeout(httpOptions.timeout || 0, function() {
     53       if (cbAlreadyCalled) return; cbAlreadyCalled = true;
     54 
     55       var msg = 'Connection timed out after ' + httpOptions.timeout + 'ms';
     56       errCallback(AWS.util.error(new Error(msg), {code: 'TimeoutError'}));
     57       stream.abort();
     58     });
     59 
     60     stream.on('error', function() {
     61       if (cbAlreadyCalled) return; cbAlreadyCalled = true;
     62       errCallback.apply(this, arguments);
     63     });
     64 
     65     var expect = httpRequest.headers.Expect || httpRequest.headers.expect;
     66     if (expect === '100-continue') {
     67       stream.on('continue', function() {
     68         self.writeBody(stream, httpRequest);
     69       });
     70     } else {
     71       this.writeBody(stream, httpRequest);
     72     }
     73 
     74     return stream;
     75   },
     76 
     77   writeBody: function writeBody(stream, httpRequest) {
     78     var body = httpRequest.body;
     79     var totalBytes = parseInt(httpRequest.headers['Content-Length'], 10);
     80 
     81     if (body instanceof Stream) {
     82       // For progress support of streaming content -
     83       // pipe the data through a transform stream to emit 'sendProgress' events
     84       var progressStream = this.progressStream(stream, totalBytes);
     85       if (progressStream) {
     86         body.pipe(progressStream).pipe(stream);
     87       } else {
     88         body.pipe(stream);
     89       }
     90     } else if (body) {
     91       // The provided body is a buffer/string and is already fully available in memory -
     92       // For performance it's best to send it as a whole by calling stream.end(body),
     93       // Callers expect a 'sendProgress' event which is best emitted once
     94       // the http request stream has been fully written and all data flushed.
     95       // The use of totalBytes is important over body.length for strings where
     96       // length is char length and not byte length.
     97       stream.once('finish', function() {
     98         stream.emit('sendProgress', {
     99           loaded: totalBytes,
    100           total: totalBytes
    101         });
    102       });
    103       stream.end(body);
    104     } else {
    105       // no request body
    106       stream.end();
    107     }
    108   },
    109 
    110   sslAgent: function sslAgent() {
    111     var https = require('https');
    112 
    113     if (!AWS.NodeHttpClient.sslAgent) {
    114       AWS.NodeHttpClient.sslAgent = new https.Agent({rejectUnauthorized: true});
    115       AWS.NodeHttpClient.sslAgent.setMaxListeners(0);
    116 
    117       // delegate maxSockets to globalAgent, set a default limit of 50 if current value is Infinity.
    118       // Users can bypass this default by supplying their own Agent as part of SDK configuration.
    119       Object.defineProperty(AWS.NodeHttpClient.sslAgent, 'maxSockets', {
    120         enumerable: true,
    121         get: function() {
    122           var defaultMaxSockets = 50;
    123           var globalAgent = https.globalAgent;
    124           if (globalAgent && globalAgent.maxSockets !== Infinity && typeof globalAgent.maxSockets === 'number') {
    125             return globalAgent.maxSockets;
    126           }
    127           return defaultMaxSockets;
    128         }
    129       });
    130     }
    131     return AWS.NodeHttpClient.sslAgent;
    132   },
    133 
    134   progressStream: function progressStream(stream, totalBytes) {
    135     if (typeof TransformStream === 'undefined') {
    136       // for node 0.8 there is no streaming progress
    137       return;
    138     }
    139     var loadedBytes = 0;
    140     var reporter = new TransformStream();
    141     reporter._transform = function(chunk, encoding, callback) {
    142       if (chunk) {
    143         loadedBytes += chunk.length;
    144         stream.emit('sendProgress', {
    145           loaded: loadedBytes,
    146           total: totalBytes
    147         });
    148       }
    149       callback(null, chunk);
    150     };
    151     return reporter;
    152   },
    153 
    154   emitter: null
    155 });
    156 
    157 /**
    158  * @!ignore
    159  */
    160 
    161 /**
    162  * @api private
    163  */
    164 AWS.HttpClient.prototype = AWS.NodeHttpClient.prototype;
    165 
    166 /**
    167  * @api private
    168  */
    169 AWS.HttpClient.streamsApiVersion = ReadableStream ? 2 : 1;