first commit

This commit is contained in:
monjack
2025-06-20 18:01:48 +08:00
commit 6daa6d65c1
24611 changed files with 2512443 additions and 0 deletions

13
app_vue/node_modules/spdy/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,13 @@
sudo: false
language: node_js
node_js:
- "6"
- "8"
- "10"
script:
- npm run lint
- npm test
- npm run coverage

267
app_vue/node_modules/spdy/README.md generated vendored Normal file
View File

@ -0,0 +1,267 @@
# SPDY Server for node.js
[![Build Status](https://travis-ci.org/spdy-http2/node-spdy.svg?branch=master)](http://travis-ci.org/spdy-http2/node-spdy)
[![NPM version](https://badge.fury.io/js/spdy.svg)](http://badge.fury.io/js/spdy)
[![dependencies Status](https://david-dm.org/spdy-http2/node-spdy/status.svg?style=flat-square)](https://david-dm.org/spdy-http2/node-spdy)
[![Standard - JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg?style=flat-square)](http://standardjs.com/)
[![Waffle](https://img.shields.io/badge/track-waffle-blue.svg?style=flat-square)](https://waffle.io/spdy-http2/node-spdy)
With this module you can create [HTTP2][0] / [SPDY][1] servers
in node.js with natural http module interface and fallback to regular https
(for browsers that don't support neither HTTP2, nor SPDY yet).
This module named `spdy` but it [provides](https://github.com/indutny/node-spdy/issues/269#issuecomment-239014184) support for both http/2 (h2) and spdy (2,3,3.1). Also, `spdy` is compatible with Express.
## Usage
### Examples
Server:
```javascript
var spdy = require('spdy'),
fs = require('fs');
var options = {
// Private key
key: fs.readFileSync(__dirname + '/keys/spdy-key.pem'),
// Fullchain file or cert file (prefer the former)
cert: fs.readFileSync(__dirname + '/keys/spdy-fullchain.pem'),
// **optional** SPDY-specific options
spdy: {
protocols: [ 'h2', 'spdy/3.1', ..., 'http/1.1' ],
plain: false,
// **optional**
// Parse first incoming X_FORWARDED_FOR frame and put it to the
// headers of every request.
// NOTE: Use with care! This should not be used without some proxy that
// will *always* send X_FORWARDED_FOR
'x-forwarded-for': true,
connection: {
windowSize: 1024 * 1024, // Server's window size
// **optional** if true - server will send 3.1 frames on 3.0 *plain* spdy
autoSpdy31: false
}
}
};
var server = spdy.createServer(options, function(req, res) {
res.writeHead(200);
res.end('hello world!');
});
server.listen(3000);
```
Client:
```javascript
var spdy = require('spdy');
var https = require('https');
var agent = spdy.createAgent({
host: 'www.google.com',
port: 443,
// Optional SPDY options
spdy: {
plain: false,
ssl: true,
// **optional** send X_FORWARDED_FOR
'x-forwarded-for': '127.0.0.1'
}
});
https.get({
host: 'www.google.com',
agent: agent
}, function(response) {
console.log('yikes');
// Here it goes like with any other node.js HTTP request
// ...
// And once we're done - we may close TCP connection to server
// NOTE: All non-closed requests will die!
agent.close();
}).end();
```
Please note that if you use a custom agent, by default all connection-level
errors will result in an uncaught exception. To handle these errors subscribe
to the `error` event and re-emit the captured error:
```javascript
var agent = spdy.createAgent({
host: 'www.google.com',
port: 443
}).once('error', function (err) {
this.emit(err);
});
```
#### Push streams
It is possible to initiate [PUSH_PROMISE][5] to send content to clients _before_
the client requests it.
```javascript
spdy.createServer(options, function(req, res) {
var stream = res.push('/main.js', {
status: 200, // optional
method: 'GET', // optional
request: {
accept: '*/*'
},
response: {
'content-type': 'application/javascript'
}
});
stream.on('error', function() {
});
stream.end('alert("hello from push stream!");');
res.end('<script src="/main.js"></script>');
}).listen(3000);
```
[PUSH_PROMISE][5] may be sent using the `push()` method on the current response
object. The signature of the `push()` method is:
`.push('/some/relative/url', { request: {...}, response: {...} }, callback)`
Second argument contains headers for both PUSH_PROMISE and emulated response.
`callback` will receive two arguments: `err` (if any error is happened) and a
[Duplex][4] stream as the second argument.
Client usage:
```javascript
var agent = spdy.createAgent({ /* ... */ });
var req = http.get({
host: 'www.google.com',
agent: agent
}, function(response) {
});
req.on('push', function(stream) {
stream.on('error', function(err) {
// Handle error
});
// Read data from stream
});
```
NOTE: You're responsible for the `stream` object once given it in `.push()`
callback or `push` event. Hence ignoring `error` event on it will result in
uncaught exception and crash your program.
#### Trailing headers
Server usage:
```javascript
function (req, res) {
// Send trailing headers to client
res.addTrailers({ header1: 'value1', header2: 'value2' });
// On client's trailing headers
req.on('trailers', function(headers) {
// ...
});
}
```
Client usage:
```javascript
var req = http.request({ agent: spdyAgent, /* ... */ }).function (res) {
// On server's trailing headers
res.on('trailers', function(headers) {
// ...
});
});
req.write('stuff');
req.addTrailers({ /* ... */ });
req.end();
```
#### Options
All options supported by [tls][2] work with node-spdy.
Additional options may be passed via `spdy` sub-object:
* `plain` - if defined, server will ignore NPN and ALPN data and choose whether
to use spdy or plain http by looking at first data packet.
* `ssl` - if `false` and `options.plain` is `true`, `http.Server` will be used
as a `base` class for created server.
* `maxChunk` - if set and non-falsy, limits number of bytes sent in one DATA
chunk. Setting it to non-zero value is recommended if you care about
interleaving of outgoing data from multiple different streams.
(defaults to 8192)
* `protocols` - list of NPN/ALPN protocols to use (default is:
`['h2','spdy/3.1', 'spdy/3', 'spdy/2','http/1.1', 'http/1.0']`)
* `protocol` - use specific protocol if no NPN/ALPN ex In addition,
* `maxStreams` - set "[maximum concurrent streams][3]" protocol option
### API
API is compatible with `http` and `https` module, but you can use another
function as base class for SPDYServer.
```javascript
spdy.createServer(
[base class constructor, i.e. https.Server],
{ /* keys and options */ }, // <- the only one required argument
[request listener]
).listen([port], [host], [callback]);
```
Request listener will receive two arguments: `request` and `response`. They're
both instances of `http`'s `IncomingMessage` and `OutgoingMessage`. But three
custom properties are added to both of them: `isSpdy`, `spdyVersion`. `isSpdy`
is `true` when the request was processed using HTTP2/SPDY protocols, it is
`false` in case of HTTP/1.1 fallback. `spdyVersion` is either of: `2`, `3`,
`3.1`, or `4` (for HTTP2).
#### Contributors
* [Fedor Indutny](https://github.com/indutny)
* [Chris Strom](https://github.com/eee-c)
* [François de Metz](https://github.com/francois2metz)
* [Ilya Grigorik](https://github.com/igrigorik)
* [Roberto Peon](https://github.com/grmocg)
* [Tatsuhiro Tsujikawa](https://github.com/tatsuhiro-t)
* [Jesse Cravens](https://github.com/jessecravens)
#### LICENSE
This software is licensed under the MIT License.
Copyright Fedor Indutny, 2015.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
[0]: https://http2.github.io/
[1]: http://www.chromium.org/spdy
[2]: http://nodejs.org/docs/latest/api/tls.html#tls.createServer
[3]: https://httpwg.github.io/specs/rfc7540.html#SETTINGS_MAX_CONCURRENT_STREAMS
[4]: https://iojs.org/api/stream.html#stream_class_stream_duplex
[5]: https://httpwg.github.io/specs/rfc7540.html#PUSH_PROMISE

20
app_vue/node_modules/spdy/lib/spdy.js generated vendored Normal file
View 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
app_vue/node_modules/spdy/lib/spdy/agent.js generated vendored Normal file
View 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
app_vue/node_modules/spdy/lib/spdy/handle.js generated vendored Normal file
View 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
app_vue/node_modules/spdy/lib/spdy/request.js generated vendored Normal file
View 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
app_vue/node_modules/spdy/lib/spdy/response.js generated vendored Normal file
View 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
app_vue/node_modules/spdy/lib/spdy/server.js generated vendored Normal file
View 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
app_vue/node_modules/spdy/lib/spdy/socket.js generated vendored Normal file
View 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)
}
})

54
app_vue/node_modules/spdy/package.json generated vendored Normal file
View File

@ -0,0 +1,54 @@
{
"name": "spdy",
"version": "4.0.2",
"description": "Implementation of the SPDY protocol on node.js.",
"license": "MIT",
"scripts": {
"lint": "standard",
"test": "mocha --reporter=spec test/*-test.js",
"coverage": "istanbul cover node_modules/.bin/_mocha -- --reporter=spec test/**/*-test.js"
},
"pre-commit": [
"lint",
"test"
],
"keywords": [
"spdy"
],
"repository": {
"type": "git",
"url": "git://github.com/indutny/node-spdy.git"
},
"homepage": "https://github.com/indutny/node-spdy",
"bugs": {
"email": "node-spdy+bugs@indutny.com",
"url": "https://github.com/spdy-http2/node-spdy/issues"
},
"author": "Fedor Indutny <fedor.indutny@gmail.com>",
"contributors": [
"Chris Storm <github@eeecooks.com>",
"François de Metz <francois@2metz.fr>",
"Ilya Grigorik <ilya@igvita.com>",
"Roberto Peon",
"Tatsuhiro Tsujikawa",
"Jesse Cravens <jesse.cravens@gmail.com>"
],
"dependencies": {
"debug": "^4.1.0",
"handle-thing": "^2.0.0",
"http-deceiver": "^1.2.7",
"select-hose": "^2.0.0",
"spdy-transport": "^3.0.0"
},
"devDependencies": {
"istanbul": "^0.4.5",
"mocha": "^6.2.3",
"pre-commit": "^1.2.2",
"standard": "^13.1.0"
},
"engines": {
"node": ">=6.0.0"
},
"main": "./lib/spdy",
"optionalDependencies": {}
}

242
app_vue/node_modules/spdy/test/client-test.js generated vendored Normal file
View File

@ -0,0 +1,242 @@
/* eslint-env mocha */
var assert = require('assert')
var https = require('https')
var http = require('http')
var util = require('util')
var fixtures = require('./fixtures')
var spdy = require('../')
// Node.js 0.10 and 0.12 support
Object.assign = process.versions.modules >= 46
? Object.assign // eslint-disable-next-line
: util._extend
describe('SPDY Client', function () {
describe('regular', function () {
fixtures.everyConfig(function (protocol, alpn, version, plain) {
var server
var agent
var hmodule
beforeEach(function (done) {
hmodule = plain ? http : https
var options = Object.assign({
spdy: {
plain: plain
}
}, fixtures.keys)
server = spdy.createServer(options, function (req, res) {
var body = ''
req.on('data', function (chunk) {
body += chunk
})
req.on('end', function () {
res.writeHead(200, req.headers)
res.addTrailers({ trai: 'ler' })
var push = res.push('/push', {
request: {
push: 'yes'
}
}, function (err) {
assert(!err)
push.end('push')
push.on('error', function () {
})
res.end(body || 'okay')
})
})
})
server.listen(fixtures.port, function () {
agent = spdy.createAgent({
rejectUnauthorized: false,
port: fixtures.port,
spdy: {
plain: plain,
protocol: plain ? alpn : null,
protocols: [alpn]
}
})
done()
})
})
afterEach(function (done) {
var waiting = 2
agent.close(next)
server.close(next)
function next () {
if (--waiting === 0) {
done()
}
}
})
it('should send GET request', function (done) {
var req = hmodule.request({
agent: agent,
method: 'GET',
path: '/get',
headers: {
a: 'b'
}
}, function (res) {
assert.strictEqual(res.statusCode, 200)
assert.strictEqual(res.headers.a, 'b')
fixtures.expectData(res, 'okay', done)
})
req.end()
})
it('should send POST request', function (done) {
var req = hmodule.request({
agent: agent,
method: 'POST',
path: '/post',
headers: {
post: 'headers'
}
}, function (res) {
assert.strictEqual(res.statusCode, 200)
assert.strictEqual(res.headers.post, 'headers')
fixtures.expectData(res, 'post body', done)
})
agent._spdyState.socket.once(plain ? 'connect' : 'secureConnect',
function () {
req.end('post body')
})
})
it('should receive PUSH_PROMISE', function (done) {
var req = hmodule.request({
agent: agent,
method: 'GET',
path: '/get'
}, function (res) {
assert.strictEqual(res.statusCode, 200)
res.resume()
})
req.on('push', function (push) {
assert.strictEqual(push.path, '/push')
assert.strictEqual(push.headers.push, 'yes')
push.resume()
push.once('end', done)
})
req.end()
})
it('should receive trailing headers', function (done) {
var req = hmodule.request({
agent: agent,
method: 'GET',
path: '/get'
}, function (res) {
assert.strictEqual(res.statusCode, 200)
res.on('trailers', function (headers) {
assert.strictEqual(headers.trai, 'ler')
fixtures.expectData(res, 'okay', done)
})
})
req.end()
})
})
})
describe('x-forwarded-for', function () {
fixtures.everyConfig(function (protocol, alpn, version, plain) {
var server
var agent
var hmodule
// The underlying spdy Connection created by the agent.
var connection
beforeEach(function (done) {
hmodule = plain ? http : https
var options = Object.assign({
spdy: {
plain: plain,
'x-forwarded-for': true
}
}, fixtures.keys)
server = spdy.createServer(options, function (req, res) {
res.writeHead(200, req.headers)
res.end()
})
server.listen(fixtures.port, function () {
agent = spdy.createAgent({
rejectUnauthorized: false,
port: fixtures.port,
spdy: {
'x-forwarded-for': '1.2.3.4',
plain: plain,
protocol: plain ? alpn : null,
protocols: [alpn]
}
})
// Once aagent has connection, keep a copy for testing.
agent.once('_connect', function () {
connection = agent._spdyState.connection
done()
})
})
})
afterEach(function (done) {
var waiting = 2
agent.close(next)
server.close(next)
function next () {
if (--waiting === 0) {
done()
}
}
})
it('should send x-forwarded-for', function (done) {
var req = hmodule.request({
agent: agent,
method: 'GET',
path: '/get'
}, function (res) {
assert.strictEqual(res.statusCode, 200)
assert.strictEqual(res.headers['x-forwarded-for'], '1.2.3.4')
res.resume()
res.once('end', done)
})
req.end()
})
it('agent should emit connection level errors', function (done) {
agent.once('error', function (err) {
assert.strictEqual(err.message, 'mock error')
done()
})
connection.emit('error', new Error('mock error'))
})
})
})
})

95
app_vue/node_modules/spdy/test/fixtures.js generated vendored Normal file
View File

@ -0,0 +1,95 @@
/* eslint-env mocha */
'use strict'
var assert = require('assert')
exports.port = 23433
exports.keys = {
key: '-----BEGIN RSA PRIVATE KEY-----\n' +
'MIIEogIBAAKCAQEA1ARXSoyizYSnHDYickxX4x2UG/8uNWnQWKlWR97NAwRsspN6\n' +
'aFF1+LnyN9bvLNnhxIowcYy68+LpZ7pYAQgBZSyAhnF1S4qz2w/rxH4CNn96B/je\n' +
'vQGo3e8vIQ8ChhfuYvGAtTEYJzW8aRoxWSPcukZZdxPQ1Wgbhd9DSXhgkUnkEEET\n' +
'owyn8ufQFRnQHfc9Fn5DrJilI7vD+ZyRU3gZoBj2GVMQuxJLqQEHy2XsJ6ZWTea/\n' +
'EfK93XfDyY7ZxyeK0ZdWCVoTqw9QNJSkGjesCBkcY4Rjxi9LbLJwW3Es4wgW4N4Y\n' +
'cltfygjltSis+RVKJyGeDqTWAxceih3mlkdGIQIDAQABAoIBAB6akc8dBdMMtuKH\n' +
'nelJw9XwyxRPfWgQYhaqOt4c9xLcbKRKTX0JZTIGBUSyLcwXl1M7b0q0ubfCpVZn\n' +
'u5RKh4kHJ3ZAomHJH7UbUzkFx2P+eqrz7ZLyzmFayT7IX+DjS3HU0nNVJttiElRJ\n' +
'h54KYy4wQXHC1n43jOGCHMBaM/ZEpO3xA7PLfVD/BpYLzL+FAYoFBb/x2buLv8Mg\n' +
'D6QAWkS70mu8ER13NapKjg6PUsYPxHYU30BjGMTXw95Iz5PSAK8+/xQ6YaW7MEVM\n' +
'twxxfJfZ+9u9nJMfJANqxCi6iZ6ft/e5cbhvNhV/X97XeoPWxqSpx98M6BC/vvBc\n' +
'UjSmaRECgYEA4NH8Y20zC8zF4ALcBgqgrx+U9upov2UGa+kjS1/So4r/dpG4T8pT\n' +
'T2tMW6zR5qe7g11kgJm0oI/I6x9P2qwFJONO3MdLYVKd2mSxG2fniCktLg2j6BAX\n' +
'QTt5zjIEWvhRP2vkrS8gAaJbVMLTMg4s374bE/IdKT+c59tYpcVaXXMCgYEA8WvJ\n' +
'dfPXoagEgaHRd++R2COMG19euOTFRle0MSq+S9ZeeSe9ejb9CIpWYZ3WVviKvf+E\n' +
'zksmKTZJnig5pGEgU+2ka1C9PthCGlTlQagD6Ey4hblQgi+pOFgBjE9Yn3FxfppH\n' +
'25ICXNY89EF6klEqKV67E/5O+nBZo+Y2TM4YKRsCgYAaEV8RbEUB9kFvYwV+Eddl\n' +
'1uSf6LgykRU4h/TWtYqn+eL7LZRQdCZKzCczbgt8kjBU4AxaOPhPsbxbPus0cMO7\n' +
'7jtjsBwWcczp2MkMY3TePeAGOgCqVMtNfgb2mKgWoDpTf0ApsJAmgFvUrS5t3GTp\n' +
'oJJlMqqc8MpRvAZAWmzK7wKBgEVBFlmvyXumJyTItr4hC0VlbRutEA8aET1Mi3RP\n' +
'Pqeipxc6PzB/9bYtePonvQTV53b5ha9n/1pzKEsmXuK4uf1ZfoEKeD8+6jeDgwCC\n' +
'ohxRZd12e5Hc+j4fgNIvMM0MTfJzb4mdKPBYxMOMxQyUG/QiKKhjm2RcNlq9/3Wo\n' +
'6WVhAoGAG4QPWoE4ccFECp8eyGw8rjE45y5uqUI/f/RssX7bnKbCRY0otDsPlJd6\n' +
'Kf0XFssLnYsCXO+ua03gw2N+2mrcsuA5FXHmQMrbfnuojHIVY05nt4Wa5iqV/gqH\n' +
'PJXWyOgD+Kd6eR/cih/SCoKl4tSGCSJG5TDEpMt+r8EJkCXJ7Fw=\n' +
'-----END RSA PRIVATE KEY-----',
cert: '-----BEGIN CERTIFICATE-----\n' +
'MIICuTCCAaOgAwIBAgIDAQABMAsGCSqGSIb3DQEBCzAUMRIwEAYDVQQDFglub2Rl\n' +
'LnNwZHkwHhcNNjkwMTAxMDAwMDAwWhcNMjUwNzA2MDUwMzQzWjAUMRIwEAYDVQQD\n' +
'Fglub2RlLnNwZHkwggEgMAsGCSqGSIb3DQEBAQOCAQ8AMIIBCgKCAQEA1ARXSoyi\n' +
'zYSnHDYickxX4x2UG/8uNWnQWKlWR97NAwRsspN6aFF1+LnyN9bvLNnhxIowcYy6\n' +
'8+LpZ7pYAQgBZSyAhnF1S4qz2w/rxH4CNn96B/jevQGo3e8vIQ8ChhfuYvGAtTEY\n' +
'JzW8aRoxWSPcukZZdxPQ1Wgbhd9DSXhgkUnkEEETowyn8ufQFRnQHfc9Fn5DrJil\n' +
'I7vD+ZyRU3gZoBj2GVMQuxJLqQEHy2XsJ6ZWTea/EfK93XfDyY7ZxyeK0ZdWCVoT\n' +
'qw9QNJSkGjesCBkcY4Rjxi9LbLJwW3Es4wgW4N4YcltfygjltSis+RVKJyGeDqTW\n' +
'Axceih3mlkdGIQIDAQABoxowGDAWBgNVHREEDzANggsqLm5vZGUuc3BkeTALBgkq\n' +
'hkiG9w0BAQsDggEBALn2FQSDMsyu+oqUnJgTVdGpnzKmfXoBPlQuznRdibri8ABO\n' +
'kOo8FC72Iy6leVSsB26KtAdhpURZ3mv1Oyt4cGeeyQln2Olzp5flIos+GqYSztAq\n' +
'5ZnrzTLLlip7KHkmastYRXhEwTLmo2JCU8RkRP1X/m1xONF/YkURxmqj6cQTahPY\n' +
'FzzLP1clW3arJwPlUcKKby6WpxO5MihYEliheBr7fL2TDUA96eG+B/SKxvwaGF2v\n' +
'gWF8rg5prjPaLW8HH3Efq59AimFqUVQ4HtcJApjLJDYUKlvsMNMvBqh/pQRRPafj\n' +
'0Cp8dyS45sbZ2RgXdyfl6gNEj+DiPbaFliIuFmM=\n' +
'-----END CERTIFICATE-----'
}
function expectData (stream, expected, callback) {
var actual = ''
stream.on('data', function (chunk) {
actual += chunk
})
stream.on('end', function () {
assert.strictEqual(actual, expected)
callback()
})
}
exports.expectData = expectData
exports.everyProtocol = function everyProtocol (body) {
var protocols = [
{ protocol: 'http2', alpn: 'h2', version: 4 },
{ protocol: 'spdy', alpn: 'spdy/3.1', version: 3.1 },
{ protocol: 'spdy', alpn: 'spdy/3', version: 3 },
{ protocol: 'spdy', alpn: 'spdy/2', version: 2 }
]
protocols.forEach(function (protocol) {
describe(protocol.alpn, function () {
body(protocol.protocol, protocol.alpn, protocol.version)
})
})
}
exports.everyConfig = function everyConfig (body) {
exports.everyProtocol(function (protocol, alpn, version) {
if (alpn === 'spdy/2') {
return
}
[false, true].forEach(function (plain) {
describe(plain ? 'plain mode' : 'ssl mode', function () {
body(protocol, alpn, version, plain)
})
})
})
}

487
app_vue/node_modules/spdy/test/server-test.js generated vendored Normal file
View File

@ -0,0 +1,487 @@
/* eslint-env mocha */
var assert = require('assert')
var tls = require('tls')
var net = require('net')
var https = require('https')
var transport = require('spdy-transport')
var util = require('util')
var fixtures = require('./fixtures')
var spdy = require('../')
describe('SPDY Server', function () {
fixtures.everyConfig(function (protocol, alpn, version, plain) {
var server
var client
beforeEach(function (done) {
server = spdy.createServer(Object.assign({
spdy: {
'x-forwarded-for': true,
plain: plain
}
}, fixtures.keys))
server.listen(fixtures.port, function () {
var socket = (plain ? net : tls).connect({
rejectUnauthorized: false,
port: fixtures.port,
ALPNProtocols: [alpn]
}, function () {
client = transport.connection.create(socket, {
protocol: protocol,
isServer: false
})
client.start(version)
done()
})
})
})
afterEach(function (done) {
client.socket.destroy()
server.close(done)
})
it('should process GET request', function (done) {
var stream = client.request({
method: 'GET',
path: '/get',
headers: {
a: 'b'
}
}, function (err) {
assert(!err)
stream.on('error', (err) => {
done(err)
})
stream.on('response', function (status, headers) {
assert.strictEqual(status, 200)
assert.strictEqual(headers.ok, 'yes')
fixtures.expectData(stream, 'response', done)
})
stream.end()
})
server.on('request', function (req, res) {
assert.strictEqual(req.isSpdy, res.isSpdy)
assert.strictEqual(req.spdyVersion, res.spdyVersion)
assert(req.isSpdy)
if (!plain) {
assert(req.socket.encrypted)
assert(req.socket.getPeerCertificate())
}
// Auto-detection
if (version === 3.1) {
assert(req.spdyVersion >= 3 && req.spdyVersion <= 3.1)
} else {
assert.strictEqual(req.spdyVersion, version)
}
assert(req.spdyStream)
assert(res.spdyStream)
assert.strictEqual(req.method, 'GET')
assert.strictEqual(req.url, '/get')
assert.deepStrictEqual(req.headers, { a: 'b', host: 'localhost' })
req.on('end', function () {
res.writeHead(200, {
ok: 'yes'
})
res.end('response')
assert(res.finished, 'res.finished should be set')
})
req.resume()
})
})
it('should process POST request', function (done) {
var stream = client.request({
method: 'POST',
path: '/post'
}, function (err) {
assert(!err)
stream.on('response', function (status, headers) {
assert.strictEqual(status, 200)
assert.strictEqual(headers.ok, 'yes')
fixtures.expectData(stream, 'response', next)
})
stream.end('request')
})
server.on('request', function (req, res) {
assert.strictEqual(req.method, 'POST')
assert.strictEqual(req.url, '/post')
res.writeHead(200, {
ok: 'yes'
})
res.end('response')
fixtures.expectData(req, 'request', next)
})
var waiting = 2
function next () {
if (--waiting === 0) {
return done()
}
}
})
it('should process expect-continue request', function (done) {
var stream = client.request({
method: 'GET',
path: '/get',
headers: {
Expect: '100-continue'
}
}, function (err) {
assert(!err)
stream.on('response', function (status, headers) {
assert.strictEqual(status, 100)
fixtures.expectData(stream, 'response', done)
})
stream.end()
})
server.on('request', function (req, res) {
req.on('end', function () {
res.end('response')
})
req.resume()
})
})
it('should emit `checkContinue` request', function (done) {
var stream = client.request({
method: 'GET',
path: '/get',
headers: {
Expect: '100-continue'
}
}, function (err) {
assert(!err)
stream.on('response', function (status, headers) {
assert.strictEqual(status, 100)
fixtures.expectData(stream, 'response', done)
})
stream.end()
})
server.on('checkContinue', function (req, res) {
req.on('end', function () {
res.writeContinue()
res.end('response')
})
req.resume()
})
})
it('should send PUSH_PROMISE', function (done) {
var stream = client.request({
method: 'POST',
path: '/page'
}, function (err) {
assert(!err)
stream.on('pushPromise', function (push) {
assert.strictEqual(push.path, '/push')
assert.strictEqual(push.headers.yes, 'push')
fixtures.expectData(push, 'push', next)
fixtures.expectData(stream, 'response', next)
})
stream.end('request')
})
server.on('request', function (req, res) {
assert.strictEqual(req.method, 'POST')
assert.strictEqual(req.url, '/page')
res.writeHead(200, {
ok: 'yes'
})
var push = res.push('/push', {
request: {
yes: 'push'
}
})
push.end('push')
res.end('response')
fixtures.expectData(req, 'request', next)
})
var waiting = 3
function next () {
if (--waiting === 0) {
return done()
}
}
})
it('should receive trailing headers', function (done) {
var stream = client.request({
method: 'POST',
path: '/post'
}, function (err) {
assert(!err)
stream.sendHeaders({ trai: 'ler' })
stream.end()
stream.on('response', function (status, headers) {
assert.strictEqual(status, 200)
assert.strictEqual(headers.ok, 'yes')
fixtures.expectData(stream, 'response', done)
})
})
server.on('request', function (req, res) {
var gotHeaders = false
req.on('trailers', function (headers) {
gotHeaders = true
assert.strictEqual(headers.trai, 'ler')
})
req.on('end', function () {
assert(gotHeaders)
res.writeHead(200, {
ok: 'yes'
})
res.end('response')
})
req.resume()
})
})
it('should call .writeHead() automatically', function (done) {
var stream = client.request({
method: 'POST',
path: '/post'
}, function (err) {
assert(!err)
stream.on('response', function (status, headers) {
assert.strictEqual(status, 300)
fixtures.expectData(stream, 'response', done)
})
stream.end()
})
server.on('request', function (req, res) {
req.on('end', function () {
res.statusCode = 300
res.end('response')
})
req.resume()
})
})
it('should not crash on .writeHead() after socket close', function (done) {
var stream = client.request({
method: 'POST',
path: '/post'
}, function (err) {
assert(!err)
setTimeout(function () {
client.socket.destroy()
}, 50)
stream.on('error', function () {})
stream.end()
})
server.on('request', function (req, res) {
req.connection.on('close', function () {
assert.doesNotThrow(function () {
res.writeHead(200)
res.end('response')
})
done()
})
})
})
it('should not crash on .push() after socket close', function (done) {
var stream = client.request({
method: 'POST',
path: '/post'
}, function (err) {
assert(!err)
setTimeout(function () {
client.socket.destroy()
}, 50)
stream.on('error', function () {})
stream.end()
})
server.on('request', function (req, res) {
req.connection.on('close', function () {
assert.doesNotThrow(function () {
assert.strictEqual(res.push('/push', {}), undefined)
res.end('response')
})
done()
})
})
})
it('should end response after writing everything down', function (done) {
var stream = client.request({
method: 'GET',
path: '/post'
}, function (err) {
assert(!err)
stream.on('response', function (status, headers) {
assert.strictEqual(status, 200)
fixtures.expectData(stream, 'hello world, what\'s up?', done)
})
stream.end()
})
server.on('request', function (req, res) {
req.resume()
res.writeHead(200)
res.write('hello ')
res.write('world')
res.write(', what\'s')
res.write(' up?')
res.end()
})
})
it('should handle x-forwarded-for', function (done) {
client.sendXForwardedFor('1.2.3.4')
var stream = client.request({
method: 'GET',
path: '/post'
}, function (err) {
assert(!err)
stream.resume()
stream.on('end', done)
stream.end()
})
server.on('request', function (req, res) {
assert.strictEqual(req.headers['x-forwarded-for'], '1.2.3.4')
req.resume()
res.end()
})
})
it('should destroy request after end', function (done) {
var stream = client.request({
method: 'POST',
path: '/post'
}, function (err) {
assert(!err)
})
stream.end()
stream.on('error', function () {})
server.on('request', function (req, res) {
res.end()
res.destroy()
res.socket.on('close', function () {
done()
})
})
})
})
it('should respond to http/1.1', function (done) {
var server = spdy.createServer(fixtures.keys, function (req, res) {
assert.strictEqual(req.isSpdy, res.isSpdy)
assert.strictEqual(req.spdyVersion, res.spdyVersion)
assert(!req.isSpdy)
assert.strictEqual(req.spdyVersion, 1)
res.writeHead(200)
res.end()
})
server.listen(fixtures.port, function () {
var req = https.request({
agent: false,
rejectUnauthorized: false,
NPNProtocols: ['http/1.1'],
port: fixtures.port,
method: 'GET',
path: '/'
}, function (res) {
assert.strictEqual(res.statusCode, 200)
res.resume()
res.on('end', function () {
server.close(done)
})
})
req.end()
})
})
it('should support custom base', function (done) {
function Pseuver (options, listener) {
https.Server.call(this, options, listener)
}
util.inherits(Pseuver, https.Server)
var server = spdy.createServer(Pseuver, fixtures.keys, function (req, res) {
assert.strictEqual(req.isSpdy, res.isSpdy)
assert.strictEqual(req.spdyVersion, res.spdyVersion)
assert(!req.isSpdy)
assert.strictEqual(req.spdyVersion, 1)
res.writeHead(200)
res.end()
})
server.listen(fixtures.port, function () {
var req = https.request({
agent: false,
rejectUnauthorized: false,
NPNProtocols: ['http/1.1'],
port: fixtures.port,
method: 'GET',
path: '/'
}, function (res) {
assert.strictEqual(res.statusCode, 200)
res.resume()
res.on('end', function () {
server.close(done)
})
})
req.end()
})
})
})