Updated the files.
This commit is contained in:
parent
1553e6b971
commit
753967d4f5
23418 changed files with 3784666 additions and 0 deletions
20
my-app/node_modules/spdy/lib/spdy.js
generated
vendored
Executable file
20
my-app/node_modules/spdy/lib/spdy.js
generated
vendored
Executable file
|
@ -0,0 +1,20 @@
|
|||
'use strict'
|
||||
|
||||
var spdy = exports
|
||||
|
||||
// Export tools
|
||||
spdy.handle = require('./spdy/handle')
|
||||
spdy.request = require('./spdy/request')
|
||||
spdy.response = require('./spdy/response')
|
||||
spdy.Socket = require('./spdy/socket')
|
||||
|
||||
// Export client
|
||||
spdy.agent = require('./spdy/agent')
|
||||
spdy.Agent = spdy.agent.Agent
|
||||
spdy.createAgent = spdy.agent.create
|
||||
|
||||
// Export server
|
||||
spdy.server = require('./spdy/server')
|
||||
spdy.Server = spdy.server.Server
|
||||
spdy.PlainServer = spdy.server.PlainServer
|
||||
spdy.createServer = spdy.server.create
|
295
my-app/node_modules/spdy/lib/spdy/agent.js
generated
vendored
Executable file
295
my-app/node_modules/spdy/lib/spdy/agent.js
generated
vendored
Executable file
|
@ -0,0 +1,295 @@
|
|||
'use strict'
|
||||
|
||||
var assert = require('assert')
|
||||
var http = require('http')
|
||||
var https = require('https')
|
||||
var net = require('net')
|
||||
var util = require('util')
|
||||
var transport = require('spdy-transport')
|
||||
var debug = require('debug')('spdy:client')
|
||||
|
||||
// Node.js 0.10 and 0.12 support
|
||||
Object.assign = process.versions.modules >= 46
|
||||
? Object.assign // eslint-disable-next-line
|
||||
: util._extend
|
||||
|
||||
var EventEmitter = require('events').EventEmitter
|
||||
|
||||
var spdy = require('../spdy')
|
||||
|
||||
var mode = /^v0\.8\./.test(process.version)
|
||||
? 'rusty'
|
||||
: /^v0\.(9|10)\./.test(process.version)
|
||||
? 'old'
|
||||
: /^v0\.12\./.test(process.version)
|
||||
? 'normal'
|
||||
: 'modern'
|
||||
|
||||
var proto = {}
|
||||
|
||||
function instantiate (base) {
|
||||
function Agent (options) {
|
||||
this._init(base, options)
|
||||
}
|
||||
util.inherits(Agent, base)
|
||||
|
||||
Agent.create = function create (options) {
|
||||
return new Agent(options)
|
||||
}
|
||||
|
||||
Object.keys(proto).forEach(function (key) {
|
||||
Agent.prototype[key] = proto[key]
|
||||
})
|
||||
|
||||
return Agent
|
||||
}
|
||||
|
||||
proto._init = function _init (base, options) {
|
||||
base.call(this, options)
|
||||
|
||||
var state = {}
|
||||
this._spdyState = state
|
||||
|
||||
state.host = options.host
|
||||
state.options = options.spdy || {}
|
||||
state.secure = this instanceof https.Agent
|
||||
state.fallback = false
|
||||
state.createSocket = this._getCreateSocket()
|
||||
state.socket = null
|
||||
state.connection = null
|
||||
|
||||
// No chunked encoding
|
||||
this.keepAlive = false
|
||||
|
||||
var self = this
|
||||
this._connect(options, function (err, connection) {
|
||||
if (err) {
|
||||
return self.emit('error', err)
|
||||
}
|
||||
|
||||
state.connection = connection
|
||||
self.emit('_connect')
|
||||
})
|
||||
}
|
||||
|
||||
proto._getCreateSocket = function _getCreateSocket () {
|
||||
// Find super's `createSocket` method
|
||||
var createSocket
|
||||
var cons = this.constructor.super_
|
||||
do {
|
||||
createSocket = cons.prototype.createSocket
|
||||
|
||||
if (cons.super_ === EventEmitter || !cons.super_) {
|
||||
break
|
||||
}
|
||||
cons = cons.super_
|
||||
} while (!createSocket)
|
||||
if (!createSocket) {
|
||||
createSocket = http.Agent.prototype.createSocket
|
||||
}
|
||||
|
||||
assert(createSocket, '.createSocket() method not found')
|
||||
|
||||
return createSocket
|
||||
}
|
||||
|
||||
proto._connect = function _connect (options, callback) {
|
||||
var self = this
|
||||
var state = this._spdyState
|
||||
|
||||
var protocols = state.options.protocols || [
|
||||
'h2',
|
||||
'spdy/3.1', 'spdy/3', 'spdy/2',
|
||||
'http/1.1', 'http/1.0'
|
||||
]
|
||||
|
||||
// TODO(indutny): reconnect automatically?
|
||||
var socket = this.createConnection(Object.assign({
|
||||
NPNProtocols: protocols,
|
||||
ALPNProtocols: protocols,
|
||||
servername: options.servername || options.host
|
||||
}, options))
|
||||
state.socket = socket
|
||||
|
||||
socket.setNoDelay(true)
|
||||
|
||||
function onError (err) {
|
||||
return callback(err)
|
||||
}
|
||||
socket.on('error', onError)
|
||||
|
||||
socket.on(state.secure ? 'secureConnect' : 'connect', function () {
|
||||
socket.removeListener('error', onError)
|
||||
|
||||
var protocol
|
||||
if (state.secure) {
|
||||
protocol = socket.npnProtocol ||
|
||||
socket.alpnProtocol ||
|
||||
state.options.protocol
|
||||
} else {
|
||||
protocol = state.options.protocol
|
||||
}
|
||||
|
||||
// HTTP server - kill socket and switch to the fallback mode
|
||||
if (!protocol || protocol === 'http/1.1' || protocol === 'http/1.0') {
|
||||
debug('activating fallback')
|
||||
socket.destroy()
|
||||
state.fallback = true
|
||||
return
|
||||
}
|
||||
|
||||
debug('connected protocol=%j', protocol)
|
||||
var connection = transport.connection.create(socket, Object.assign({
|
||||
protocol: /spdy/.test(protocol) ? 'spdy' : 'http2',
|
||||
isServer: false
|
||||
}, state.options.connection || {}))
|
||||
|
||||
// Pass connection level errors are passed to the agent.
|
||||
connection.on('error', function (err) {
|
||||
self.emit('error', err)
|
||||
})
|
||||
|
||||
// Set version when we are certain
|
||||
if (protocol === 'h2') {
|
||||
connection.start(4)
|
||||
} else if (protocol === 'spdy/3.1') {
|
||||
connection.start(3.1)
|
||||
} else if (protocol === 'spdy/3') {
|
||||
connection.start(3)
|
||||
} else if (protocol === 'spdy/2') {
|
||||
connection.start(2)
|
||||
} else {
|
||||
socket.destroy()
|
||||
callback(new Error('Unexpected protocol: ' + protocol))
|
||||
return
|
||||
}
|
||||
|
||||
if (state.options['x-forwarded-for'] !== undefined) {
|
||||
connection.sendXForwardedFor(state.options['x-forwarded-for'])
|
||||
}
|
||||
|
||||
callback(null, connection)
|
||||
})
|
||||
}
|
||||
|
||||
proto._createSocket = function _createSocket (req, options, callback) {
|
||||
var state = this._spdyState
|
||||
if (state.fallback) { return state.createSocket(req, options) }
|
||||
|
||||
var handle = spdy.handle.create(null, null, state.socket)
|
||||
|
||||
var socketOptions = {
|
||||
handle: handle,
|
||||
allowHalfOpen: true
|
||||
}
|
||||
|
||||
var socket
|
||||
if (state.secure) {
|
||||
socket = new spdy.Socket(state.socket, socketOptions)
|
||||
} else {
|
||||
socket = new net.Socket(socketOptions)
|
||||
}
|
||||
|
||||
handle.assignSocket(socket)
|
||||
handle.assignClientRequest(req)
|
||||
|
||||
// Create stream only once `req.end()` is called
|
||||
var self = this
|
||||
handle.once('needStream', function () {
|
||||
if (state.connection === null) {
|
||||
self.once('_connect', function () {
|
||||
handle.setStream(self._createStream(req, handle))
|
||||
})
|
||||
} else {
|
||||
handle.setStream(self._createStream(req, handle))
|
||||
}
|
||||
})
|
||||
|
||||
// Yes, it is in reverse
|
||||
req.on('response', function (res) {
|
||||
handle.assignRequest(res)
|
||||
})
|
||||
handle.assignResponse(req)
|
||||
|
||||
// Handle PUSH
|
||||
req.addListener('newListener', spdy.request.onNewListener)
|
||||
|
||||
// For v0.8
|
||||
socket.readable = true
|
||||
socket.writable = true
|
||||
|
||||
if (callback) {
|
||||
return callback(null, socket)
|
||||
}
|
||||
|
||||
return socket
|
||||
}
|
||||
|
||||
if (mode === 'modern' || mode === 'normal') {
|
||||
proto.createSocket = proto._createSocket
|
||||
} else {
|
||||
proto.createSocket = function createSocket (name, host, port, addr, req) {
|
||||
var state = this._spdyState
|
||||
if (state.fallback) {
|
||||
return state.createSocket(name, host, port, addr, req)
|
||||
}
|
||||
|
||||
return this._createSocket(req, {
|
||||
host: host,
|
||||
port: port
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
proto._createStream = function _createStream (req, handle) {
|
||||
var state = this._spdyState
|
||||
|
||||
var self = this
|
||||
return state.connection.reserveStream({
|
||||
method: req.method,
|
||||
path: req.path,
|
||||
headers: req._headers,
|
||||
host: state.host
|
||||
}, function (err, stream) {
|
||||
if (err) {
|
||||
return self.emit('error', err)
|
||||
}
|
||||
|
||||
stream.on('response', function (status, headers) {
|
||||
handle.emitResponse(status, headers)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Public APIs
|
||||
|
||||
proto.close = function close (callback) {
|
||||
var state = this._spdyState
|
||||
|
||||
if (state.connection === null) {
|
||||
this.once('_connect', function () {
|
||||
this.close(callback)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
state.connection.end(callback)
|
||||
}
|
||||
|
||||
exports.Agent = instantiate(https.Agent)
|
||||
exports.PlainAgent = instantiate(http.Agent)
|
||||
|
||||
exports.create = function create (base, options) {
|
||||
if (typeof base === 'object') {
|
||||
options = base
|
||||
base = null
|
||||
}
|
||||
|
||||
if (base) {
|
||||
return instantiate(base).create(options)
|
||||
}
|
||||
|
||||
if (options.spdy && options.spdy.plain) {
|
||||
return exports.PlainAgent.create(options)
|
||||
} else { return exports.Agent.create(options) }
|
||||
}
|
247
my-app/node_modules/spdy/lib/spdy/handle.js
generated
vendored
Executable file
247
my-app/node_modules/spdy/lib/spdy/handle.js
generated
vendored
Executable file
|
@ -0,0 +1,247 @@
|
|||
'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)
|
||||
})
|
||||
}
|
33
my-app/node_modules/spdy/lib/spdy/request.js
generated
vendored
Executable file
33
my-app/node_modules/spdy/lib/spdy/request.js
generated
vendored
Executable file
|
@ -0,0 +1,33 @@
|
|||
'use strict'
|
||||
|
||||
function attachPush (req) {
|
||||
var handle = req.socket._handle
|
||||
|
||||
handle.getStream(function (stream) {
|
||||
stream.on('pushPromise', function (push) {
|
||||
req.emit('push', push)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
exports.onNewListener = function onNewListener (type) {
|
||||
var req = this
|
||||
|
||||
if (type !== 'push') {
|
||||
return
|
||||
}
|
||||
|
||||
// Not first listener
|
||||
if (req.listeners('push').length !== 0) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!req.socket) {
|
||||
req.on('socket', function () {
|
||||
attachPush(req)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
attachPush(req)
|
||||
}
|
100
my-app/node_modules/spdy/lib/spdy/response.js
generated
vendored
Executable file
100
my-app/node_modules/spdy/lib/spdy/response.js
generated
vendored
Executable file
|
@ -0,0 +1,100 @@
|
|||
'use strict'
|
||||
|
||||
// NOTE: Mostly copy paste from node
|
||||
exports.writeHead = function writeHead (statusCode, reason, obj) {
|
||||
var headers
|
||||
|
||||
if (typeof reason === 'string') {
|
||||
// writeHead(statusCode, reasonPhrase[, headers])
|
||||
this.statusMessage = reason
|
||||
} else {
|
||||
// writeHead(statusCode[, headers])
|
||||
this.statusMessage =
|
||||
this.statusMessage || 'unknown'
|
||||
obj = reason
|
||||
}
|
||||
this.statusCode = statusCode
|
||||
|
||||
if (this._headers) {
|
||||
// Slow-case: when progressive API and header fields are passed.
|
||||
if (obj) {
|
||||
var keys = Object.keys(obj)
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var k = keys[i]
|
||||
if (k) this.setHeader(k, obj[k])
|
||||
}
|
||||
}
|
||||
// only progressive api is used
|
||||
headers = this._renderHeaders()
|
||||
} else {
|
||||
// only writeHead() called
|
||||
headers = obj
|
||||
}
|
||||
|
||||
if (statusCode === 204 || statusCode === 304 ||
|
||||
(statusCode >= 100 && statusCode <= 199)) {
|
||||
// RFC 2616, 10.2.5:
|
||||
// The 204 response MUST NOT include a message-body, and thus is always
|
||||
// terminated by the first empty line after the header fields.
|
||||
// RFC 2616, 10.3.5:
|
||||
// The 304 response MUST NOT contain a message-body, and thus is always
|
||||
// terminated by the first empty line after the header fields.
|
||||
// RFC 2616, 10.1 Informational 1xx:
|
||||
// This class of status code indicates a provisional response,
|
||||
// consisting only of the Status-Line and optional headers, and is
|
||||
// terminated by an empty line.
|
||||
this._hasBody = false
|
||||
}
|
||||
|
||||
// don't keep alive connections where the client expects 100 Continue
|
||||
// but we sent a final status; they may put extra bytes on the wire.
|
||||
if (this._expect_continue && !this._sent100) {
|
||||
this.shouldKeepAlive = false
|
||||
}
|
||||
|
||||
// Implicit headers sent!
|
||||
this._header = true
|
||||
this._headerSent = true
|
||||
|
||||
if (this.socket._handle) { this.socket._handle._spdyState.stream.respond(this.statusCode, headers) }
|
||||
}
|
||||
|
||||
exports.end = function end (data, encoding, callback) {
|
||||
if (!this._headerSent) {
|
||||
this.writeHead(this.statusCode)
|
||||
}
|
||||
|
||||
if (!this.socket._handle) {
|
||||
return
|
||||
}
|
||||
|
||||
// Compatibility with Node.js core
|
||||
this.finished = true
|
||||
|
||||
var self = this
|
||||
var handle = this.socket._handle
|
||||
handle._spdyState.ending = true
|
||||
this.socket.end(data, encoding, function () {
|
||||
self.constructor.prototype.end.call(self, '', 'utf8', callback)
|
||||
})
|
||||
}
|
||||
|
||||
exports.push = function push (path, headers, callback) {
|
||||
var frame = {
|
||||
path: path,
|
||||
method: headers.method ? headers.method.toString() : 'GET',
|
||||
status: headers.status ? parseInt(headers.status, 10) : 200,
|
||||
host: this._req.headers.host,
|
||||
headers: headers.request,
|
||||
response: headers.response
|
||||
}
|
||||
|
||||
var stream = this.spdyStream
|
||||
return stream.pushPromise(frame, callback)
|
||||
}
|
||||
|
||||
exports.writeContinue = function writeContinue (callback) {
|
||||
if (this.socket._handle) {
|
||||
this.socket._handle._spdyState.stream.respond(100, {}, callback)
|
||||
}
|
||||
}
|
288
my-app/node_modules/spdy/lib/spdy/server.js
generated
vendored
Executable file
288
my-app/node_modules/spdy/lib/spdy/server.js
generated
vendored
Executable file
|
@ -0,0 +1,288 @@
|
|||
'use strict'
|
||||
|
||||
var assert = require('assert')
|
||||
var https = require('https')
|
||||
var http = require('http')
|
||||
var tls = require('tls')
|
||||
var net = require('net')
|
||||
var util = require('util')
|
||||
var selectHose = require('select-hose')
|
||||
var transport = require('spdy-transport')
|
||||
var debug = require('debug')('spdy:server')
|
||||
var EventEmitter = require('events').EventEmitter
|
||||
|
||||
// Node.js 0.8, 0.10 and 0.12 support
|
||||
Object.assign = process.versions.modules >= 46
|
||||
? Object.assign // eslint-disable-next-line
|
||||
: util._extend
|
||||
|
||||
var spdy = require('../spdy')
|
||||
|
||||
var proto = {}
|
||||
|
||||
function instantiate (base) {
|
||||
function Server (options, handler) {
|
||||
this._init(base, options, handler)
|
||||
}
|
||||
util.inherits(Server, base)
|
||||
|
||||
Server.create = function create (options, handler) {
|
||||
return new Server(options, handler)
|
||||
}
|
||||
|
||||
Object.keys(proto).forEach(function (key) {
|
||||
Server.prototype[key] = proto[key]
|
||||
})
|
||||
|
||||
return Server
|
||||
}
|
||||
|
||||
proto._init = function _init (base, options, handler) {
|
||||
var state = {}
|
||||
this._spdyState = state
|
||||
|
||||
state.options = options.spdy || {}
|
||||
|
||||
var protocols = state.options.protocols || [
|
||||
'h2',
|
||||
'spdy/3.1', 'spdy/3', 'spdy/2',
|
||||
'http/1.1', 'http/1.0'
|
||||
]
|
||||
|
||||
var actualOptions = Object.assign({
|
||||
NPNProtocols: protocols,
|
||||
|
||||
// Future-proof
|
||||
ALPNProtocols: protocols
|
||||
}, options)
|
||||
|
||||
state.secure = this instanceof tls.Server
|
||||
|
||||
if (state.secure) {
|
||||
base.call(this, actualOptions)
|
||||
} else {
|
||||
base.call(this)
|
||||
}
|
||||
|
||||
// Support HEADERS+FIN
|
||||
this.httpAllowHalfOpen = true
|
||||
|
||||
var event = state.secure ? 'secureConnection' : 'connection'
|
||||
|
||||
state.listeners = this.listeners(event).slice()
|
||||
assert(state.listeners.length > 0, 'Server does not have default listeners')
|
||||
this.removeAllListeners(event)
|
||||
|
||||
if (state.options.plain) {
|
||||
this.on(event, this._onPlainConnection)
|
||||
} else { this.on(event, this._onConnection) }
|
||||
|
||||
if (handler) {
|
||||
this.on('request', handler)
|
||||
}
|
||||
|
||||
debug('server init secure=%d', state.secure)
|
||||
}
|
||||
|
||||
proto._onConnection = function _onConnection (socket) {
|
||||
var state = this._spdyState
|
||||
|
||||
var protocol
|
||||
if (state.secure) {
|
||||
protocol = socket.npnProtocol || socket.alpnProtocol
|
||||
}
|
||||
|
||||
this._handleConnection(socket, protocol)
|
||||
}
|
||||
|
||||
proto._handleConnection = function _handleConnection (socket, protocol) {
|
||||
var state = this._spdyState
|
||||
|
||||
if (!protocol) {
|
||||
protocol = state.options.protocol
|
||||
}
|
||||
|
||||
debug('incoming socket protocol=%j', protocol)
|
||||
|
||||
// No way we can do anything with the socket
|
||||
if (!protocol || protocol === 'http/1.1' || protocol === 'http/1.0') {
|
||||
debug('to default handler it goes')
|
||||
return this._invokeDefault(socket)
|
||||
}
|
||||
|
||||
socket.setNoDelay(true)
|
||||
|
||||
var connection = transport.connection.create(socket, Object.assign({
|
||||
protocol: /spdy/.test(protocol) ? 'spdy' : 'http2',
|
||||
isServer: true
|
||||
}, state.options.connection || {}))
|
||||
|
||||
// Set version when we are certain
|
||||
if (protocol === 'http2') { connection.start(4) } else if (protocol === 'spdy/3.1') {
|
||||
connection.start(3.1)
|
||||
} else if (protocol === 'spdy/3') { connection.start(3) } else if (protocol === 'spdy/2') {
|
||||
connection.start(2)
|
||||
}
|
||||
|
||||
connection.on('error', function () {
|
||||
socket.destroy()
|
||||
})
|
||||
|
||||
var self = this
|
||||
connection.on('stream', function (stream) {
|
||||
self._onStream(stream)
|
||||
})
|
||||
}
|
||||
|
||||
// HTTP2 preface
|
||||
var PREFACE = 'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n'
|
||||
var PREFACE_BUFFER = Buffer.from(PREFACE)
|
||||
|
||||
function hoseFilter (data, callback) {
|
||||
if (data.length < 1) {
|
||||
return callback(null, null)
|
||||
}
|
||||
|
||||
// SPDY!
|
||||
if (data[0] === 0x80) { return callback(null, 'spdy') }
|
||||
|
||||
var avail = Math.min(data.length, PREFACE_BUFFER.length)
|
||||
for (var i = 0; i < avail; i++) {
|
||||
if (data[i] !== PREFACE_BUFFER[i]) { return callback(null, 'http/1.1') }
|
||||
}
|
||||
|
||||
// Not enough bytes to be sure about HTTP2
|
||||
if (avail !== PREFACE_BUFFER.length) { return callback(null, null) }
|
||||
|
||||
return callback(null, 'h2')
|
||||
}
|
||||
|
||||
proto._onPlainConnection = function _onPlainConnection (socket) {
|
||||
var hose = selectHose.create(socket, {}, hoseFilter)
|
||||
|
||||
var self = this
|
||||
hose.on('select', function (protocol, socket) {
|
||||
self._handleConnection(socket, protocol)
|
||||
})
|
||||
|
||||
hose.on('error', function (err) {
|
||||
debug('hose error %j', err.message)
|
||||
socket.destroy()
|
||||
})
|
||||
}
|
||||
|
||||
proto._invokeDefault = function _invokeDefault (socket) {
|
||||
var state = this._spdyState
|
||||
|
||||
for (var i = 0; i < state.listeners.length; i++) { state.listeners[i].call(this, socket) }
|
||||
}
|
||||
|
||||
proto._onStream = function _onStream (stream) {
|
||||
var state = this._spdyState
|
||||
|
||||
var handle = spdy.handle.create(this._spdyState.options, stream)
|
||||
|
||||
var socketOptions = {
|
||||
handle: handle,
|
||||
allowHalfOpen: true
|
||||
}
|
||||
|
||||
var socket
|
||||
if (state.secure) {
|
||||
socket = new spdy.Socket(stream.connection.socket, socketOptions)
|
||||
} else {
|
||||
socket = new net.Socket(socketOptions)
|
||||
}
|
||||
|
||||
// This is needed because the `error` listener, added by the default
|
||||
// `connection` listener, no longer has bound arguments. It relies instead
|
||||
// on the `server` property of the socket. See https://github.com/nodejs/node/pull/11926
|
||||
// for more details.
|
||||
// This is only done for Node.js >= 4 in order to not break compatibility
|
||||
// with older versions of the platform.
|
||||
if (process.versions.modules >= 46) { socket.server = this }
|
||||
|
||||
handle.assignSocket(socket)
|
||||
|
||||
// For v0.8
|
||||
socket.readable = true
|
||||
socket.writable = true
|
||||
|
||||
this._invokeDefault(socket)
|
||||
|
||||
// For v0.8, 0.10 and 0.12
|
||||
if (process.versions.modules < 46) {
|
||||
// eslint-disable-next-line
|
||||
this.listenerCount = EventEmitter.listenerCount.bind(this)
|
||||
}
|
||||
|
||||
// Add lazy `checkContinue` listener, otherwise `res.writeContinue` will be
|
||||
// called before the response object was patched by us.
|
||||
if (stream.headers.expect !== undefined &&
|
||||
/100-continue/i.test(stream.headers.expect) &&
|
||||
this.listenerCount('checkContinue') === 0) {
|
||||
this.once('checkContinue', function (req, res) {
|
||||
res.writeContinue()
|
||||
|
||||
this.emit('request', req, res)
|
||||
})
|
||||
}
|
||||
|
||||
handle.emitRequest()
|
||||
}
|
||||
|
||||
proto.emit = function emit (event, req, res) {
|
||||
if (event !== 'request' && event !== 'checkContinue') {
|
||||
return EventEmitter.prototype.emit.apply(this, arguments)
|
||||
}
|
||||
|
||||
if (!(req.socket._handle instanceof spdy.handle)) {
|
||||
debug('not spdy req/res')
|
||||
req.isSpdy = false
|
||||
req.spdyVersion = 1
|
||||
res.isSpdy = false
|
||||
res.spdyVersion = 1
|
||||
return EventEmitter.prototype.emit.apply(this, arguments)
|
||||
}
|
||||
|
||||
var handle = req.connection._handle
|
||||
|
||||
req.isSpdy = true
|
||||
req.spdyVersion = handle.getStream().connection.getVersion()
|
||||
res.isSpdy = true
|
||||
res.spdyVersion = req.spdyVersion
|
||||
req.spdyStream = handle.getStream()
|
||||
|
||||
debug('override req/res')
|
||||
res.writeHead = spdy.response.writeHead
|
||||
res.end = spdy.response.end
|
||||
res.push = spdy.response.push
|
||||
res.writeContinue = spdy.response.writeContinue
|
||||
res.spdyStream = handle.getStream()
|
||||
|
||||
res._req = req
|
||||
|
||||
handle.assignRequest(req)
|
||||
handle.assignResponse(res)
|
||||
|
||||
return EventEmitter.prototype.emit.apply(this, arguments)
|
||||
}
|
||||
|
||||
exports.Server = instantiate(https.Server)
|
||||
exports.PlainServer = instantiate(http.Server)
|
||||
|
||||
exports.create = function create (base, options, handler) {
|
||||
if (typeof base === 'object') {
|
||||
handler = options
|
||||
options = base
|
||||
base = null
|
||||
}
|
||||
|
||||
if (base) {
|
||||
return instantiate(base).create(options, handler)
|
||||
}
|
||||
|
||||
if (options.spdy && options.spdy.plain) { return exports.PlainServer.create(options, handler) } else {
|
||||
return exports.Server.create(options, handler)
|
||||
}
|
||||
}
|
39
my-app/node_modules/spdy/lib/spdy/socket.js
generated
vendored
Executable file
39
my-app/node_modules/spdy/lib/spdy/socket.js
generated
vendored
Executable file
|
@ -0,0 +1,39 @@
|
|||
'use strict'
|
||||
|
||||
var util = require('util')
|
||||
var net = require('net')
|
||||
|
||||
function Socket (parent, options) {
|
||||
net.Socket.call(this, options)
|
||||
|
||||
var state = {}
|
||||
|
||||
this._spdyState = state
|
||||
|
||||
state.parent = parent
|
||||
|
||||
this.servername = parent.servername
|
||||
this.npnProtocol = parent.npnProtocol
|
||||
this.alpnProtocol = parent.alpnProtocol
|
||||
this.authorized = parent.authorized
|
||||
this.authorizationError = parent.authorizationError
|
||||
this.encrypted = true
|
||||
this.allowHalfOpen = true
|
||||
}
|
||||
|
||||
util.inherits(Socket, net.Socket)
|
||||
|
||||
module.exports = Socket
|
||||
|
||||
var methods = [
|
||||
'renegotiate', 'setMaxSendFragment', 'getTLSTicket', 'setServername',
|
||||
'setSession', 'getPeerCertificate', 'getSession', 'isSessionReused',
|
||||
'getCipher', 'getEphemeralKeyInfo'
|
||||
]
|
||||
|
||||
methods.forEach(function (method) {
|
||||
Socket.prototype[method] = function methodWrap () {
|
||||
var parent = this._spdyState.parent
|
||||
return parent[method].apply(parent, arguments)
|
||||
}
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue