tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

http.js (43660B)


      1 // Public API
      2 // ==========
      3 
      4 // The main governing power behind the http2 API design is that it should look very similar to the
      5 // existing node.js [HTTPS API][1] (which is, in turn, almost identical to the [HTTP API][2]). The
      6 // additional features of HTTP/2 are exposed as extensions to this API. Furthermore, node-http2
      7 // should fall back to using HTTP/1.1 if needed. Compatibility with undocumented or deprecated
      8 // elements of the node.js HTTP/HTTPS API is a non-goal.
      9 //
     10 // Additional and modified API elements
     11 // ------------------------------------
     12 //
     13 // - **Class: http2.Endpoint**: an API for using the raw HTTP/2 framing layer. For documentation
     14 //   see [protocol/endpoint.js](protocol/endpoint.html).
     15 //
     16 // - **Class: http2.Server**
     17 //   - **Event: 'connection' (socket, [endpoint])**: there's a second argument if the negotiation of
     18 //     HTTP/2 was successful: the reference to the [Endpoint](protocol/endpoint.html) object tied to the
     19 //     socket.
     20 //
     21 // - **http2.createServer(options, [requestListener])**: additional option:
     22 //   - **log**: an optional [bunyan](https://github.com/trentm/node-bunyan) logger object
     23 //
     24 // - **Class: http2.ServerResponse**
     25 //   - **response.push(options)**: initiates a server push. `options` describes the 'imaginary'
     26 //     request to which the push stream is a response; the possible options are identical to the
     27 //     ones accepted by `http2.request`. Returns a ServerResponse object that can be used to send
     28 //     the response headers and content.
     29 //
     30 // - **Class: http2.Agent**
     31 //   - **new Agent(options)**: additional option:
     32 //     - **log**: an optional [bunyan](https://github.com/trentm/node-bunyan) logger object
     33 //   - **agent.sockets**: only contains TCP sockets that corresponds to HTTP/1 requests.
     34 //   - **agent.endpoints**: contains [Endpoint](protocol/endpoint.html) objects for HTTP/2 connections.
     35 //
     36 // - **http2.request(options, [callback])**:
     37 //   - similar to http.request
     38 //
     39 // - **http2.get(options, [callback])**:
     40 //   - similar to http.get
     41 //
     42 // - **Class: http2.ClientRequest**
     43 //   - **Event: 'socket' (socket)**: in case of an HTTP/2 incoming message, `socket` is a reference
     44 //     to the associated [HTTP/2 Stream](protocol/stream.html) object (and not to the TCP socket).
     45 //   - **Event: 'push' (promise)**: signals the intention of a server push associated to this
     46 //     request. `promise` is an IncomingPromise. If there's no listener for this event, the server
     47 //     push is cancelled.
     48 //   - **request.setPriority(priority)**: assign a priority to this request. `priority` is a number
     49 //     between 0 (highest priority) and 2^31-1 (lowest priority). Default value is 2^30.
     50 //
     51 // - **Class: http2.IncomingMessage**
     52 //   - has two subclasses for easier interface description: **IncomingRequest** and
     53 //     **IncomingResponse**
     54 //   - **message.socket**: in case of an HTTP/2 incoming message, it's a reference to the associated
     55 //     [HTTP/2 Stream](protocol/stream.html) object (and not to the TCP socket).
     56 //
     57 // - **Class: http2.IncomingRequest (IncomingMessage)**
     58 //   - **message.url**: in case of an HTTP/2 incoming request, the `url` field always contains the
     59 //     path, and never a full url (it contains the path in most cases in the HTTPS api as well).
     60 //   - **message.scheme**: additional field. Mandatory HTTP/2 request metadata.
     61 //   - **message.host**: additional field. Mandatory HTTP/2 request metadata. Note that this
     62 //     replaces the old Host header field, but node-http2 will add Host to the `message.headers` for
     63 //     backwards compatibility.
     64 //
     65 // - **Class: http2.IncomingPromise (IncomingRequest)**
     66 //   - contains the metadata of the 'imaginary' request to which the server push is an answer.
     67 //   - **Event: 'response' (response)**: signals the arrival of the actual push stream. `response`
     68 //     is an IncomingResponse.
     69 //   - **Event: 'push' (promise)**: signals the intention of a server push associated to this
     70 //     request. `promise` is an IncomingPromise. If there's no listener for this event, the server
     71 //     push is cancelled.
     72 //   - **promise.cancel()**: cancels the promised server push.
     73 //   - **promise.setPriority(priority)**: assign a priority to this push stream. `priority` is a
     74 //     number between 0 (highest priority) and 2^31-1 (lowest priority). Default value is 2^30.
     75 //
     76 // API elements not yet implemented
     77 // --------------------------------
     78 //
     79 // - **Class: http2.Server**
     80 //   - **server.maxHeadersCount**
     81 //
     82 // API elements that are not applicable to HTTP/2
     83 // ----------------------------------------------
     84 //
     85 // The reason may be deprecation of certain HTTP/1.1 features, or that some API elements simply
     86 // don't make sense when using HTTP/2. These will not be present when a request is done with HTTP/2,
     87 // but will function normally when falling back to using HTTP/1.1.
     88 //
     89 // - **Class: http2.Server**
     90 //   - **Event: 'checkContinue'**: not in the spec
     91 //   - **Event: 'upgrade'**: upgrade is deprecated in HTTP/2
     92 //   - **Event: 'timeout'**: HTTP/2 sockets won't timeout because of application level keepalive
     93 //     (PING frames)
     94 //   - **Event: 'connect'**: not yet supported
     95 //   - **server.setTimeout(msecs, [callback])**
     96 //   - **server.timeout**
     97 //
     98 // - **Class: http2.ServerResponse**
     99 //   - **Event: 'close'**
    100 //   - **Event: 'timeout'**
    101 //   - **response.writeContinue()**
    102 //   - **response.writeHead(statusCode, [reasonPhrase], [headers])**: reasonPhrase will always be
    103 //     ignored since [it's not supported in HTTP/2][3]
    104 //   - **response.setTimeout(timeout, [callback])**
    105 //
    106 // - **Class: http2.Agent**
    107 //   - **agent.maxSockets**: only affects HTTP/1 connection pool. When using HTTP/2, there's always
    108 //     one connection per host.
    109 //
    110 // - **Class: http2.ClientRequest**
    111 //   - **Event: 'upgrade'**
    112 //   - **Event: 'connect'**
    113 //   - **Event: 'continue'**
    114 //   - **request.setTimeout(timeout, [callback])**
    115 //   - **request.setNoDelay([noDelay])**
    116 //   - **request.setSocketKeepAlive([enable], [initialDelay])**
    117 //
    118 // - **Class: http2.IncomingMessage**
    119 //   - **Event: 'close'**
    120 //   - **message.setTimeout(timeout, [callback])**
    121 //
    122 // [1]: https://nodejs.org/api/https.html
    123 // [2]: https://nodejs.org/api/http.html
    124 // [3]: https://tools.ietf.org/html/rfc7540#section-8.1.2.4
    125 
    126 // Common server and client side code
    127 // ==================================
    128 
    129 var net = require('net');
    130 var url = require('url');
    131 var util = require('util');
    132 var EventEmitter = require('events').EventEmitter;
    133 var PassThrough = require('stream').PassThrough;
    134 var Readable = require('stream').Readable;
    135 var Writable = require('stream').Writable;
    136 var protocol = require('./protocol');
    137 var Endpoint = protocol.Endpoint;
    138 var http = require('http');
    139 var https = require('https');
    140 
    141 exports.STATUS_CODES = http.STATUS_CODES;
    142 exports.IncomingMessage = IncomingMessage;
    143 exports.OutgoingMessage = OutgoingMessage;
    144 exports.protocol = protocol;
    145 
    146 var deprecatedHeaders = [
    147  'connection',
    148  'host',
    149  'keep-alive',
    150  'proxy-connection',
    151  'transfer-encoding',
    152  'upgrade'
    153 ];
    154 
    155 // When doing NPN/ALPN negotiation, HTTP/1.1 is used as fallback
    156 var supportedProtocols = [protocol.VERSION, 'http/1.1', 'http/1.0'];
    157 
    158 // Ciphersuite list based on the recommendations of https://wiki.mozilla.org/Security/Server_Side_TLS
    159 // The only modification is that kEDH+AESGCM were placed after DHE and ECDHE suites
    160 var cipherSuites = [
    161  'ECDHE-RSA-AES128-GCM-SHA256',
    162  'ECDHE-ECDSA-AES128-GCM-SHA256',
    163  'ECDHE-RSA-AES256-GCM-SHA384',
    164  'ECDHE-ECDSA-AES256-GCM-SHA384',
    165  'DHE-RSA-AES128-GCM-SHA256',
    166  'DHE-DSS-AES128-GCM-SHA256',
    167  'ECDHE-RSA-AES128-SHA256',
    168  'ECDHE-ECDSA-AES128-SHA256',
    169  'ECDHE-RSA-AES128-SHA',
    170  'ECDHE-ECDSA-AES128-SHA',
    171  'ECDHE-RSA-AES256-SHA384',
    172  'ECDHE-ECDSA-AES256-SHA384',
    173  'ECDHE-RSA-AES256-SHA',
    174  'ECDHE-ECDSA-AES256-SHA',
    175  'DHE-RSA-AES128-SHA256',
    176  'DHE-RSA-AES128-SHA',
    177  'DHE-DSS-AES128-SHA256',
    178  'DHE-RSA-AES256-SHA256',
    179  'DHE-DSS-AES256-SHA',
    180  'DHE-RSA-AES256-SHA',
    181  'kEDH+AESGCM',
    182  'AES128-GCM-SHA256',
    183  'AES256-GCM-SHA384',
    184  'ECDHE-RSA-RC4-SHA',
    185  'ECDHE-ECDSA-RC4-SHA',
    186  'AES128',
    187  'AES256',
    188  'RC4-SHA',
    189  'HIGH',
    190  '!aNULL',
    191  '!eNULL',
    192  '!EXPORT',
    193  '!DES',
    194  '!3DES',
    195  '!MD5',
    196  '!PSK'
    197 ].join(':');
    198 
    199 // Logging
    200 // -------
    201 
    202 // Logger shim, used when no logger is provided by the user.
    203 function noop() {}
    204 var defaultLogger = {
    205  fatal: noop,
    206  error: noop,
    207  warn : noop,
    208  info : noop,
    209  debug: noop,
    210  trace: noop,
    211 
    212  child: function() { return this; }
    213 };
    214 
    215 // Bunyan serializers exported by submodules that are worth adding when creating a logger.
    216 exports.serializers = protocol.serializers;
    217 
    218 // IncomingMessage class
    219 // ---------------------
    220 
    221 function IncomingMessage(stream) {
    222  // * This is basically a read-only wrapper for the [Stream](protocol/stream.html) class.
    223  PassThrough.call(this);
    224  stream.pipe(this);
    225  this.socket = this.stream = stream;
    226 
    227  this._log = stream._log.child({ component: 'http' });
    228 
    229  // * HTTP/2.0 does not define a way to carry the version identifier that is included in the
    230  //   HTTP/1.1 request/status line. Version is always 2.0.
    231  this.httpVersion = '2.0';
    232  this.httpVersionMajor = 2;
    233  this.httpVersionMinor = 0;
    234 
    235  // * `this.headers` will store the regular headers (and none of the special colon headers)
    236  this.headers = {};
    237  this.trailers = undefined;
    238  this._lastHeadersSeen = undefined;
    239 
    240  // * Other metadata is filled in when the headers arrive.
    241  stream.once('headers', this._onHeaders.bind(this));
    242  stream.once('end', this._onEnd.bind(this));
    243 }
    244 IncomingMessage.prototype = Object.create(PassThrough.prototype, { constructor: { value: IncomingMessage } });
    245 
    246 // [Request Header Fields](https://tools.ietf.org/html/rfc7540#section-8.1.2.3)
    247 // * `headers` argument: HTTP/2.0 request and response header fields carry information as a series
    248 //   of key-value pairs. This includes the target URI for the request, the status code for the
    249 //   response, as well as HTTP header fields.
    250 IncomingMessage.prototype._onHeaders = function _onHeaders(headers) {
    251  // * Detects malformed headers
    252  this._validateHeaders(headers);
    253 
    254  // * Store the _regular_ headers in `this.headers`
    255  for (var name in headers) {
    256    if (name[0] !== ':') {
    257      if (name === 'set-cookie' && !Array.isArray(headers[name])) {
    258        this.headers[name] = [headers[name]];
    259      } else {
    260        this.headers[name] = headers[name];
    261      }
    262    }
    263  }
    264 
    265  // * The last header block, if it's not the first, will represent the trailers
    266  var self = this;
    267  this.stream.on('headers', function(headers) {
    268    self._lastHeadersSeen = headers;
    269  });
    270 };
    271 
    272 IncomingMessage.prototype._onEnd = function _onEnd() {
    273  this.trailers = this._lastHeadersSeen;
    274 };
    275 
    276 IncomingMessage.prototype.setTimeout = noop;
    277 
    278 IncomingMessage.prototype._checkSpecialHeader = function _checkSpecialHeader(key, value) {
    279  if ((typeof value !== 'string') || (value.length === 0)) {
    280    this._log.error({ key: key, value: value }, 'Invalid or missing special header field');
    281    this.stream.reset('PROTOCOL_ERROR');
    282  }
    283 
    284  return value;
    285 };
    286 
    287 IncomingMessage.prototype._validateHeaders = function _validateHeaders(headers) {
    288  // * An HTTP/2.0 request or response MUST NOT include any of the following header fields:
    289  //   Connection, Host, Keep-Alive, Proxy-Connection, Transfer-Encoding, and Upgrade. A server
    290  //   MUST treat the presence of any of these header fields as a stream error of type
    291  //   PROTOCOL_ERROR.
    292  //  If the TE header is present, it's only valid value is 'trailers'
    293  for (var i = 0; i < deprecatedHeaders.length; i++) {
    294    var key = deprecatedHeaders[i];
    295    if (key in headers || (key === 'te' && headers[key] !== 'trailers')) {
    296      this._log.error({ key: key, value: headers[key] }, 'Deprecated header found');
    297      this.stream.reset('PROTOCOL_ERROR');
    298      return;
    299    }
    300  }
    301 
    302  for (var headerName in headers) {
    303    // * Empty header name field is malformed
    304    if (headerName.length <= 1) {
    305      this.stream.reset('PROTOCOL_ERROR');
    306      return;
    307    }
    308    // * A request or response containing uppercase header name field names MUST be
    309    //   treated as malformed (Section 8.1.3.5). Implementations that detect malformed
    310    //   requests or responses need to ensure that the stream ends.
    311    if(/[A-Z]/.test(headerName)) {
    312      this.stream.reset('PROTOCOL_ERROR');
    313      return;
    314    }
    315  }
    316 };
    317 
    318 // OutgoingMessage class
    319 // ---------------------
    320 
    321 function OutgoingMessage() {
    322  // * This is basically a read-only wrapper for the [Stream](protocol/stream.html) class.
    323  Writable.call(this);
    324 
    325  this._headers = {};
    326  this._trailers = undefined;
    327  this.headersSent = false;
    328  this.finished = false;
    329 
    330  this.on('finish', this._finish);
    331 }
    332 OutgoingMessage.prototype = Object.create(Writable.prototype, { constructor: { value: OutgoingMessage } });
    333 
    334 OutgoingMessage.prototype._write = function _write(chunk, encoding, callback) {
    335  if (this.stream) {
    336    this.stream.write(chunk, encoding, callback);
    337  } else {
    338    this.once('socket', this._write.bind(this, chunk, encoding, callback));
    339  }
    340 };
    341 
    342 OutgoingMessage.prototype._finish = function _finish() {
    343  if (this.stream) {
    344    if (this._trailers) {
    345      if (this.request) {
    346        this.request.addTrailers(this._trailers);
    347      } else {
    348        this.stream.trailers(this._trailers);
    349      }
    350    }
    351    this.finished = true;
    352    this.stream.end();
    353  } else {
    354    this.once('socket', this._finish.bind(this));
    355  }
    356 };
    357 
    358 OutgoingMessage.prototype.setHeader = function setHeader(name, value) {
    359  if (this.headersSent) {
    360    return this.emit('error', new Error('Can\'t set headers after they are sent.'));
    361  } else {
    362    name = name.toLowerCase();
    363    if (deprecatedHeaders.indexOf(name) !== -1) {
    364      return this.emit('error', new Error('Cannot set deprecated header: ' + name));
    365    }
    366    this._headers[name] = value;
    367  }
    368 };
    369 
    370 OutgoingMessage.prototype.removeHeader = function removeHeader(name) {
    371  if (this.headersSent) {
    372    return this.emit('error', new Error('Can\'t remove headers after they are sent.'));
    373  } else {
    374    delete this._headers[name.toLowerCase()];
    375  }
    376 };
    377 
    378 OutgoingMessage.prototype.getHeader = function getHeader(name) {
    379  return this._headers[name.toLowerCase()];
    380 };
    381 
    382 OutgoingMessage.prototype.addTrailers = function addTrailers(trailers) {
    383  this._trailers = trailers;
    384 };
    385 
    386 OutgoingMessage.prototype.setTimeout = noop;
    387 
    388 OutgoingMessage.prototype._checkSpecialHeader = IncomingMessage.prototype._checkSpecialHeader;
    389 
    390 // Server side
    391 // ===========
    392 
    393 exports.Server = Server;
    394 exports.IncomingRequest = IncomingRequest;
    395 exports.OutgoingResponse = OutgoingResponse;
    396 exports.ServerResponse = OutgoingResponse; // for API compatibility
    397 
    398 // Forward events `event` on `source` to all listeners on `target`.
    399 //
    400 // Note: The calling context is `source`.
    401 function forwardEvent(event, source, target) {
    402  function forward() {
    403    var listeners = target.listeners(event);
    404 
    405    var n = listeners.length;
    406 
    407    // Special case for `error` event with no listeners.
    408    if (n === 0 && event === 'error') {
    409      var args = [event];
    410      args.push.apply(args, arguments);
    411 
    412      target.emit.apply(target, args);
    413      return;
    414    }
    415 
    416    for (var i = 0; i < n; ++i) {
    417      listeners[i].apply(source, arguments);
    418    }
    419  }
    420 
    421  source.on(event, forward);
    422 
    423  // A reference to the function is necessary to be able to stop
    424  // forwarding.
    425  return forward;
    426 }
    427 
    428 // Server class
    429 // ------------
    430 
    431 function Server(options) {
    432  options = util._extend({}, options);
    433 
    434  this._log = (options.log || defaultLogger).child({ component: 'http' });
    435  this._settings = options.settings;
    436 
    437  var start = this._start.bind(this);
    438  var fallback = this._fallback.bind(this);
    439 
    440  // HTTP2 over TLS (using NPN or ALPN)
    441  if ((options.key && options.cert) || options.pfx) {
    442    this._log.info('Creating HTTP/2 server over TLS');
    443    this._mode = 'tls';
    444    options.ALPNProtocols = supportedProtocols;
    445    options.NPNProtocols = supportedProtocols;
    446    options.ciphers = options.ciphers || cipherSuites;
    447    options.honorCipherOrder = (options.honorCipherOrder != false);
    448    this._server = https.createServer(options);
    449    this._originalSocketListeners = this._server.listeners('secureConnection');
    450    this._server.removeAllListeners('secureConnection');
    451    this._server.on('secureConnection', function(socket) {
    452      var negotiatedProtocol = socket.alpnProtocol || socket.npnProtocol;
    453      // It's true that the client MUST use SNI, but if it doesn't, we don't care, don't fall back to HTTP/1,
    454      // since if the ALPN negotiation is otherwise successful, the client thinks we speak HTTP/2 but we don't.
    455      if (negotiatedProtocol === protocol.VERSION) {
    456        start(socket);
    457      } else {
    458        fallback(socket);
    459      }
    460    });
    461    this._server.on('request', this.emit.bind(this, 'request'));
    462    this._server.on('connect', this.emit.bind(this, 'connect'));
    463 
    464    forwardEvent('error', this._server, this);
    465    forwardEvent('listening', this._server, this);
    466  }
    467 
    468  // HTTP2 over plain TCP
    469  else if (options.plain) {
    470    this._log.info('Creating HTTP/2 server over plain TCP');
    471    this._mode = 'plain';
    472    this._server = net.createServer(start);
    473  }
    474 
    475  // HTTP/2 with HTTP/1.1 upgrade
    476  else {
    477    this._log.error('Trying to create HTTP/2 server with Upgrade from HTTP/1.1');
    478    throw new Error('HTTP1.1 -> HTTP2 upgrade is not yet supported. Please provide TLS keys.');
    479  }
    480 
    481  this._server.on('close', this.emit.bind(this, 'close'));
    482 }
    483 Server.prototype = Object.create(EventEmitter.prototype, { constructor: { value: Server } });
    484 
    485 // Starting HTTP/2
    486 Server.prototype._start = function _start(socket) {
    487  var endpoint = new Endpoint(this._log, 'SERVER', this._settings);
    488 
    489  this._log.info({ e: endpoint,
    490                   client: socket.remoteAddress + ':' + socket.remotePort,
    491                   SNI: socket.servername
    492                 }, 'New incoming HTTP/2 connection');
    493 
    494  endpoint.pipe(socket).pipe(endpoint);
    495 
    496  var self = this;
    497  endpoint.on('stream', function _onStream(stream) {
    498    var response = new OutgoingResponse(stream);
    499    var request = new IncomingRequest(stream);
    500 
    501    // Some conformance to Node.js Https specs allows to distinguish clients:
    502    request.remoteAddress = socket.remoteAddress;
    503    request.remotePort = socket.remotePort;
    504    request.connection = request.socket = response.socket = socket;
    505 
    506    request.once('ready', self.emit.bind(self, 'request', request, response));
    507  });
    508 
    509  endpoint.on('error', this.emit.bind(this, 'clientError'));
    510  socket.on('error', this.emit.bind(this, 'clientError'));
    511 
    512  this.emit('connection', socket, endpoint);
    513 };
    514 
    515 Server.prototype._fallback = function _fallback(socket) {
    516  var negotiatedProtocol = socket.alpnProtocol || socket.npnProtocol;
    517 
    518  this._log.info({ client: socket.remoteAddress + ':' + socket.remotePort,
    519                   protocol: negotiatedProtocol,
    520                   SNI: socket.servername
    521                 }, 'Falling back to simple HTTPS');
    522 
    523  for (var i = 0; i < this._originalSocketListeners.length; i++) {
    524    this._originalSocketListeners[i].call(this._server, socket);
    525  }
    526 
    527  this.emit('connection', socket);
    528 };
    529 
    530 // There are [3 possible signatures][1] of the `listen` function. Every arguments is forwarded to
    531 // the backing TCP or HTTPS server.
    532 // [1]: https://nodejs.org/api/http.html#http_server_listen_port_hostname_backlog_callback
    533 Server.prototype.listen = function listen(port, hostname) {
    534  this._log.info({ on: ((typeof hostname === 'string') ? (hostname + ':' + port) : port) },
    535                 'Listening for incoming connections');
    536  this._server.listen.apply(this._server, arguments);
    537 
    538  return this._server;
    539 };
    540 
    541 Server.prototype.close = function close(callback) {
    542  this._log.info('Closing server');
    543  this._server.close(callback);
    544 };
    545 
    546 Server.prototype.setTimeout = function setTimeout(timeout, callback) {
    547  if (this._mode === 'tls') {
    548    this._server.setTimeout(timeout, callback);
    549  }
    550 };
    551 
    552 Object.defineProperty(Server.prototype, 'timeout', {
    553  get: function getTimeout() {
    554    if (this._mode === 'tls') {
    555      return this._server.timeout;
    556    } else {
    557      return undefined;
    558    }
    559  },
    560  set: function setTimeout(timeout) {
    561    if (this._mode === 'tls') {
    562      this._server.timeout = timeout;
    563    }
    564  }
    565 });
    566 
    567 // Overriding `EventEmitter`'s `on(event, listener)` method to forward certain subscriptions to
    568 // `server`.There are events on the `http.Server` class where it makes difference whether someone is
    569 // listening on the event or not. In these cases, we can not simply forward the events from the
    570 // `server` to `this` since that means a listener. Instead, we forward the subscriptions.
    571 Server.prototype.on = function on(event, listener) {
    572  if ((event === 'upgrade') || (event === 'timeout')) {
    573    return this._server.on(event, listener && listener.bind(this));
    574  } else {
    575    return EventEmitter.prototype.on.call(this, event, listener);
    576  }
    577 };
    578 
    579 // `addContext` is used to add Server Name Indication contexts
    580 Server.prototype.addContext = function addContext(hostname, credentials) {
    581  if (this._mode === 'tls') {
    582    this._server.addContext(hostname, credentials);
    583  }
    584 };
    585 
    586 Server.prototype.address = function address() {
    587  return this._server.address()
    588 };
    589 
    590 function createServerRaw(options, requestListener) {
    591  if (typeof options === 'function') {
    592    requestListener = options;
    593    options = {};
    594  }
    595 
    596  if (options.pfx || (options.key && options.cert)) {
    597    throw new Error('options.pfx, options.key, and options.cert are nonsensical!');
    598  }
    599 
    600  options.plain = true;
    601  var server = new Server(options);
    602 
    603  if (requestListener) {
    604    server.on('request', requestListener);
    605  }
    606 
    607  return server;
    608 }
    609 
    610 function createServerTLS(options, requestListener) {
    611  if (typeof options === 'function') {
    612    throw new Error('options are required!');
    613  }
    614  if (!options.pfx && !(options.key && options.cert)) {
    615    throw new Error('options.pfx or options.key and options.cert are required!');
    616  }
    617  options.plain = false;
    618 
    619  var server = new Server(options);
    620 
    621  if (requestListener) {
    622    server.on('request', requestListener);
    623  }
    624 
    625  return server;
    626 }
    627 
    628 // Exposed main interfaces for HTTPS connections (the default)
    629 exports.https = {};
    630 exports.createServer = exports.https.createServer = createServerTLS;
    631 exports.request = exports.https.request = requestTLS;
    632 exports.get = exports.https.get = getTLS;
    633 
    634 // Exposed main interfaces for raw TCP connections (not recommended)
    635 exports.raw = {};
    636 exports.raw.createServer = createServerRaw;
    637 exports.raw.request = requestRaw;
    638 exports.raw.get = getRaw;
    639 
    640 // Exposed main interfaces for HTTP plaintext upgrade connections (not implemented)
    641 function notImplemented() {
    642    throw new Error('HTTP UPGRADE is not implemented!');
    643 }
    644 
    645 exports.http = {};
    646 exports.http.createServer = exports.http.request = exports.http.get = notImplemented;
    647 
    648 // IncomingRequest class
    649 // ---------------------
    650 
    651 function IncomingRequest(stream) {
    652  IncomingMessage.call(this, stream);
    653 }
    654 IncomingRequest.prototype = Object.create(IncomingMessage.prototype, { constructor: { value: IncomingRequest } });
    655 
    656 // [Request Header Fields](https://tools.ietf.org/html/rfc7540#section-8.1.2.3)
    657 // * `headers` argument: HTTP/2.0 request and response header fields carry information as a series
    658 //   of key-value pairs. This includes the target URI for the request, the status code for the
    659 //   response, as well as HTTP header fields.
    660 IncomingRequest.prototype._onHeaders = function _onHeaders(headers) {
    661  // * The ":method" header field includes the HTTP method
    662  // * The ":scheme" header field includes the scheme portion of the target URI
    663  // * The ":authority" header field includes the authority portion of the target URI
    664  // * The ":path" header field includes the path and query parts of the target URI.
    665  //   This field MUST NOT be empty; URIs that do not contain a path component MUST include a value
    666  //   of '/', unless the request is an OPTIONS request for '*', in which case the ":path" header
    667  //   field MUST include '*'.
    668  // * All HTTP/2.0 requests MUST include exactly one valid value for all of these header fields. A
    669  //   server MUST treat the absence of any of these header fields, presence of multiple values, or
    670  //   an invalid value as a stream error of type PROTOCOL_ERROR.
    671  this.method = this._checkSpecialHeader(':method'   , headers[':method']);
    672  this.host   = this._checkSpecialHeader(':authority', headers[':authority']  );
    673  if (this.method == "CONNECT") {
    674    this.scheme = headers[':scheme'];
    675    this.url    = headers[':path'];
    676    if (!this.method || !this.host) {
    677      // This is invalid, and we've sent a RST_STREAM, so don't continue processing
    678      return;
    679    }
    680  } else {
    681    this.scheme = this._checkSpecialHeader(':scheme'   , headers[':scheme']);
    682    this.url    = this._checkSpecialHeader(':path'     , headers[':path']  );
    683    if (!this.method || !this.scheme || !this.host || !this.url) {
    684      // This is invalid, and we've sent a RST_STREAM, so don't continue processing
    685      return;
    686    }
    687  }
    688 
    689  // * Host header is included in the headers object for backwards compatibility.
    690  this.headers.host = this.host;
    691 
    692  // * Handling regular headers.
    693  IncomingMessage.prototype._onHeaders.call(this, headers);
    694 
    695  // * Signaling that the headers arrived.
    696  this._log.info({ method: this.method, scheme: this.scheme, host: this.host,
    697                   path: this.url, headers: this.headers }, 'Incoming request');
    698  this.emit('ready');
    699 };
    700 
    701 // OutgoingResponse class
    702 // ----------------------
    703 
    704 function OutgoingResponse(stream) {
    705  OutgoingMessage.call(this);
    706 
    707  this._log = stream._log.child({ component: 'http' });
    708 
    709  this.stream = stream;
    710  this.statusCode = 200;
    711  this.sendDate = true;
    712 
    713  this.stream.once('headers', this._onRequestHeaders.bind(this));
    714 }
    715 OutgoingResponse.prototype = Object.create(OutgoingMessage.prototype, { constructor: { value: OutgoingResponse } });
    716 
    717 OutgoingResponse.prototype.writeHead = function writeHead(statusCode, reasonPhrase, headers) {
    718  if (this.headersSent) {
    719    return;
    720  }
    721 
    722  if (typeof reasonPhrase === 'string') {
    723    this._log.warn('Reason phrase argument was present but ignored by the writeHead method');
    724  } else {
    725    headers = reasonPhrase;
    726  }
    727 
    728  for (var name in headers) {
    729    this.setHeader(name, headers[name]);
    730  }
    731  headers = this._headers;
    732 
    733  if (this.sendDate && !('date' in this._headers)) {
    734    headers.date = (new Date()).toUTCString();
    735  }
    736 
    737  this._log.info({ status: statusCode, headers: this._headers }, 'Sending server response');
    738 
    739  headers[':status'] = this.statusCode = statusCode;
    740 
    741  this.stream.headers(headers);
    742  if (statusCode >= 200) {
    743    this.headersSent = true;
    744  } else {
    745    this._headers = {};
    746  }
    747 };
    748 
    749 OutgoingResponse.prototype._implicitHeaders = function _implicitHeaders() {
    750  if (!this.headersSent) {
    751    this.writeHead(this.statusCode);
    752  }
    753 };
    754 
    755 OutgoingResponse.prototype._implicitHeader = function() {
    756  this._implicitHeaders();
    757 };
    758 
    759 OutgoingResponse.prototype.write = function write() {
    760  this._implicitHeaders();
    761  return OutgoingMessage.prototype.write.apply(this, arguments);
    762 };
    763 
    764 OutgoingResponse.prototype.end = function end() {
    765  this.finshed = true;
    766  this._implicitHeaders();
    767  return OutgoingMessage.prototype.end.apply(this, arguments);
    768 };
    769 
    770 OutgoingResponse.prototype._onRequestHeaders = function _onRequestHeaders(headers) {
    771  this._requestHeaders = headers;
    772 };
    773 
    774 OutgoingResponse.prototype.push = function push(options) {
    775  if (typeof options === 'string') {
    776    options = url.parse(options);
    777  }
    778 
    779  if (!options.path) {
    780    throw new Error('`path` option is mandatory.');
    781  }
    782 
    783  var promise = util._extend({
    784    ':method': (options.method || 'GET').toUpperCase(),
    785    ':scheme': (options.protocol && options.protocol.slice(0, -1)) || this._requestHeaders[':scheme'],
    786    ':authority': options.hostname || options.host || this._requestHeaders[':authority'],
    787    ':path': options.path
    788  }, options.headers);
    789 
    790  this._log.info({ method: promise[':method'], scheme: promise[':scheme'],
    791                   authority: promise[':authority'], path: promise[':path'],
    792                   headers: options.headers }, 'Promising push stream');
    793 
    794  var pushStream = this.stream.promise(promise);
    795 
    796  return new OutgoingResponse(pushStream);
    797 };
    798 
    799 OutgoingResponse.prototype.altsvc = function altsvc(host, port, protocolID, maxAge, origin) {
    800    if (origin === undefined) {
    801        origin = "";
    802    }
    803    this.stream.altsvc(host, port, protocolID, maxAge, origin);
    804 };
    805 
    806 // Overriding `EventEmitter`'s `on(event, listener)` method to forward certain subscriptions to
    807 // `request`. See `Server.prototype.on` for explanation.
    808 OutgoingResponse.prototype.on = function on(event, listener) {
    809  if (this.request && (event === 'timeout')) {
    810    this.request.on(event, listener && listener.bind(this));
    811  } else {
    812    OutgoingMessage.prototype.on.call(this, event, listener);
    813  }
    814 };
    815 
    816 // Client side
    817 // ===========
    818 
    819 exports.ClientRequest = OutgoingRequest; // for API compatibility
    820 exports.OutgoingRequest = OutgoingRequest;
    821 exports.IncomingResponse = IncomingResponse;
    822 exports.Agent = Agent;
    823 exports.globalAgent = undefined;
    824 
    825 function requestRaw(options, callback) {
    826  if (typeof options === "string") {
    827    options = url.parse(options);
    828  }
    829  options.plain = true;
    830  if (options.protocol && options.protocol !== "http:") {
    831    throw new Error('This interface only supports http-schemed URLs');
    832  }
    833  if (options.agent && typeof(options.agent.request) === 'function') {
    834    var agentOptions = util._extend({}, options);
    835    delete agentOptions.agent;
    836    return options.agent.request(agentOptions, callback);
    837  }
    838  return exports.globalAgent.request(options, callback);
    839 }
    840 
    841 function requestTLS(options, callback) {
    842  if (typeof options === "string") {
    843    options = url.parse(options);
    844  }
    845  options.plain = false;
    846  if (options.protocol && options.protocol !== "https:") {
    847    throw new Error('This interface only supports https-schemed URLs');
    848  }
    849  if (options.agent && typeof(options.agent.request) === 'function') {
    850    var agentOptions = util._extend({}, options);
    851    delete agentOptions.agent;
    852    return options.agent.request(agentOptions, callback);
    853  }
    854  return exports.globalAgent.request(options, callback);
    855 }
    856 
    857 function getRaw(options, callback) {
    858  if (typeof options === "string") {
    859    options = url.parse(options);
    860  }
    861  options.plain = true;
    862  if (options.protocol && options.protocol !== "http:") {
    863    throw new Error('This interface only supports http-schemed URLs');
    864  }
    865  if (options.agent && typeof(options.agent.get) === 'function') {
    866    var agentOptions = util._extend({}, options);
    867    delete agentOptions.agent;
    868    return options.agent.get(agentOptions, callback);
    869  }
    870  return exports.globalAgent.get(options, callback);
    871 }
    872 
    873 function getTLS(options, callback) {
    874  if (typeof options === "string") {
    875    options = url.parse(options);
    876  }
    877  options.plain = false;
    878  if (options.protocol && options.protocol !== "https:") {
    879    throw new Error('This interface only supports https-schemed URLs');
    880  }
    881  if (options.agent && typeof(options.agent.get) === 'function') {
    882    var agentOptions = util._extend({}, options);
    883    delete agentOptions.agent;
    884    return options.agent.get(agentOptions, callback);
    885  }
    886  return exports.globalAgent.get(options, callback);
    887 }
    888 
    889 // Agent class
    890 // -----------
    891 
    892 function Agent(options) {
    893  EventEmitter.call(this);
    894  this.setMaxListeners(0);
    895 
    896  options = util._extend({}, options);
    897 
    898  this._settings = options.settings;
    899  this._log = (options.log || defaultLogger).child({ component: 'http' });
    900  this.endpoints = {};
    901 
    902  // * Using an own HTTPS agent, because the global agent does not look at `NPN/ALPNProtocols` when
    903  //   generating the key identifying the connection, so we may get useless non-negotiated TLS
    904  //   channels even if we ask for a negotiated one. This agent will contain only negotiated
    905  //   channels.
    906  options.ALPNProtocols = supportedProtocols;
    907  options.NPNProtocols = supportedProtocols;
    908  this._httpsAgent = new https.Agent(options);
    909 
    910  this.sockets = this._httpsAgent.sockets;
    911  this.requests = this._httpsAgent.requests;
    912 }
    913 Agent.prototype = Object.create(EventEmitter.prototype, { constructor: { value: Agent } });
    914 
    915 Agent.prototype.request = function request(options, callback) {
    916  if (typeof options === 'string') {
    917    options = url.parse(options);
    918  } else {
    919    options = util._extend({}, options);
    920  }
    921 
    922  options.method = (options.method || 'GET').toUpperCase();
    923  options.protocol = options.protocol || 'https:';
    924  options.host = options.hostname || options.host || 'localhost';
    925  options.port = options.port || 443;
    926  options.path = options.path || '/';
    927 
    928  if (!options.plain && options.protocol === 'http:') {
    929    this._log.error('Trying to negotiate client request with Upgrade from HTTP/1.1');
    930    this.emit('error', new Error('HTTP1.1 -> HTTP2 upgrade is not yet supported.'));
    931  }
    932 
    933  var request = new OutgoingRequest(this._log);
    934 
    935  if (callback) {
    936    request.on('response', callback);
    937  }
    938 
    939  var key = [
    940    !!options.plain,
    941    options.host,
    942    options.port
    943  ].join(':');
    944  var self = this;
    945 
    946  // * There's an existing HTTP/2 connection to this host
    947  if (key in this.endpoints) {
    948    var endpoint = this.endpoints[key];
    949    request._start(endpoint.createStream(), options);
    950  }
    951 
    952  // * HTTP/2 over plain TCP
    953  else if (options.plain) {
    954    endpoint = new Endpoint(this._log, 'CLIENT', this._settings);
    955    endpoint.socket = net.connect({
    956      host: options.host,
    957      port: options.port,
    958      localAddress: options.localAddress
    959    });
    960 
    961    endpoint.socket.on('error', function (error) {
    962      self._log.error('Socket error: ' + error.toString());
    963      request.emit('error', error);
    964    });
    965 
    966    endpoint.on('error', function(error){
    967      self._log.error('Connection error: ' + error.toString());
    968      request.emit('error', error);
    969    });
    970 
    971    this.endpoints[key] = endpoint;
    972    endpoint.pipe(endpoint.socket).pipe(endpoint);
    973    request._start(endpoint.createStream(), options);
    974  }
    975 
    976  // * HTTP/2 over TLS negotiated using NPN or ALPN, or fallback to HTTPS1
    977  else {
    978    var started = false;
    979    var createAgent = hasAgentOptions(options);
    980    options.ALPNProtocols = supportedProtocols;
    981    options.NPNProtocols = supportedProtocols;
    982    options.servername = options.host; // Server Name Indication
    983    options.ciphers = options.ciphers || cipherSuites;
    984    if (createAgent) {
    985      options.agent = new https.Agent(options);
    986    } else if (options.agent == null) {
    987      options.agent = this._httpsAgent;
    988    }
    989    var httpsRequest = https.request(options);
    990 
    991    httpsRequest.on('error', function (error) {
    992      self._log.error('Socket error: ' + error.toString());
    993      self.removeAllListeners(key);
    994      request.emit('error', error);
    995    });
    996 
    997    httpsRequest.on('socket', function(socket) {
    998      var negotiatedProtocol = socket.alpnProtocol || socket.npnProtocol;
    999      if (negotiatedProtocol != null) { // null in >=0.11.0, undefined in <0.11.0
   1000        negotiated();
   1001      } else {
   1002        socket.on('secureConnect', negotiated);
   1003      }
   1004    });
   1005 
   1006    function negotiated() {
   1007      var endpoint;
   1008      var negotiatedProtocol = httpsRequest.socket.alpnProtocol || httpsRequest.socket.npnProtocol;
   1009      if (negotiatedProtocol === protocol.VERSION) {
   1010        httpsRequest.socket.emit('agentRemove');
   1011        unbundleSocket(httpsRequest.socket);
   1012        endpoint = new Endpoint(self._log, 'CLIENT', self._settings);
   1013        endpoint.socket = httpsRequest.socket;
   1014        endpoint.pipe(endpoint.socket).pipe(endpoint);
   1015      }
   1016      if (started) {
   1017        // ** In the meantime, an other connection was made to the same host...
   1018        if (endpoint) {
   1019          // *** and it turned out to be HTTP2 and the request was multiplexed on that one, so we should close this one
   1020          endpoint.close();
   1021        }
   1022        // *** otherwise, the fallback to HTTPS1 is already done.
   1023      } else {
   1024        if (endpoint) {
   1025          self._log.info({ e: endpoint, server: options.host + ':' + options.port },
   1026                         'New outgoing HTTP/2 connection');
   1027          self.endpoints[key] = endpoint;
   1028          self.emit(key, endpoint);
   1029        } else {
   1030          self.emit(key, undefined);
   1031        }
   1032      }
   1033    }
   1034 
   1035    this.once(key, function(endpoint) {
   1036      started = true;
   1037      if (endpoint) {
   1038        request._start(endpoint.createStream(), options);
   1039      } else {
   1040        request._fallback(httpsRequest);
   1041      }
   1042    });
   1043  }
   1044 
   1045  return request;
   1046 };
   1047 
   1048 Agent.prototype.get = function get(options, callback) {
   1049  var request = this.request(options, callback);
   1050  request.end();
   1051  return request;
   1052 };
   1053 
   1054 Agent.prototype.destroy = function(error) {
   1055  if (this._httpsAgent) {
   1056    this._httpsAgent.destroy();
   1057  }
   1058  for (var key in this.endpoints) {
   1059    this.endpoints[key].close(error);
   1060  }
   1061 };
   1062 
   1063 function unbundleSocket(socket) {
   1064  socket.removeAllListeners('data');
   1065  socket.removeAllListeners('end');
   1066  socket.removeAllListeners('readable');
   1067  socket.removeAllListeners('close');
   1068  socket.removeAllListeners('error');
   1069  socket.unpipe();
   1070  delete socket.ondata;
   1071  delete socket.onend;
   1072 }
   1073 
   1074 function hasAgentOptions(options) {
   1075  return options.pfx != null ||
   1076    options.key != null ||
   1077    options.passphrase != null ||
   1078    options.cert != null ||
   1079    options.ca != null ||
   1080    options.ciphers != null ||
   1081    options.rejectUnauthorized != null ||
   1082    options.secureProtocol != null;
   1083 }
   1084 
   1085 Object.defineProperty(Agent.prototype, 'maxSockets', {
   1086  get: function getMaxSockets() {
   1087    return this._httpsAgent.maxSockets;
   1088  },
   1089  set: function setMaxSockets(value) {
   1090    this._httpsAgent.maxSockets = value;
   1091  }
   1092 });
   1093 
   1094 exports.globalAgent = new Agent();
   1095 
   1096 // OutgoingRequest class
   1097 // ---------------------
   1098 
   1099 function OutgoingRequest() {
   1100  OutgoingMessage.call(this);
   1101 
   1102  this._log = undefined;
   1103 
   1104  this.stream = undefined;
   1105 }
   1106 OutgoingRequest.prototype = Object.create(OutgoingMessage.prototype, { constructor: { value: OutgoingRequest } });
   1107 
   1108 OutgoingRequest.prototype._start = function _start(stream, options) {
   1109  this.stream = stream;
   1110  this.options = options;
   1111 
   1112  this._log = stream._log.child({ component: 'http' });
   1113 
   1114  for (var key in options.headers) {
   1115    this.setHeader(key, options.headers[key]);
   1116  }
   1117  var headers = this._headers;
   1118  delete headers.host;
   1119 
   1120  if (options.auth) {
   1121    headers.authorization = 'Basic ' + Buffer.from(options.auth).toString('base64');
   1122  }
   1123 
   1124  headers[':scheme'] = options.protocol.slice(0, -1);
   1125  headers[':method'] = options.method;
   1126  headers[':authority'] = options.host;
   1127  headers[':path'] = options.path;
   1128 
   1129  this._log.info({ scheme: headers[':scheme'], method: headers[':method'],
   1130                   authority: headers[':authority'], path: headers[':path'],
   1131                   headers: (options.headers || {}) }, 'Sending request');
   1132  this.stream.headers(headers);
   1133  this.headersSent = true;
   1134 
   1135  this.emit('socket', this.stream);
   1136  var response = new IncomingResponse(this.stream);
   1137  response.req = this;
   1138  response.once('ready', this.emit.bind(this, 'response', response));
   1139 
   1140  this.stream.on('promise', this._onPromise.bind(this));
   1141 };
   1142 
   1143 OutgoingRequest.prototype._fallback = function _fallback(request) {
   1144  request.on('response', this.emit.bind(this, 'response'));
   1145  this.stream = this.request = request;
   1146  this.emit('socket', this.socket);
   1147 };
   1148 
   1149 OutgoingRequest.prototype.setPriority = function setPriority(priority) {
   1150  if (this.stream) {
   1151    this.stream.priority(priority);
   1152  } else {
   1153    this.once('socket', this.setPriority.bind(this, priority));
   1154  }
   1155 };
   1156 
   1157 // Overriding `EventEmitter`'s `on(event, listener)` method to forward certain subscriptions to
   1158 // `request`. See `Server.prototype.on` for explanation.
   1159 OutgoingRequest.prototype.on = function on(event, listener) {
   1160  if (this.request && (event === 'upgrade')) {
   1161    this.request.on(event, listener && listener.bind(this));
   1162  } else {
   1163    OutgoingMessage.prototype.on.call(this, event, listener);
   1164  }
   1165 };
   1166 
   1167 // Methods only in fallback mode
   1168 OutgoingRequest.prototype.setNoDelay = function setNoDelay(noDelay) {
   1169  if (this.request) {
   1170    this.request.setNoDelay(noDelay);
   1171  } else if (!this.stream) {
   1172    this.on('socket', this.setNoDelay.bind(this, noDelay));
   1173  }
   1174 };
   1175 
   1176 OutgoingRequest.prototype.setSocketKeepAlive = function setSocketKeepAlive(enable, initialDelay) {
   1177  if (this.request) {
   1178    this.request.setSocketKeepAlive(enable, initialDelay);
   1179  } else if (!this.stream) {
   1180    this.on('socket', this.setSocketKeepAlive.bind(this, enable, initialDelay));
   1181  }
   1182 };
   1183 
   1184 OutgoingRequest.prototype.setTimeout = function setTimeout(timeout, callback) {
   1185  if (this.request) {
   1186    this.request.setTimeout(timeout, callback);
   1187  } else if (!this.stream) {
   1188    this.on('socket', this.setTimeout.bind(this, timeout, callback));
   1189  }
   1190 };
   1191 
   1192 // Aborting the request
   1193 OutgoingRequest.prototype.abort = function abort() {
   1194  if (this.request) {
   1195    this.request.abort();
   1196  } else if (this.stream) {
   1197    this.stream.reset('CANCEL');
   1198  } else {
   1199    this.on('socket', this.abort.bind(this));
   1200  }
   1201 };
   1202 
   1203 // Receiving push promises
   1204 OutgoingRequest.prototype._onPromise = function _onPromise(stream, headers) {
   1205  this._log.info({ push_stream: stream.id }, 'Receiving push promise');
   1206 
   1207  var promise = new IncomingPromise(stream, headers);
   1208 
   1209  if (this.listeners('push').length > 0) {
   1210    this.emit('push', promise);
   1211  } else {
   1212    promise.cancel();
   1213  }
   1214 };
   1215 
   1216 // IncomingResponse class
   1217 // ----------------------
   1218 
   1219 function IncomingResponse(stream) {
   1220  IncomingMessage.call(this, stream);
   1221 }
   1222 IncomingResponse.prototype = Object.create(IncomingMessage.prototype, { constructor: { value: IncomingResponse } });
   1223 
   1224 // [Response Header Fields](https://tools.ietf.org/html/rfc7540#section-8.1.2.4)
   1225 // * `headers` argument: HTTP/2.0 request and response header fields carry information as a series
   1226 //   of key-value pairs. This includes the target URI for the request, the status code for the
   1227 //   response, as well as HTTP header fields.
   1228 IncomingResponse.prototype._onHeaders = function _onHeaders(headers) {
   1229  // * A single ":status" header field is defined that carries the HTTP status code field. This
   1230  //   header field MUST be included in all responses.
   1231  // * A client MUST treat the absence of the ":status" header field, the presence of multiple
   1232  //   values, or an invalid value as a stream error of type PROTOCOL_ERROR.
   1233  //   Note: currently, we do not enforce it strictly: we accept any format, and parse it as int
   1234  // * HTTP/2.0 does not define a way to carry the reason phrase that is included in an HTTP/1.1
   1235  //   status line.
   1236  this.statusCode = parseInt(this._checkSpecialHeader(':status', headers[':status']));
   1237 
   1238  // * Handling regular headers.
   1239  IncomingMessage.prototype._onHeaders.call(this, headers);
   1240 
   1241  // * Signaling that the headers arrived.
   1242  this._log.info({ status: this.statusCode, headers: this.headers}, 'Incoming response');
   1243  this.emit('ready');
   1244 };
   1245 
   1246 // IncomingPromise class
   1247 // -------------------------
   1248 
   1249 function IncomingPromise(responseStream, promiseHeaders) {
   1250  var stream = new Readable();
   1251  stream._read = noop;
   1252  stream.push(null);
   1253  stream._log = responseStream._log;
   1254 
   1255  IncomingRequest.call(this, stream);
   1256 
   1257  this._onHeaders(promiseHeaders);
   1258 
   1259  this._responseStream = responseStream;
   1260 
   1261  var response = new IncomingResponse(this._responseStream);
   1262  response.once('ready', this.emit.bind(this, 'response', response));
   1263 
   1264  this.stream.on('promise', this._onPromise.bind(this));
   1265 }
   1266 IncomingPromise.prototype = Object.create(IncomingRequest.prototype, { constructor: { value: IncomingPromise } });
   1267 
   1268 IncomingPromise.prototype.cancel = function cancel() {
   1269  this._responseStream.reset('CANCEL');
   1270 };
   1271 
   1272 IncomingPromise.prototype.setPriority = function setPriority(priority) {
   1273  this._responseStream.priority(priority);
   1274 };
   1275 
   1276 IncomingPromise.prototype._onPromise = OutgoingRequest.prototype._onPromise;