�PNG  IHDR��;���IDATx��ܻn�0���K�� �)(�pA��� ���7�LeG{�� �§㻢|��ذaÆ 6lذaÆ 6lذaÆ 6lom��$^�y���ذag�5bÆ 6lذaÆ 6lذa{���� 6lذaÆ �`����}H�Fkm�,�m����Ӫ���ô�ô!� �x�|'ܢ˟;�E:���9�&ᶒ�}�{�v]�n&�6� �h��_��t�ڠ͵-ҫ���Z;��Z$�.�P���k�ž)�!��o���>}l�eQfJ�T��u і���چ��\��X=8��Rن4`Vw�l�>����n�G�^��i�s��"ms�$�u��i��?w�bs[m�6�K4���O���.�4��%����/����b�C%��t ��M�ז� �-l�G6�mrz2���s�%�9��s@���-�k�9�=���)������k�B5����\��+͂�Zsٲ ��Rn��~G���R���C����� �wIcI��n7jJ���hۛNCS|���j0��8y�iHKֶۛ�k�Ɉ+;Sz������L/��F�*\��Ԕ�#"5��m�2��[S��������=�g��n�a�P�e�ғ�L�� lذaÆ 6l�^k��̱aÆ 6lذaÆ 6lذa;���� �_��ذaÆ 6lذaÆ 6lذaÆ ���R���IEND�B` 'use strict' var assert = require('assert') var thing = require('handle-thing') var httpDeceiver = require('http-deceiver') var util = require('util') function Handle (options, stream, socket) { var state = {} this._spdyState = state state.options = options || {} state.stream = stream state.socket = null state.rawSocket = socket || stream.connection.socket state.deceiver = null state.ending = false var self = this thing.call(this, stream, { getPeerName: function () { return self._getPeerName() }, close: function (callback) { return self._closeCallback(callback) } }) if (!state.stream) { this.on('stream', function (stream) { state.stream = stream }) } } util.inherits(Handle, thing) module.exports = Handle Handle.create = function create (options, stream, socket) { return new Handle(options, stream, socket) } Handle.prototype._getPeerName = function _getPeerName () { var state = this._spdyState if (state.rawSocket._getpeername) { return state.rawSocket._getpeername() } return null } Handle.prototype._closeCallback = function _closeCallback (callback) { var state = this._spdyState var stream = state.stream if (state.ending) { // The .end() method of the stream may be called by us or by the // .shutdown() method in our super-class. If the latter has already been // called, then calling the .end() method below will have no effect, with // the result that the callback will never get executed, leading to an ever // so subtle memory leak. if (stream._writableState.finished) { // NOTE: it is important to call `setImmediate` instead of `nextTick`, // since this is how regular `handle.close()` works in node.js core. // // Using `nextTick` will lead to `net.Socket` emitting `close` before // `end` on UV_EOF. This results in aborted request without `end` event. setImmediate(callback) } else if (stream._writableState.ending) { stream.once('finish', function () { callback(null) }) } else { stream.end(callback) } } else { stream.abort(callback) } // Only a single end is allowed state.ending = false } Handle.prototype.getStream = function getStream (callback) { var state = this._spdyState if (!callback) { assert(state.stream) return state.stream } if (state.stream) { process.nextTick(function () { callback(state.stream) }) return } this.on('stream', callback) } Handle.prototype.assignSocket = function assignSocket (socket, options) { var state = this._spdyState state.socket = socket state.deceiver = httpDeceiver.create(socket, options) function onStreamError (err) { state.socket.emit('error', err) } this.getStream(function (stream) { stream.on('error', onStreamError) }) } Handle.prototype.assignClientRequest = function assignClientRequest (req) { var state = this._spdyState var oldEnd = req.end var oldSend = req._send // Catch the headers before request will be sent var self = this // For old nodes if (thing.mode !== 'modern') { req.end = function end () { this.end = oldEnd this._send('') return this.end.apply(this, arguments) } } req._send = function send (data) { this._headerSent = true // for v0.10 and below, otherwise it will set `hot = false` and include // headers in first write this._header = 'ignore me' // To prevent exception this.connection = state.socket // It is very important to leave this here, otherwise it will be executed // on a next tick, after `_send` will perform write self.getStream(function (stream) { if (!stream.connection._isGoaway(stream.id)) { stream.send() } }) // We are ready to create stream self.emit('needStream') // Ensure that the connection is still ok to use if (state.stream && state.stream.connection._isGoaway(state.stream.id)) { return } req._send = oldSend // Ignore empty writes if (req.method === 'GET' && data.length === 0) { return } return req._send.apply(this, arguments) } // No chunked encoding req.useChunkedEncodingByDefault = false req.on('finish', function () { req.socket.end() }) } Handle.prototype.assignRequest = function assignRequest (req) { // Emit trailing headers this.getStream(function (stream) { stream.on('headers', function (headers) { req.emit('trailers', headers) }) }) } Handle.prototype.assignResponse = function assignResponse (res) { var self = this res.addTrailers = function addTrailers (headers) { self.getStream(function (stream) { stream.sendHeaders(headers) }) } } Handle.prototype._transformHeaders = function _transformHeaders (kind, headers) { var state = this._spdyState var res = {} var keys = Object.keys(headers) if (kind === 'request' && state.options['x-forwarded-for']) { var xforwarded = state.stream.connection.getXForwardedFor() if (xforwarded !== null) { res['x-forwarded-for'] = xforwarded } } for (var i = 0; i < keys.length; i++) { var key = keys[i] var value = headers[key] if (key === ':authority') { res.host = value } if (/^:/.test(key)) { continue } res[key] = value } return res } Handle.prototype.emitRequest = function emitRequest () { var state = this._spdyState var stream = state.stream state.deceiver.emitRequest({ method: stream.method, path: stream.path, headers: this._transformHeaders('request', stream.headers) }) } Handle.prototype.emitResponse = function emitResponse (status, headers) { var state = this._spdyState state.deceiver.emitResponse({ status: status, headers: this._transformHeaders('response', headers) }) }