done
This commit is contained in:
19
node_modules/engine.io/LICENSE
generated
vendored
Normal file
19
node_modules/engine.io/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014-present Guillermo Rauch and Socket.IO contributors
|
||||
|
||||
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.
|
||||
|
||||
603
node_modules/engine.io/README.md
generated
vendored
Normal file
603
node_modules/engine.io/README.md
generated
vendored
Normal file
@@ -0,0 +1,603 @@
|
||||
|
||||
# Engine.IO: the realtime engine
|
||||
|
||||
[](https://github.com/socketio/engine.io/actions)
|
||||
[](http://badge.fury.io/js/engine.io)
|
||||
|
||||
`Engine.IO` is the implementation of transport-based
|
||||
cross-browser/cross-device bi-directional communication layer for
|
||||
[Socket.IO](http://github.com/socketio/socket.io).
|
||||
|
||||
## How to use
|
||||
|
||||
### Server
|
||||
|
||||
#### (A) Listening on a port
|
||||
|
||||
```js
|
||||
const engine = require('engine.io');
|
||||
const server = engine.listen(80);
|
||||
|
||||
server.on('connection', socket => {
|
||||
socket.send('utf 8 string');
|
||||
socket.send(Buffer.from([0, 1, 2, 3, 4, 5])); // binary data
|
||||
});
|
||||
```
|
||||
|
||||
#### (B) Intercepting requests for a http.Server
|
||||
|
||||
```js
|
||||
const engine = require('engine.io');
|
||||
const http = require('http').createServer().listen(3000);
|
||||
const server = engine.attach(http);
|
||||
|
||||
server.on('connection', socket => {
|
||||
socket.on('message', data => { });
|
||||
socket.on('close', () => { });
|
||||
});
|
||||
```
|
||||
|
||||
#### (C) Passing in requests
|
||||
|
||||
```js
|
||||
const engine = require('engine.io');
|
||||
const server = new engine.Server();
|
||||
|
||||
server.on('connection', socket => {
|
||||
socket.send('hi');
|
||||
});
|
||||
|
||||
// …
|
||||
httpServer.on('upgrade', (req, socket, head) => {
|
||||
server.handleUpgrade(req, socket, head);
|
||||
});
|
||||
|
||||
httpServer.on('request', (req, res) => {
|
||||
server.handleRequest(req, res);
|
||||
});
|
||||
```
|
||||
|
||||
### Client
|
||||
|
||||
```html
|
||||
<script src="/path/to/engine.io.js"></script>
|
||||
<script>
|
||||
const socket = new eio.Socket('ws://localhost/');
|
||||
socket.on('open', () => {
|
||||
socket.on('message', data => {});
|
||||
socket.on('close', () => {});
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
For more information on the client refer to the
|
||||
[engine-client](http://github.com/socketio/engine.io-client) repository.
|
||||
|
||||
## What features does it have?
|
||||
|
||||
- **Maximum reliability**. Connections are established even in the presence of:
|
||||
- proxies and load balancers.
|
||||
- personal firewall and antivirus software.
|
||||
- for more information refer to **Goals** and **Architecture** sections
|
||||
- **Minimal client size** aided by:
|
||||
- lazy loading of flash transports.
|
||||
- lack of redundant transports.
|
||||
- **Scalable**
|
||||
- load balancer friendly
|
||||
- **Future proof**
|
||||
- **100% Node.JS core style**
|
||||
- No API sugar (left for higher level projects)
|
||||
|
||||
## API
|
||||
|
||||
### Server
|
||||
|
||||
<hr><br>
|
||||
|
||||
#### Top-level
|
||||
|
||||
These are exposed by `require('engine.io')`:
|
||||
|
||||
##### Events
|
||||
|
||||
- `flush`
|
||||
- Called when a socket buffer is being flushed.
|
||||
- **Arguments**
|
||||
- `Socket`: socket being flushed
|
||||
- `Array`: write buffer
|
||||
- `drain`
|
||||
- Called when a socket buffer is drained
|
||||
- **Arguments**
|
||||
- `Socket`: socket being flushed
|
||||
|
||||
##### Properties
|
||||
|
||||
- `protocol` _(Number)_: protocol revision number
|
||||
- `Server`: Server class constructor
|
||||
- `Socket`: Socket class constructor
|
||||
- `Transport` _(Function)_: transport constructor
|
||||
- `transports` _(Object)_: map of available transports
|
||||
|
||||
##### Methods
|
||||
|
||||
- `()`
|
||||
- Returns a new `Server` instance. If the first argument is an `http.Server` then the
|
||||
new `Server` instance will be attached to it. Otherwise, the arguments are passed
|
||||
directly to the `Server` constructor.
|
||||
- **Parameters**
|
||||
- `http.Server`: optional, server to attach to.
|
||||
- `Object`: optional, options object (see `Server#constructor` api docs below)
|
||||
|
||||
The following are identical ways to instantiate a server and then attach it.
|
||||
|
||||
```js
|
||||
const httpServer; // previously created with `http.createServer();` from node.js api.
|
||||
|
||||
// create a server first, and then attach
|
||||
const eioServer = require('engine.io').Server();
|
||||
eioServer.attach(httpServer);
|
||||
|
||||
// or call the module as a function to get `Server`
|
||||
const eioServer = require('engine.io')();
|
||||
eioServer.attach(httpServer);
|
||||
|
||||
// immediately attach
|
||||
const eioServer = require('engine.io')(httpServer);
|
||||
|
||||
// with custom options
|
||||
const eioServer = require('engine.io')(httpServer, {
|
||||
maxHttpBufferSize: 1e3
|
||||
});
|
||||
```
|
||||
|
||||
- `listen`
|
||||
- Creates an `http.Server` which listens on the given port and attaches WS
|
||||
to it. It returns `501 Not Implemented` for regular http requests.
|
||||
- **Parameters**
|
||||
- `Number`: port to listen on.
|
||||
- `Object`: optional, options object
|
||||
- `Function`: callback for `listen`.
|
||||
- **Options**
|
||||
- All options from `Server.attach` method, documented below.
|
||||
- **Additionally** See Server `constructor` below for options you can pass for creating the new Server
|
||||
- **Returns** `Server`
|
||||
|
||||
```js
|
||||
const engine = require('engine.io');
|
||||
const server = engine.listen(3000, {
|
||||
pingTimeout: 2000,
|
||||
pingInterval: 10000
|
||||
});
|
||||
|
||||
server.on('connection', /* ... */);
|
||||
```
|
||||
|
||||
- `attach`
|
||||
- Captures `upgrade` requests for a `http.Server`. In other words, makes
|
||||
a regular http.Server WebSocket-compatible.
|
||||
- **Parameters**
|
||||
- `http.Server`: server to attach to.
|
||||
- `Object`: optional, options object
|
||||
- **Options**
|
||||
- All options from `Server.attach` method, documented below.
|
||||
- **Additionally** See Server `constructor` below for options you can pass for creating the new Server
|
||||
- **Returns** `Server` a new Server instance.
|
||||
|
||||
```js
|
||||
const engine = require('engine.io');
|
||||
const httpServer = require('http').createServer().listen(3000);
|
||||
const server = engine.attach(httpServer, {
|
||||
wsEngine: require('eiows').Server // requires having eiows as dependency
|
||||
});
|
||||
|
||||
server.on('connection', /* ... */);
|
||||
```
|
||||
|
||||
#### Server
|
||||
|
||||
The main server/manager. _Inherits from EventEmitter_.
|
||||
|
||||
##### Events
|
||||
|
||||
- `connection`
|
||||
- Fired when a new connection is established.
|
||||
- **Arguments**
|
||||
- `Socket`: a Socket object
|
||||
|
||||
- `initial_headers`
|
||||
- Fired on the first request of the connection, before writing the response headers
|
||||
- **Arguments**
|
||||
- `headers` (`Object`): a hash of headers
|
||||
- `req` (`http.IncomingMessage`): the request
|
||||
|
||||
- `headers`
|
||||
- Fired on the all requests of the connection, before writing the response headers
|
||||
- **Arguments**
|
||||
- `headers` (`Object`): a hash of headers
|
||||
- `req` (`http.IncomingMessage`): the request
|
||||
|
||||
- `connection_error`
|
||||
- Fired when an error occurs when establishing the connection.
|
||||
- **Arguments**
|
||||
- `error`: an object with following properties:
|
||||
- `req` (`http.IncomingMessage`): the request that was dropped
|
||||
- `code` (`Number`): one of `Server.errors`
|
||||
- `message` (`string`): one of `Server.errorMessages`
|
||||
- `context` (`Object`): extra info about the error
|
||||
|
||||
| Code | Message |
|
||||
| ---- | ------- |
|
||||
| 0 | "Transport unknown"
|
||||
| 1 | "Session ID unknown"
|
||||
| 2 | "Bad handshake method"
|
||||
| 3 | "Bad request"
|
||||
| 4 | "Forbidden"
|
||||
| 5 | "Unsupported protocol version"
|
||||
|
||||
|
||||
##### Properties
|
||||
|
||||
**Important**: if you plan to use Engine.IO in a scalable way, please
|
||||
keep in mind the properties below will only reflect the clients connected
|
||||
to a single process.
|
||||
|
||||
- `clients` _(Object)_: hash of connected clients by id.
|
||||
- `clientsCount` _(Number)_: number of connected clients.
|
||||
|
||||
##### Methods
|
||||
|
||||
- **constructor**
|
||||
- Initializes the server
|
||||
- **Parameters**
|
||||
- `Object`: optional, options object
|
||||
- **Options**
|
||||
- `pingTimeout` (`Number`): how many ms without a pong packet to
|
||||
consider the connection closed (`20000`)
|
||||
- `pingInterval` (`Number`): how many ms before sending a new ping
|
||||
packet (`25000`)
|
||||
- `upgradeTimeout` (`Number`): how many ms before an uncompleted transport upgrade is cancelled (`10000`)
|
||||
- `maxHttpBufferSize` (`Number`): how many bytes or characters a message
|
||||
can be, before closing the session (to avoid DoS). Default
|
||||
value is `1E6`.
|
||||
- `allowRequest` (`Function`): A function that receives a given handshake
|
||||
or upgrade request as its first parameter, and can decide whether to
|
||||
continue or not. The second argument is a function that needs to be
|
||||
called with the decided information: `fn(err, success)`, where
|
||||
`success` is a boolean value where false means that the request is
|
||||
rejected, and err is an error code.
|
||||
- `transports` (`<Array> String`): transports to allow connections
|
||||
to (`['polling', 'websocket']`)
|
||||
- `allowUpgrades` (`Boolean`): whether to allow transport upgrades
|
||||
(`true`)
|
||||
- `perMessageDeflate` (`Object|Boolean`): parameters of the WebSocket permessage-deflate extension
|
||||
(see [ws module](https://github.com/einaros/ws) api docs). Set to `true` to enable. (defaults to `false`)
|
||||
- `threshold` (`Number`): data is compressed only if the byte size is above this value (`1024`)
|
||||
- `httpCompression` (`Object|Boolean`): parameters of the http compression for the polling transports
|
||||
(see [zlib](http://nodejs.org/api/zlib.html#zlib_options) api docs). Set to `false` to disable. (`true`)
|
||||
- `threshold` (`Number`): data is compressed only if the byte size is above this value (`1024`)
|
||||
- `cookie` (`Object|Boolean`): configuration of the cookie that
|
||||
contains the client sid to send as part of handshake response
|
||||
headers. This cookie might be used for sticky-session. Defaults to not sending any cookie (`false`).
|
||||
See [here](https://github.com/jshttp/cookie#options-1) for all supported options.
|
||||
- `wsEngine` (`Function`): what WebSocket server implementation to use. Specified module must conform to the `ws` interface (see [ws module api docs](https://github.com/websockets/ws/blob/master/doc/ws.md)). Default value is `ws`. An alternative c++ addon is also available by installing `eiows` module.
|
||||
- `cors` (`Object`): the options that will be forwarded to the cors module. See [there](https://github.com/expressjs/cors#configuration-options) for all available options. Defaults to no CORS allowed.
|
||||
- `initialPacket` (`Object`): an optional packet which will be concatenated to the handshake packet emitted by Engine.IO.
|
||||
- `allowEIO3` (`Boolean`): whether to support v3 Engine.IO clients (defaults to `false`)
|
||||
- `close`
|
||||
- Closes all clients
|
||||
- **Returns** `Server` for chaining
|
||||
- `handleRequest`
|
||||
- Called internally when a `Engine` request is intercepted.
|
||||
- **Parameters**
|
||||
- `http.IncomingMessage`: a node request object
|
||||
- `http.ServerResponse`: a node response object
|
||||
- **Returns** `Server` for chaining
|
||||
- `handleUpgrade`
|
||||
- Called internally when a `Engine` ws upgrade is intercepted.
|
||||
- **Parameters** (same as `upgrade` event)
|
||||
- `http.IncomingMessage`: a node request object
|
||||
- `net.Stream`: TCP socket for the request
|
||||
- `Buffer`: legacy tail bytes
|
||||
- **Returns** `Server` for chaining
|
||||
- `attach`
|
||||
- Attach this Server instance to an `http.Server`
|
||||
- Captures `upgrade` requests for a `http.Server`. In other words, makes
|
||||
a regular http.Server WebSocket-compatible.
|
||||
- **Parameters**
|
||||
- `http.Server`: server to attach to.
|
||||
- `Object`: optional, options object
|
||||
- **Options**
|
||||
- `path` (`String`): name of the path to capture (`/engine.io`).
|
||||
- `destroyUpgrade` (`Boolean`): destroy unhandled upgrade requests (`true`)
|
||||
- `destroyUpgradeTimeout` (`Number`): milliseconds after which unhandled requests are ended (`1000`)
|
||||
- `generateId`
|
||||
- Generate a socket id.
|
||||
- Overwrite this method to generate your custom socket id.
|
||||
- **Parameters**
|
||||
- `http.IncomingMessage`: a node request object
|
||||
- **Returns** A socket id for connected client.
|
||||
|
||||
<hr><br>
|
||||
|
||||
#### Socket
|
||||
|
||||
A representation of a client. _Inherits from EventEmitter_.
|
||||
|
||||
##### Events
|
||||
|
||||
- `close`
|
||||
- Fired when the client is disconnected.
|
||||
- **Arguments**
|
||||
- `String`: reason for closing
|
||||
- `Object`: description object (optional)
|
||||
- `message`
|
||||
- Fired when the client sends a message.
|
||||
- **Arguments**
|
||||
- `String` or `Buffer`: Unicode string or Buffer with binary contents
|
||||
- `error`
|
||||
- Fired when an error occurs.
|
||||
- **Arguments**
|
||||
- `Error`: error object
|
||||
- `upgrading`
|
||||
- Fired when the client starts the upgrade to a better transport like WebSocket.
|
||||
- **Arguments**
|
||||
- `Object`: the transport
|
||||
- `upgrade`
|
||||
- Fired when the client completes the upgrade to a better transport like WebSocket.
|
||||
- **Arguments**
|
||||
- `Object`: the transport
|
||||
- `flush`
|
||||
- Called when the write buffer is being flushed.
|
||||
- **Arguments**
|
||||
- `Array`: write buffer
|
||||
- `drain`
|
||||
- Called when the write buffer is drained
|
||||
- `packet`
|
||||
- Called when a socket received a packet (`message`, `ping`)
|
||||
- **Arguments**
|
||||
- `type`: packet type
|
||||
- `data`: packet data (if type is message)
|
||||
- `packetCreate`
|
||||
- Called before a socket sends a packet (`message`, `ping`)
|
||||
- **Arguments**
|
||||
- `type`: packet type
|
||||
- `data`: packet data (if type is message)
|
||||
- `heartbeat`
|
||||
- Called when `ping` or `pong` packed is received (depends of client version)
|
||||
|
||||
##### Properties
|
||||
|
||||
- `id` _(String)_: unique identifier
|
||||
- `server` _(Server)_: engine parent reference
|
||||
- `request` _(http.IncomingMessage)_: request that originated the Socket
|
||||
- `upgraded` _(Boolean)_: whether the transport has been upgraded
|
||||
- `readyState` _(String)_: opening|open|closing|closed
|
||||
- `transport` _(Transport)_: transport reference
|
||||
|
||||
##### Methods
|
||||
|
||||
- `send`:
|
||||
- Sends a message, performing `message = toString(arguments[0])` unless
|
||||
sending binary data, which is sent as is.
|
||||
- **Parameters**
|
||||
- `String` | `Buffer` | `ArrayBuffer` | `ArrayBufferView`: a string or any object implementing `toString()`, with outgoing data, or a Buffer or ArrayBuffer with binary data. Also any ArrayBufferView can be sent as is.
|
||||
- `Object`: optional, options object
|
||||
- `Function`: optional, a callback executed when the message gets flushed out by the transport
|
||||
- **Options**
|
||||
- `compress` (`Boolean`): whether to compress sending data. This option might be ignored and forced to be `true` when using polling. (`true`)
|
||||
- **Returns** `Socket` for chaining
|
||||
- `close`
|
||||
- Disconnects the client
|
||||
- **Returns** `Socket` for chaining
|
||||
|
||||
### Client
|
||||
|
||||
<hr><br>
|
||||
|
||||
Exposed in the `eio` global namespace (in the browser), or by
|
||||
`require('engine.io-client')` (in Node.JS).
|
||||
|
||||
For the client API refer to the
|
||||
[engine-client](http://github.com/learnboost/engine.io-client) repository.
|
||||
|
||||
## Debug / logging
|
||||
|
||||
Engine.IO is powered by [debug](http://github.com/visionmedia/debug).
|
||||
In order to see all the debug output, run your app with the environment variable
|
||||
`DEBUG` including the desired scope.
|
||||
|
||||
To see the output from all of Engine.IO's debugging scopes you can use:
|
||||
|
||||
```
|
||||
DEBUG=engine* node myapp
|
||||
```
|
||||
|
||||
## Transports
|
||||
|
||||
- `polling`: XHR / JSONP polling transport.
|
||||
- `websocket`: WebSocket transport.
|
||||
|
||||
## Plugins
|
||||
|
||||
- [engine.io-conflation](https://github.com/EugenDueck/engine.io-conflation): Makes **conflation and aggregation** of messages straightforward.
|
||||
|
||||
## Support
|
||||
|
||||
The support channels for `engine.io` are the same as `socket.io`:
|
||||
- irc.freenode.net **#socket.io**
|
||||
- [Google Groups](http://groups.google.com/group/socket_io)
|
||||
- [Website](http://socket.io)
|
||||
|
||||
## Development
|
||||
|
||||
To contribute patches, run tests or benchmarks, make sure to clone the
|
||||
repository:
|
||||
|
||||
```
|
||||
git clone git://github.com/LearnBoost/engine.io.git
|
||||
```
|
||||
|
||||
Then:
|
||||
|
||||
```
|
||||
cd engine.io
|
||||
npm install
|
||||
```
|
||||
|
||||
## Tests
|
||||
|
||||
Tests run with `npm test`. It runs the server tests that are aided by
|
||||
the usage of `engine.io-client`.
|
||||
|
||||
Make sure `npm install` is run first.
|
||||
|
||||
## Goals
|
||||
|
||||
The main goal of `Engine` is ensuring the most reliable realtime communication.
|
||||
Unlike the previous Socket.IO core, it always establishes a long-polling
|
||||
connection first, then tries to upgrade to better transports that are "tested" on
|
||||
the side.
|
||||
|
||||
During the lifetime of the Socket.IO projects, we've found countless drawbacks
|
||||
to relying on `HTML5 WebSocket` or `Flash Socket` as the first connection
|
||||
mechanisms.
|
||||
|
||||
Both are clearly the _right way_ of establishing a bidirectional communication,
|
||||
with HTML5 WebSocket being the way of the future. However, to answer most business
|
||||
needs, alternative traditional HTTP 1.1 mechanisms are just as good as delivering
|
||||
the same solution.
|
||||
|
||||
WebSocket based connections have two fundamental benefits:
|
||||
|
||||
1. **Better server performance**
|
||||
- _A: Load balancers_<br>
|
||||
Load balancing a long polling connection poses a serious architectural nightmare
|
||||
since requests can come from any number of open sockets by the user agent, but
|
||||
they all need to be routed to the process and computer that owns the `Engine`
|
||||
connection. This negatively impacts RAM and CPU usage.
|
||||
- _B: Network traffic_<br>
|
||||
WebSocket is designed around the premise that each message frame has to be
|
||||
surrounded by the least amount of data. In HTTP 1.1 transports, each message
|
||||
frame is surrounded by HTTP headers and chunked encoding frames. If you try to
|
||||
send the message _"Hello world"_ with xhr-polling, the message ultimately
|
||||
becomes larger than if you were to send it with WebSocket.
|
||||
- _C: Lightweight parser_<br>
|
||||
As an effect of **B**, the server has to do a lot more work to parse the network
|
||||
data and figure out the message when traditional HTTP requests are used
|
||||
(as in long polling). This means that another advantage of WebSocket is
|
||||
less server CPU usage.
|
||||
|
||||
2. **Better user experience**
|
||||
|
||||
Due to the reasons stated in point **1**, the most important effect of being able
|
||||
to establish a WebSocket connection is raw data transfer speed, which translates
|
||||
in _some_ cases in better user experience.
|
||||
|
||||
Applications with heavy realtime interaction (such as games) will benefit greatly,
|
||||
whereas applications like realtime chat (Gmail/Facebook), newsfeeds (Facebook) or
|
||||
timelines (Twitter) will have negligible user experience improvements.
|
||||
|
||||
Having said this, attempting to establish a WebSocket connection directly so far has
|
||||
proven problematic:
|
||||
|
||||
1. **Proxies**<br>
|
||||
Many corporate proxies block WebSocket traffic.
|
||||
|
||||
2. **Personal firewall and antivirus software**<br>
|
||||
As a result of our research, we've found that at least 3 personal security
|
||||
applications block WebSocket traffic.
|
||||
|
||||
3. **Cloud application platforms**<br>
|
||||
Platforms like Heroku or No.de have had trouble keeping up with the fast-paced
|
||||
nature of the evolution of the WebSocket protocol. Applications therefore end up
|
||||
inevitably using long polling, but the seamless installation experience of
|
||||
Socket.IO we strive for (_"require() it and it just works"_) disappears.
|
||||
|
||||
Some of these problems have solutions. In the case of proxies and personal programs,
|
||||
however, the solutions many times involve upgrading software. Experience has shown
|
||||
that relying on client software upgrades to deliver a business solution is
|
||||
fruitless: the very existence of this project has to do with a fragmented panorama
|
||||
of user agent distribution, with clients connecting with latest versions of the most
|
||||
modern user agents (Chrome, Firefox and Safari), but others with versions as low as
|
||||
IE 5.5.
|
||||
|
||||
From the user perspective, an unsuccessful WebSocket connection can translate in
|
||||
up to at least 10 seconds of waiting for the realtime application to begin
|
||||
exchanging data. This **perceptively** hurts user experience.
|
||||
|
||||
To summarize, **Engine** focuses on reliability and user experience first, marginal
|
||||
potential UX improvements and increased server performance second. `Engine` is the
|
||||
result of all the lessons learned with WebSocket in the wild.
|
||||
|
||||
## Architecture
|
||||
|
||||
The main premise of `Engine`, and the core of its existence, is the ability to
|
||||
swap transports on the fly. A connection starts as xhr-polling, but it can
|
||||
switch to WebSocket.
|
||||
|
||||
The central problem this poses is: how do we switch transports without losing
|
||||
messages?
|
||||
|
||||
`Engine` only switches from polling to another transport in between polling
|
||||
cycles. Since the server closes the connection after a certain timeout when
|
||||
there's no activity, and the polling transport implementation buffers messages
|
||||
in between connections, this ensures no message loss and optimal performance.
|
||||
|
||||
Another benefit of this design is that we workaround almost all the limitations
|
||||
of **Flash Socket**, such as slow connection times, increased file size (we can
|
||||
safely lazy load it without hurting user experience), etc.
|
||||
|
||||
## FAQ
|
||||
|
||||
### Can I use engine without Socket.IO ?
|
||||
|
||||
Absolutely. Although the recommended framework for building realtime applications
|
||||
is Socket.IO, since it provides fundamental features for real-world applications
|
||||
such as multiplexing, reconnection support, etc.
|
||||
|
||||
`Engine` is to Socket.IO what Connect is to Express. An essential piece for building
|
||||
realtime frameworks, but something you _probably_ won't be using for building
|
||||
actual applications.
|
||||
|
||||
### Does the server serve the client?
|
||||
|
||||
No. The main reason is that `Engine` is meant to be bundled with frameworks.
|
||||
Socket.IO includes `Engine`, therefore serving two clients is not necessary. If
|
||||
you use Socket.IO, including
|
||||
|
||||
```html
|
||||
<script src="/socket.io/socket.io.js">
|
||||
```
|
||||
|
||||
has you covered.
|
||||
|
||||
### Can I implement `Engine` in other languages?
|
||||
|
||||
Absolutely. The [engine.io-protocol](https://github.com/socketio/engine.io-protocol)
|
||||
repository contains the most up-to-date description of the specification
|
||||
at all times.
|
||||
|
||||
## License
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014 Guillermo Rauch <guillermo@learnboost.com>
|
||||
|
||||
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.
|
||||
113
node_modules/engine.io/build/contrib/types.cookie.d.ts
generated
vendored
Normal file
113
node_modules/engine.io/build/contrib/types.cookie.d.ts
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* Basic HTTP cookie parser and serializer for HTTP servers.
|
||||
*/
|
||||
/**
|
||||
* Additional serialization options
|
||||
*/
|
||||
export interface CookieSerializeOptions {
|
||||
/**
|
||||
* Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.3|Domain Set-Cookie attribute}. By default, no
|
||||
* domain is set, and most clients will consider the cookie to apply to only
|
||||
* the current domain.
|
||||
*/
|
||||
domain?: string | undefined;
|
||||
/**
|
||||
* Specifies a function that will be used to encode a cookie's value. Since
|
||||
* value of a cookie has a limited character set (and must be a simple
|
||||
* string), this function can be used to encode a value into a string suited
|
||||
* for a cookie's value.
|
||||
*
|
||||
* The default function is the global `encodeURIComponent`, which will
|
||||
* encode a JavaScript string into UTF-8 byte sequences and then URL-encode
|
||||
* any that fall outside of the cookie range.
|
||||
*/
|
||||
encode?(value: string): string;
|
||||
/**
|
||||
* Specifies the `Date` object to be the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.1|`Expires` `Set-Cookie` attribute}. By default,
|
||||
* no expiration is set, and most clients will consider this a "non-persistent cookie" and will delete
|
||||
* it on a condition like exiting a web browser application.
|
||||
*
|
||||
* *Note* the {@link https://tools.ietf.org/html/rfc6265#section-5.3|cookie storage model specification}
|
||||
* states that if both `expires` and `maxAge` are set, then `maxAge` takes precedence, but it is
|
||||
* possible not all clients by obey this, so if both are set, they should
|
||||
* point to the same date and time.
|
||||
*/
|
||||
expires?: Date | undefined;
|
||||
/**
|
||||
* Specifies the boolean value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.6|`HttpOnly` `Set-Cookie` attribute}.
|
||||
* When truthy, the `HttpOnly` attribute is set, otherwise it is not. By
|
||||
* default, the `HttpOnly` attribute is not set.
|
||||
*
|
||||
* *Note* be careful when setting this to true, as compliant clients will
|
||||
* not allow client-side JavaScript to see the cookie in `document.cookie`.
|
||||
*/
|
||||
httpOnly?: boolean | undefined;
|
||||
/**
|
||||
* Specifies the number (in seconds) to be the value for the `Max-Age`
|
||||
* `Set-Cookie` attribute. The given number will be converted to an integer
|
||||
* by rounding down. By default, no maximum age is set.
|
||||
*
|
||||
* *Note* the {@link https://tools.ietf.org/html/rfc6265#section-5.3|cookie storage model specification}
|
||||
* states that if both `expires` and `maxAge` are set, then `maxAge` takes precedence, but it is
|
||||
* possible not all clients by obey this, so if both are set, they should
|
||||
* point to the same date and time.
|
||||
*/
|
||||
maxAge?: number | undefined;
|
||||
/**
|
||||
* Specifies the `boolean` value for the [`Partitioned` `Set-Cookie`](rfc-cutler-httpbis-partitioned-cookies)
|
||||
* attribute. When truthy, the `Partitioned` attribute is set, otherwise it is not. By default, the
|
||||
* `Partitioned` attribute is not set.
|
||||
*
|
||||
* **note** This is an attribute that has not yet been fully standardized, and may change in the future.
|
||||
* This also means many clients may ignore this attribute until they understand it.
|
||||
*
|
||||
* More information about can be found in [the proposal](https://github.com/privacycg/CHIPS)
|
||||
*/
|
||||
partitioned?: boolean | undefined;
|
||||
/**
|
||||
* Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.4|`Path` `Set-Cookie` attribute}.
|
||||
* By default, the path is considered the "default path".
|
||||
*/
|
||||
path?: string | undefined;
|
||||
/**
|
||||
* Specifies the `string` to be the value for the [`Priority` `Set-Cookie` attribute][rfc-west-cookie-priority-00-4.1].
|
||||
*
|
||||
* - `'low'` will set the `Priority` attribute to `Low`.
|
||||
* - `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set.
|
||||
* - `'high'` will set the `Priority` attribute to `High`.
|
||||
*
|
||||
* More information about the different priority levels can be found in
|
||||
* [the specification][rfc-west-cookie-priority-00-4.1].
|
||||
*
|
||||
* **note** This is an attribute that has not yet been fully standardized, and may change in the future.
|
||||
* This also means many clients may ignore this attribute until they understand it.
|
||||
*/
|
||||
priority?: "low" | "medium" | "high" | undefined;
|
||||
/**
|
||||
* Specifies the boolean or string to be the value for the {@link https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7|`SameSite` `Set-Cookie` attribute}.
|
||||
*
|
||||
* - `true` will set the `SameSite` attribute to `Strict` for strict same
|
||||
* site enforcement.
|
||||
* - `false` will not set the `SameSite` attribute.
|
||||
* - `'lax'` will set the `SameSite` attribute to Lax for lax same site
|
||||
* enforcement.
|
||||
* - `'strict'` will set the `SameSite` attribute to Strict for strict same
|
||||
* site enforcement.
|
||||
* - `'none'` will set the SameSite attribute to None for an explicit
|
||||
* cross-site cookie.
|
||||
*
|
||||
* More information about the different enforcement levels can be found in {@link https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7|the specification}.
|
||||
*
|
||||
* *note* This is an attribute that has not yet been fully standardized, and may change in the future. This also means many clients may ignore this attribute until they understand it.
|
||||
*/
|
||||
sameSite?: true | false | "lax" | "strict" | "none" | undefined;
|
||||
/**
|
||||
* Specifies the boolean value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.5|`Secure` `Set-Cookie` attribute}. When truthy, the
|
||||
* `Secure` attribute is set, otherwise it is not. By default, the `Secure` attribute is not set.
|
||||
*
|
||||
* *Note* be careful when setting this to `true`, as compliant clients will
|
||||
* not send the cookie back to the server in the future if the browser does
|
||||
* not have an HTTPS connection.
|
||||
*/
|
||||
secure?: boolean | undefined;
|
||||
}
|
||||
6
node_modules/engine.io/build/contrib/types.cookie.js
generated
vendored
Normal file
6
node_modules/engine.io/build/contrib/types.cookie.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
"use strict";
|
||||
// imported from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/b83cf9ef8b044e69f05b2a00aa7c6cb767a9acd2/types/cookie/index.d.ts (now deleted)
|
||||
/**
|
||||
* Basic HTTP cookie parser and serializer for HTTP servers.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
27
node_modules/engine.io/build/engine.io.d.ts
generated
vendored
Normal file
27
node_modules/engine.io/build/engine.io.d.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Server as HttpServer } from "http";
|
||||
import { Server, AttachOptions, ServerOptions } from "./server";
|
||||
import transports from "./transports/index";
|
||||
import * as parser from "engine.io-parser";
|
||||
export { Server, transports, listen, attach, parser };
|
||||
export type { AttachOptions, ServerOptions, BaseServer, ErrorCallback, } from "./server";
|
||||
export { uServer } from "./userver";
|
||||
export { Socket } from "./socket";
|
||||
export { Transport } from "./transport";
|
||||
export declare const protocol = 4;
|
||||
/**
|
||||
* Creates an http.Server exclusively used for WS upgrades, and starts listening.
|
||||
*
|
||||
* @param port
|
||||
* @param options
|
||||
* @param listenCallback - callback for http.Server.listen()
|
||||
* @return engine.io server
|
||||
*/
|
||||
declare function listen(port: number, options?: AttachOptions & ServerOptions, listenCallback?: () => void): Server;
|
||||
/**
|
||||
* Captures upgrade requests for a http.Server.
|
||||
*
|
||||
* @param server
|
||||
* @param options
|
||||
* @return engine.io server
|
||||
*/
|
||||
declare function attach(server: HttpServer, options: AttachOptions & ServerOptions): Server;
|
||||
54
node_modules/engine.io/build/engine.io.js
generated
vendored
Normal file
54
node_modules/engine.io/build/engine.io.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.protocol = exports.Transport = exports.Socket = exports.uServer = exports.parser = exports.transports = exports.Server = void 0;
|
||||
exports.listen = listen;
|
||||
exports.attach = attach;
|
||||
const http_1 = require("http");
|
||||
const server_1 = require("./server");
|
||||
Object.defineProperty(exports, "Server", { enumerable: true, get: function () { return server_1.Server; } });
|
||||
const index_1 = require("./transports/index");
|
||||
exports.transports = index_1.default;
|
||||
const parser = require("engine.io-parser");
|
||||
exports.parser = parser;
|
||||
var userver_1 = require("./userver");
|
||||
Object.defineProperty(exports, "uServer", { enumerable: true, get: function () { return userver_1.uServer; } });
|
||||
var socket_1 = require("./socket");
|
||||
Object.defineProperty(exports, "Socket", { enumerable: true, get: function () { return socket_1.Socket; } });
|
||||
var transport_1 = require("./transport");
|
||||
Object.defineProperty(exports, "Transport", { enumerable: true, get: function () { return transport_1.Transport; } });
|
||||
exports.protocol = parser.protocol;
|
||||
/**
|
||||
* Creates an http.Server exclusively used for WS upgrades, and starts listening.
|
||||
*
|
||||
* @param port
|
||||
* @param options
|
||||
* @param listenCallback - callback for http.Server.listen()
|
||||
* @return engine.io server
|
||||
*/
|
||||
function listen(port, options, listenCallback) {
|
||||
if ("function" === typeof options) {
|
||||
listenCallback = options;
|
||||
options = {};
|
||||
}
|
||||
const server = (0, http_1.createServer)(function (req, res) {
|
||||
res.writeHead(501);
|
||||
res.end("Not Implemented");
|
||||
});
|
||||
// create engine server
|
||||
const engine = attach(server, options);
|
||||
engine.httpServer = server;
|
||||
server.listen(port, listenCallback);
|
||||
return engine;
|
||||
}
|
||||
/**
|
||||
* Captures upgrade requests for a http.Server.
|
||||
*
|
||||
* @param server
|
||||
* @param options
|
||||
* @return engine.io server
|
||||
*/
|
||||
function attach(server, options) {
|
||||
const engine = new server_1.Server(options);
|
||||
engine.attach(server, options);
|
||||
return engine;
|
||||
}
|
||||
88
node_modules/engine.io/build/parser-v3/index.d.ts
generated
vendored
Normal file
88
node_modules/engine.io/build/parser-v3/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Current protocol version.
|
||||
*/
|
||||
export declare const protocol = 3;
|
||||
/**
|
||||
* Packet types.
|
||||
*/
|
||||
export declare const packets: {
|
||||
open: number;
|
||||
close: number;
|
||||
ping: number;
|
||||
pong: number;
|
||||
message: number;
|
||||
upgrade: number;
|
||||
noop: number;
|
||||
};
|
||||
/**
|
||||
* Encodes a packet.
|
||||
*
|
||||
* <packet type id> [ <data> ]
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* 5hello world
|
||||
* 3
|
||||
* 4
|
||||
*
|
||||
* Binary is encoded in an identical principle
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
export declare function encodePacket(packet: any, supportsBinary?: any, utf8encode?: any, callback?: any): any;
|
||||
/**
|
||||
* Encodes a packet with binary data in a base64 string
|
||||
*
|
||||
* @param {Object} packet, has `type` and `data`
|
||||
* @return {String} base64 encoded message
|
||||
*/
|
||||
export declare function encodeBase64Packet(packet: any, callback: any): any;
|
||||
/**
|
||||
* Decodes a packet. Data also available as an ArrayBuffer if requested.
|
||||
*
|
||||
* @return {import('engine.io-parser').Packet} with `type` and `data` (if any)
|
||||
* @api private
|
||||
*/
|
||||
export declare function decodePacket(data: any, binaryType?: any, utf8decode?: any): any;
|
||||
/**
|
||||
* Decodes a packet encoded in a base64 string.
|
||||
*
|
||||
* @param {String} base64 encoded message
|
||||
* @return {Object} with `type` and `data` (if any)
|
||||
*/
|
||||
export declare function decodeBase64Packet(msg: any, binaryType: any): {
|
||||
type: string;
|
||||
data: Buffer;
|
||||
};
|
||||
/**
|
||||
* Encodes multiple messages (payload).
|
||||
*
|
||||
* <length>:data
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* 11:hello world2:hi
|
||||
*
|
||||
* If any contents are binary, they will be encoded as base64 strings. Base64
|
||||
* encoded strings are marked with a b before the length specifier
|
||||
*
|
||||
* @param {Array} packets
|
||||
* @api private
|
||||
*/
|
||||
export declare function encodePayload(packets: any, supportsBinary: any, callback: any): any;
|
||||
export declare function decodePayload(data: any, binaryType?: any, callback?: any): any;
|
||||
/**
|
||||
* Encodes multiple messages (payload) as binary.
|
||||
*
|
||||
* <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number
|
||||
* 255><data>
|
||||
*
|
||||
* Example:
|
||||
* 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
|
||||
*
|
||||
* @param {Array} packets
|
||||
* @return {Buffer} encoded payload
|
||||
* @api private
|
||||
*/
|
||||
export declare function encodePayloadAsBinary(packets: any, callback: any): any;
|
||||
export declare function decodePayloadAsBinary(data: any, binaryType: any, callback: any): any;
|
||||
424
node_modules/engine.io/build/parser-v3/index.js
generated
vendored
Normal file
424
node_modules/engine.io/build/parser-v3/index.js
generated
vendored
Normal file
@@ -0,0 +1,424 @@
|
||||
"use strict";
|
||||
// imported from https://github.com/socketio/engine.io-parser/tree/2.2.x
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.packets = exports.protocol = void 0;
|
||||
exports.encodePacket = encodePacket;
|
||||
exports.encodeBase64Packet = encodeBase64Packet;
|
||||
exports.decodePacket = decodePacket;
|
||||
exports.decodeBase64Packet = decodeBase64Packet;
|
||||
exports.encodePayload = encodePayload;
|
||||
exports.decodePayload = decodePayload;
|
||||
exports.encodePayloadAsBinary = encodePayloadAsBinary;
|
||||
exports.decodePayloadAsBinary = decodePayloadAsBinary;
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
var utf8 = require('./utf8');
|
||||
/**
|
||||
* Current protocol version.
|
||||
*/
|
||||
exports.protocol = 3;
|
||||
const hasBinary = (packets) => {
|
||||
for (const packet of packets) {
|
||||
if (packet.data instanceof ArrayBuffer || ArrayBuffer.isView(packet.data)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
/**
|
||||
* Packet types.
|
||||
*/
|
||||
exports.packets = {
|
||||
open: 0 // non-ws
|
||||
,
|
||||
close: 1 // non-ws
|
||||
,
|
||||
ping: 2,
|
||||
pong: 3,
|
||||
message: 4,
|
||||
upgrade: 5,
|
||||
noop: 6
|
||||
};
|
||||
var packetslist = Object.keys(exports.packets);
|
||||
/**
|
||||
* Premade error packet.
|
||||
*/
|
||||
var err = { type: 'error', data: 'parser error' };
|
||||
const EMPTY_BUFFER = Buffer.concat([]);
|
||||
/**
|
||||
* Encodes a packet.
|
||||
*
|
||||
* <packet type id> [ <data> ]
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* 5hello world
|
||||
* 3
|
||||
* 4
|
||||
*
|
||||
* Binary is encoded in an identical principle
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
function encodePacket(packet, supportsBinary, utf8encode, callback) {
|
||||
if (typeof supportsBinary === 'function') {
|
||||
callback = supportsBinary;
|
||||
supportsBinary = null;
|
||||
}
|
||||
if (typeof utf8encode === 'function') {
|
||||
callback = utf8encode;
|
||||
utf8encode = null;
|
||||
}
|
||||
if (Buffer.isBuffer(packet.data)) {
|
||||
return encodeBuffer(packet, supportsBinary, callback);
|
||||
}
|
||||
else if (packet.data && (packet.data.buffer || packet.data) instanceof ArrayBuffer) {
|
||||
return encodeBuffer({ type: packet.type, data: arrayBufferToBuffer(packet.data) }, supportsBinary, callback);
|
||||
}
|
||||
// Sending data as a utf-8 string
|
||||
var encoded = exports.packets[packet.type];
|
||||
// data fragment is optional
|
||||
if (undefined !== packet.data) {
|
||||
encoded += utf8encode ? utf8.encode(String(packet.data), { strict: false }) : String(packet.data);
|
||||
}
|
||||
return callback('' + encoded);
|
||||
}
|
||||
/**
|
||||
* Encode Buffer data
|
||||
*/
|
||||
function encodeBuffer(packet, supportsBinary, callback) {
|
||||
if (!supportsBinary) {
|
||||
return encodeBase64Packet(packet, callback);
|
||||
}
|
||||
var data = packet.data;
|
||||
var typeBuffer = Buffer.allocUnsafe(1);
|
||||
typeBuffer[0] = exports.packets[packet.type];
|
||||
return callback(Buffer.concat([typeBuffer, data]));
|
||||
}
|
||||
/**
|
||||
* Encodes a packet with binary data in a base64 string
|
||||
*
|
||||
* @param {Object} packet, has `type` and `data`
|
||||
* @return {String} base64 encoded message
|
||||
*/
|
||||
function encodeBase64Packet(packet, callback) {
|
||||
var data = Buffer.isBuffer(packet.data) ? packet.data : arrayBufferToBuffer(packet.data);
|
||||
var message = 'b' + exports.packets[packet.type];
|
||||
message += data.toString('base64');
|
||||
return callback(message);
|
||||
}
|
||||
;
|
||||
/**
|
||||
* Decodes a packet. Data also available as an ArrayBuffer if requested.
|
||||
*
|
||||
* @return {import('engine.io-parser').Packet} with `type` and `data` (if any)
|
||||
* @api private
|
||||
*/
|
||||
function decodePacket(data, binaryType, utf8decode) {
|
||||
if (data === undefined) {
|
||||
return err;
|
||||
}
|
||||
let type;
|
||||
// String data
|
||||
if (typeof data === 'string') {
|
||||
type = data.charAt(0);
|
||||
if (type === 'b') {
|
||||
return decodeBase64Packet(data.slice(1), binaryType);
|
||||
}
|
||||
if (utf8decode) {
|
||||
data = tryDecode(data);
|
||||
if (data === false) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
// @ts-expect-error
|
||||
if (Number(type) != type || !packetslist[type]) {
|
||||
return err;
|
||||
}
|
||||
if (data.length > 1) {
|
||||
return { type: packetslist[type], data: data.slice(1) };
|
||||
}
|
||||
else {
|
||||
return { type: packetslist[type] };
|
||||
}
|
||||
}
|
||||
// Binary data
|
||||
if (binaryType === 'arraybuffer') {
|
||||
// wrap Buffer/ArrayBuffer data into an Uint8Array
|
||||
var intArray = new Uint8Array(data);
|
||||
type = intArray[0];
|
||||
return { type: packetslist[type], data: intArray.buffer.slice(1) };
|
||||
}
|
||||
if (data instanceof ArrayBuffer) {
|
||||
data = arrayBufferToBuffer(data);
|
||||
}
|
||||
type = data[0];
|
||||
return { type: packetslist[type], data: data.slice(1) };
|
||||
}
|
||||
;
|
||||
function tryDecode(data) {
|
||||
try {
|
||||
data = utf8.decode(data, { strict: false });
|
||||
}
|
||||
catch (e) {
|
||||
return false;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
/**
|
||||
* Decodes a packet encoded in a base64 string.
|
||||
*
|
||||
* @param {String} base64 encoded message
|
||||
* @return {Object} with `type` and `data` (if any)
|
||||
*/
|
||||
function decodeBase64Packet(msg, binaryType) {
|
||||
var type = packetslist[msg.charAt(0)];
|
||||
var data = Buffer.from(msg.slice(1), 'base64');
|
||||
if (binaryType === 'arraybuffer') {
|
||||
var abv = new Uint8Array(data.length);
|
||||
for (var i = 0; i < abv.length; i++) {
|
||||
abv[i] = data[i];
|
||||
}
|
||||
// @ts-ignore
|
||||
data = abv.buffer;
|
||||
}
|
||||
return { type: type, data: data };
|
||||
}
|
||||
;
|
||||
/**
|
||||
* Encodes multiple messages (payload).
|
||||
*
|
||||
* <length>:data
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* 11:hello world2:hi
|
||||
*
|
||||
* If any contents are binary, they will be encoded as base64 strings. Base64
|
||||
* encoded strings are marked with a b before the length specifier
|
||||
*
|
||||
* @param {Array} packets
|
||||
* @api private
|
||||
*/
|
||||
function encodePayload(packets, supportsBinary, callback) {
|
||||
if (typeof supportsBinary === 'function') {
|
||||
callback = supportsBinary;
|
||||
supportsBinary = null;
|
||||
}
|
||||
if (supportsBinary && hasBinary(packets)) {
|
||||
return encodePayloadAsBinary(packets, callback);
|
||||
}
|
||||
if (!packets.length) {
|
||||
return callback('0:');
|
||||
}
|
||||
function encodeOne(packet, doneCallback) {
|
||||
encodePacket(packet, supportsBinary, false, function (message) {
|
||||
doneCallback(null, setLengthHeader(message));
|
||||
});
|
||||
}
|
||||
map(packets, encodeOne, function (err, results) {
|
||||
return callback(results.join(''));
|
||||
});
|
||||
}
|
||||
;
|
||||
function setLengthHeader(message) {
|
||||
return message.length + ':' + message;
|
||||
}
|
||||
/**
|
||||
* Async array map using after
|
||||
*/
|
||||
function map(ary, each, done) {
|
||||
const results = new Array(ary.length);
|
||||
let count = 0;
|
||||
for (let i = 0; i < ary.length; i++) {
|
||||
each(ary[i], (error, msg) => {
|
||||
results[i] = msg;
|
||||
if (++count === ary.length) {
|
||||
done(null, results);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Decodes data when a payload is maybe expected. Possible binary contents are
|
||||
* decoded from their base64 representation
|
||||
*
|
||||
* @param {String} data, callback method
|
||||
* @api public
|
||||
*/
|
||||
function decodePayload(data, binaryType, callback) {
|
||||
if (typeof data !== 'string') {
|
||||
return decodePayloadAsBinary(data, binaryType, callback);
|
||||
}
|
||||
if (typeof binaryType === 'function') {
|
||||
callback = binaryType;
|
||||
binaryType = null;
|
||||
}
|
||||
if (data === '') {
|
||||
// parser error - ignoring payload
|
||||
return callback(err, 0, 1);
|
||||
}
|
||||
var length = '', n, msg, packet;
|
||||
for (var i = 0, l = data.length; i < l; i++) {
|
||||
var chr = data.charAt(i);
|
||||
if (chr !== ':') {
|
||||
length += chr;
|
||||
continue;
|
||||
}
|
||||
// @ts-ignore
|
||||
if (length === '' || (length != (n = Number(length)))) {
|
||||
// parser error - ignoring payload
|
||||
return callback(err, 0, 1);
|
||||
}
|
||||
msg = data.slice(i + 1, i + 1 + n);
|
||||
if (length != msg.length) {
|
||||
// parser error - ignoring payload
|
||||
return callback(err, 0, 1);
|
||||
}
|
||||
if (msg.length) {
|
||||
packet = decodePacket(msg, binaryType, false);
|
||||
if (err.type === packet.type && err.data === packet.data) {
|
||||
// parser error in individual packet - ignoring payload
|
||||
return callback(err, 0, 1);
|
||||
}
|
||||
var more = callback(packet, i + n, l);
|
||||
if (false === more)
|
||||
return;
|
||||
}
|
||||
// advance cursor
|
||||
i += n;
|
||||
length = '';
|
||||
}
|
||||
if (length !== '') {
|
||||
// parser error - ignoring payload
|
||||
return callback(err, 0, 1);
|
||||
}
|
||||
}
|
||||
;
|
||||
/**
|
||||
*
|
||||
* Converts a buffer to a utf8.js encoded string
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
function bufferToString(buffer) {
|
||||
var str = '';
|
||||
for (var i = 0, l = buffer.length; i < l; i++) {
|
||||
str += String.fromCharCode(buffer[i]);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* Converts a utf8.js encoded string to a buffer
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
function stringToBuffer(string) {
|
||||
var buf = Buffer.allocUnsafe(string.length);
|
||||
for (var i = 0, l = string.length; i < l; i++) {
|
||||
buf.writeUInt8(string.charCodeAt(i), i);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* Converts an ArrayBuffer to a Buffer
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
function arrayBufferToBuffer(data) {
|
||||
// data is either an ArrayBuffer or ArrayBufferView.
|
||||
var length = data.byteLength || data.length;
|
||||
var offset = data.byteOffset || 0;
|
||||
return Buffer.from(data.buffer || data, offset, length);
|
||||
}
|
||||
/**
|
||||
* Encodes multiple messages (payload) as binary.
|
||||
*
|
||||
* <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number
|
||||
* 255><data>
|
||||
*
|
||||
* Example:
|
||||
* 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
|
||||
*
|
||||
* @param {Array} packets
|
||||
* @return {Buffer} encoded payload
|
||||
* @api private
|
||||
*/
|
||||
function encodePayloadAsBinary(packets, callback) {
|
||||
if (!packets.length) {
|
||||
return callback(EMPTY_BUFFER);
|
||||
}
|
||||
map(packets, encodeOneBinaryPacket, function (err, results) {
|
||||
return callback(Buffer.concat(results));
|
||||
});
|
||||
}
|
||||
;
|
||||
function encodeOneBinaryPacket(p, doneCallback) {
|
||||
function onBinaryPacketEncode(packet) {
|
||||
var encodingLength = '' + packet.length;
|
||||
var sizeBuffer;
|
||||
if (typeof packet === 'string') {
|
||||
sizeBuffer = Buffer.allocUnsafe(encodingLength.length + 2);
|
||||
sizeBuffer[0] = 0; // is a string (not true binary = 0)
|
||||
for (var i = 0; i < encodingLength.length; i++) {
|
||||
sizeBuffer[i + 1] = parseInt(encodingLength[i], 10);
|
||||
}
|
||||
sizeBuffer[sizeBuffer.length - 1] = 255;
|
||||
return doneCallback(null, Buffer.concat([sizeBuffer, stringToBuffer(packet)]));
|
||||
}
|
||||
sizeBuffer = Buffer.allocUnsafe(encodingLength.length + 2);
|
||||
sizeBuffer[0] = 1; // is binary (true binary = 1)
|
||||
for (var i = 0; i < encodingLength.length; i++) {
|
||||
sizeBuffer[i + 1] = parseInt(encodingLength[i], 10);
|
||||
}
|
||||
sizeBuffer[sizeBuffer.length - 1] = 255;
|
||||
doneCallback(null, Buffer.concat([sizeBuffer, packet]));
|
||||
}
|
||||
encodePacket(p, true, true, onBinaryPacketEncode);
|
||||
}
|
||||
/*
|
||||
* Decodes data when a payload is maybe expected. Strings are decoded by
|
||||
* interpreting each byte as a key code for entries marked to start with 0. See
|
||||
* description of encodePayloadAsBinary
|
||||
|
||||
* @param {Buffer} data, callback method
|
||||
* @api public
|
||||
*/
|
||||
function decodePayloadAsBinary(data, binaryType, callback) {
|
||||
if (typeof binaryType === 'function') {
|
||||
callback = binaryType;
|
||||
binaryType = null;
|
||||
}
|
||||
var bufferTail = data;
|
||||
var buffers = [];
|
||||
var i;
|
||||
while (bufferTail.length > 0) {
|
||||
var strLen = '';
|
||||
var isString = bufferTail[0] === 0;
|
||||
for (i = 1;; i++) {
|
||||
if (bufferTail[i] === 255)
|
||||
break;
|
||||
// 310 = char length of Number.MAX_VALUE
|
||||
if (strLen.length > 310) {
|
||||
return callback(err, 0, 1);
|
||||
}
|
||||
strLen += '' + bufferTail[i];
|
||||
}
|
||||
bufferTail = bufferTail.slice(strLen.length + 1);
|
||||
var msgLength = parseInt(strLen, 10);
|
||||
var msg = bufferTail.slice(1, msgLength + 1);
|
||||
if (isString)
|
||||
msg = bufferToString(msg);
|
||||
buffers.push(msg);
|
||||
bufferTail = bufferTail.slice(msgLength + 1);
|
||||
}
|
||||
var total = buffers.length;
|
||||
for (i = 0; i < total; i++) {
|
||||
var buffer = buffers[i];
|
||||
callback(decodePacket(buffer, binaryType, true), i, total);
|
||||
}
|
||||
}
|
||||
;
|
||||
14
node_modules/engine.io/build/parser-v3/utf8.d.ts
generated
vendored
Normal file
14
node_modules/engine.io/build/parser-v3/utf8.d.ts
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
/*! https://mths.be/utf8js v2.1.2 by @mathias */
|
||||
declare var stringFromCharCode: (...codes: number[]) => string;
|
||||
declare function ucs2decode(string: any): any[];
|
||||
declare function ucs2encode(array: any): string;
|
||||
declare function checkScalarValue(codePoint: any, strict: any): boolean;
|
||||
declare function createByte(codePoint: any, shift: any): string;
|
||||
declare function encodeCodePoint(codePoint: any, strict: any): string;
|
||||
declare function utf8encode(string: any, opts: any): string;
|
||||
declare function readContinuationByte(): number;
|
||||
declare function decodeSymbol(strict: any): any;
|
||||
declare var byteArray: any;
|
||||
declare var byteCount: any;
|
||||
declare var byteIndex: any;
|
||||
declare function utf8decode(byteString: any, opts: any): string;
|
||||
187
node_modules/engine.io/build/parser-v3/utf8.js
generated
vendored
Normal file
187
node_modules/engine.io/build/parser-v3/utf8.js
generated
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
/*! https://mths.be/utf8js v2.1.2 by @mathias */
|
||||
var stringFromCharCode = String.fromCharCode;
|
||||
// Taken from https://mths.be/punycode
|
||||
function ucs2decode(string) {
|
||||
var output = [];
|
||||
var counter = 0;
|
||||
var length = string.length;
|
||||
var value;
|
||||
var extra;
|
||||
while (counter < length) {
|
||||
value = string.charCodeAt(counter++);
|
||||
if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
|
||||
// high surrogate, and there is a next character
|
||||
extra = string.charCodeAt(counter++);
|
||||
if ((extra & 0xFC00) == 0xDC00) { // low surrogate
|
||||
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
|
||||
}
|
||||
else {
|
||||
// unmatched surrogate; only append this code unit, in case the next
|
||||
// code unit is the high surrogate of a surrogate pair
|
||||
output.push(value);
|
||||
counter--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
output.push(value);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
// Taken from https://mths.be/punycode
|
||||
function ucs2encode(array) {
|
||||
var length = array.length;
|
||||
var index = -1;
|
||||
var value;
|
||||
var output = '';
|
||||
while (++index < length) {
|
||||
value = array[index];
|
||||
if (value > 0xFFFF) {
|
||||
value -= 0x10000;
|
||||
output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
|
||||
value = 0xDC00 | value & 0x3FF;
|
||||
}
|
||||
output += stringFromCharCode(value);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
function checkScalarValue(codePoint, strict) {
|
||||
if (codePoint >= 0xD800 && codePoint <= 0xDFFF) {
|
||||
if (strict) {
|
||||
throw Error('Lone surrogate U+' + codePoint.toString(16).toUpperCase() +
|
||||
' is not a scalar value');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
function createByte(codePoint, shift) {
|
||||
return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80);
|
||||
}
|
||||
function encodeCodePoint(codePoint, strict) {
|
||||
if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence
|
||||
return stringFromCharCode(codePoint);
|
||||
}
|
||||
var symbol = '';
|
||||
if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence
|
||||
symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0);
|
||||
}
|
||||
else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence
|
||||
if (!checkScalarValue(codePoint, strict)) {
|
||||
codePoint = 0xFFFD;
|
||||
}
|
||||
symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0);
|
||||
symbol += createByte(codePoint, 6);
|
||||
}
|
||||
else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence
|
||||
symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0);
|
||||
symbol += createByte(codePoint, 12);
|
||||
symbol += createByte(codePoint, 6);
|
||||
}
|
||||
symbol += stringFromCharCode((codePoint & 0x3F) | 0x80);
|
||||
return symbol;
|
||||
}
|
||||
function utf8encode(string, opts) {
|
||||
opts = opts || {};
|
||||
var strict = false !== opts.strict;
|
||||
var codePoints = ucs2decode(string);
|
||||
var length = codePoints.length;
|
||||
var index = -1;
|
||||
var codePoint;
|
||||
var byteString = '';
|
||||
while (++index < length) {
|
||||
codePoint = codePoints[index];
|
||||
byteString += encodeCodePoint(codePoint, strict);
|
||||
}
|
||||
return byteString;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
function readContinuationByte() {
|
||||
if (byteIndex >= byteCount) {
|
||||
throw Error('Invalid byte index');
|
||||
}
|
||||
var continuationByte = byteArray[byteIndex] & 0xFF;
|
||||
byteIndex++;
|
||||
if ((continuationByte & 0xC0) == 0x80) {
|
||||
return continuationByte & 0x3F;
|
||||
}
|
||||
// If we end up here, it’s not a continuation byte
|
||||
throw Error('Invalid continuation byte');
|
||||
}
|
||||
function decodeSymbol(strict) {
|
||||
var byte1;
|
||||
var byte2;
|
||||
var byte3;
|
||||
var byte4;
|
||||
var codePoint;
|
||||
if (byteIndex > byteCount) {
|
||||
throw Error('Invalid byte index');
|
||||
}
|
||||
if (byteIndex == byteCount) {
|
||||
return false;
|
||||
}
|
||||
// Read first byte
|
||||
byte1 = byteArray[byteIndex] & 0xFF;
|
||||
byteIndex++;
|
||||
// 1-byte sequence (no continuation bytes)
|
||||
if ((byte1 & 0x80) == 0) {
|
||||
return byte1;
|
||||
}
|
||||
// 2-byte sequence
|
||||
if ((byte1 & 0xE0) == 0xC0) {
|
||||
byte2 = readContinuationByte();
|
||||
codePoint = ((byte1 & 0x1F) << 6) | byte2;
|
||||
if (codePoint >= 0x80) {
|
||||
return codePoint;
|
||||
}
|
||||
else {
|
||||
throw Error('Invalid continuation byte');
|
||||
}
|
||||
}
|
||||
// 3-byte sequence (may include unpaired surrogates)
|
||||
if ((byte1 & 0xF0) == 0xE0) {
|
||||
byte2 = readContinuationByte();
|
||||
byte3 = readContinuationByte();
|
||||
codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
|
||||
if (codePoint >= 0x0800) {
|
||||
return checkScalarValue(codePoint, strict) ? codePoint : 0xFFFD;
|
||||
}
|
||||
else {
|
||||
throw Error('Invalid continuation byte');
|
||||
}
|
||||
}
|
||||
// 4-byte sequence
|
||||
if ((byte1 & 0xF8) == 0xF0) {
|
||||
byte2 = readContinuationByte();
|
||||
byte3 = readContinuationByte();
|
||||
byte4 = readContinuationByte();
|
||||
codePoint = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0C) |
|
||||
(byte3 << 0x06) | byte4;
|
||||
if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) {
|
||||
return codePoint;
|
||||
}
|
||||
}
|
||||
throw Error('Invalid UTF-8 detected');
|
||||
}
|
||||
var byteArray;
|
||||
var byteCount;
|
||||
var byteIndex;
|
||||
function utf8decode(byteString, opts) {
|
||||
opts = opts || {};
|
||||
var strict = false !== opts.strict;
|
||||
byteArray = ucs2decode(byteString);
|
||||
byteCount = byteArray.length;
|
||||
byteIndex = 0;
|
||||
var codePoints = [];
|
||||
var tmp;
|
||||
while ((tmp = decodeSymbol(strict)) !== false) {
|
||||
codePoints.push(tmp);
|
||||
}
|
||||
return ucs2encode(codePoints);
|
||||
}
|
||||
module.exports = {
|
||||
version: '2.1.2',
|
||||
encode: utf8encode,
|
||||
decode: utf8decode
|
||||
};
|
||||
272
node_modules/engine.io/build/server.d.ts
generated
vendored
Normal file
272
node_modules/engine.io/build/server.d.ts
generated
vendored
Normal file
@@ -0,0 +1,272 @@
|
||||
import { EventEmitter } from "events";
|
||||
import { Socket } from "./socket";
|
||||
import { type PerMessageDeflateOptions } from "ws";
|
||||
import type { IncomingMessage, Server as HttpServer, ServerResponse } from "http";
|
||||
import type { CorsOptions, CorsOptionsDelegate } from "cors";
|
||||
import type { Duplex } from "stream";
|
||||
import type { EngineRequest, Transport } from "./transport";
|
||||
import type { CookieSerializeOptions } from "./contrib/types.cookie";
|
||||
type TransportName = "polling" | "websocket" | "webtransport";
|
||||
export type ErrorCallback = (errorCode?: (typeof Server.errors)[keyof typeof Server.errors], errorContext?: Record<string, unknown> & {
|
||||
name?: string;
|
||||
message?: string;
|
||||
}) => void;
|
||||
export interface AttachOptions {
|
||||
/**
|
||||
* name of the path to capture
|
||||
* @default "/engine.io"
|
||||
*/
|
||||
path?: string;
|
||||
/**
|
||||
* destroy unhandled upgrade requests
|
||||
* @default true
|
||||
*/
|
||||
destroyUpgrade?: boolean;
|
||||
/**
|
||||
* milliseconds after which unhandled requests are ended
|
||||
* @default 1000
|
||||
*/
|
||||
destroyUpgradeTimeout?: number;
|
||||
/**
|
||||
* Whether we should add a trailing slash to the request path.
|
||||
* @default true
|
||||
*/
|
||||
addTrailingSlash?: boolean;
|
||||
}
|
||||
export interface ServerOptions {
|
||||
/**
|
||||
* how many ms without a pong packet to consider the connection closed
|
||||
* @default 20000
|
||||
*/
|
||||
pingTimeout?: number;
|
||||
/**
|
||||
* how many ms before sending a new ping packet
|
||||
* @default 25000
|
||||
*/
|
||||
pingInterval?: number;
|
||||
/**
|
||||
* how many ms before an uncompleted transport upgrade is cancelled
|
||||
* @default 10000
|
||||
*/
|
||||
upgradeTimeout?: number;
|
||||
/**
|
||||
* how many bytes or characters a message can be, before closing the session (to avoid DoS).
|
||||
* @default 1e5 (100 KB)
|
||||
*/
|
||||
maxHttpBufferSize?: number;
|
||||
/**
|
||||
* A function that receives a given handshake or upgrade request as its first parameter,
|
||||
* and can decide whether to continue or not. The second argument is a function that needs
|
||||
* to be called with the decided information: fn(err, success), where success is a boolean
|
||||
* value where false means that the request is rejected, and err is an error code.
|
||||
*/
|
||||
allowRequest?: (req: IncomingMessage, fn: (err: string | null | undefined, success: boolean) => void) => void;
|
||||
/**
|
||||
* The low-level transports that are enabled. WebTransport is disabled by default and must be manually enabled:
|
||||
*
|
||||
* @example
|
||||
* new Server({
|
||||
* transports: ["polling", "websocket", "webtransport"]
|
||||
* });
|
||||
*
|
||||
* @default ["polling", "websocket"]
|
||||
*/
|
||||
transports?: TransportName[];
|
||||
/**
|
||||
* whether to allow transport upgrades
|
||||
* @default true
|
||||
*/
|
||||
allowUpgrades?: boolean;
|
||||
/**
|
||||
* parameters of the WebSocket permessage-deflate extension (see ws module api docs). Set to false to disable.
|
||||
* @default false
|
||||
*/
|
||||
perMessageDeflate?: boolean | PerMessageDeflateOptions;
|
||||
/**
|
||||
* parameters of the http compression for the polling transports (see zlib api docs). Set to false to disable.
|
||||
* @default true
|
||||
*/
|
||||
httpCompression?: boolean | object;
|
||||
/**
|
||||
* what WebSocket server implementation to use. Specified module must
|
||||
* conform to the ws interface (see ws module api docs).
|
||||
* An alternative c++ addon is also available by installing eiows module.
|
||||
*
|
||||
* @default `require("ws").Server`
|
||||
*/
|
||||
wsEngine?: any;
|
||||
/**
|
||||
* an optional packet which will be concatenated to the handshake packet emitted by Engine.IO.
|
||||
*/
|
||||
initialPacket?: any;
|
||||
/**
|
||||
* configuration of the cookie that contains the client sid to send as part of handshake response headers. This cookie
|
||||
* might be used for sticky-session. Defaults to not sending any cookie.
|
||||
* @default false
|
||||
*/
|
||||
cookie?: (CookieSerializeOptions & {
|
||||
name: string;
|
||||
}) | boolean;
|
||||
/**
|
||||
* the options that will be forwarded to the cors module
|
||||
*/
|
||||
cors?: CorsOptions | CorsOptionsDelegate;
|
||||
/**
|
||||
* whether to enable compatibility with Socket.IO v2 clients
|
||||
* @default false
|
||||
*/
|
||||
allowEIO3?: boolean;
|
||||
}
|
||||
/**
|
||||
* An Express-compatible middleware.
|
||||
*
|
||||
* Middleware functions are functions that have access to the request object (req), the response object (res), and the
|
||||
* next middleware function in the application’s request-response cycle.
|
||||
*
|
||||
* @see https://expressjs.com/en/guide/using-middleware.html
|
||||
*/
|
||||
type Middleware = (req: IncomingMessage, res: ServerResponse, next: (err?: any) => void) => void;
|
||||
export declare abstract class BaseServer extends EventEmitter {
|
||||
opts: ServerOptions;
|
||||
protected clients: Record<string, Socket>;
|
||||
clientsCount: number;
|
||||
protected middlewares: Middleware[];
|
||||
/**
|
||||
* Server constructor.
|
||||
*
|
||||
* @param {Object} opts - options
|
||||
*/
|
||||
constructor(opts?: ServerOptions);
|
||||
protected abstract init(): void;
|
||||
/**
|
||||
* Compute the pathname of the requests that are handled by the server
|
||||
* @param options
|
||||
* @protected
|
||||
*/
|
||||
protected _computePath(options: AttachOptions): string;
|
||||
/**
|
||||
* Returns a list of available transports for upgrade given a certain transport.
|
||||
*/
|
||||
upgrades(transport: TransportName): string[];
|
||||
/**
|
||||
* Verifies a request.
|
||||
*
|
||||
* @param {EngineRequest} req
|
||||
* @param upgrade - whether it's an upgrade request
|
||||
* @param fn
|
||||
* @protected
|
||||
* @return whether the request is valid
|
||||
*/
|
||||
protected verify(req: EngineRequest, upgrade: boolean, fn: ErrorCallback): void | boolean;
|
||||
/**
|
||||
* Adds a new middleware.
|
||||
*
|
||||
* @example
|
||||
* import helmet from "helmet";
|
||||
*
|
||||
* engine.use(helmet());
|
||||
*
|
||||
* @param fn
|
||||
*/
|
||||
use(fn: any): void;
|
||||
/**
|
||||
* Apply the middlewares to the request.
|
||||
*
|
||||
* @param req
|
||||
* @param res
|
||||
* @param callback
|
||||
* @protected
|
||||
*/
|
||||
protected _applyMiddlewares(req: IncomingMessage, res: ServerResponse, callback: (err?: any) => void): void;
|
||||
/**
|
||||
* Closes all clients.
|
||||
*/
|
||||
close(): this;
|
||||
protected abstract cleanup(): any;
|
||||
/**
|
||||
* generate a socket id.
|
||||
* Overwrite this method to generate your custom socket id
|
||||
*
|
||||
* @param {IncomingMessage} req - the request object
|
||||
*/
|
||||
generateId(req: IncomingMessage): string | PromiseLike<string>;
|
||||
/**
|
||||
* Handshakes a new client.
|
||||
*
|
||||
* @param {String} transportName
|
||||
* @param {Object} req - the request object
|
||||
* @param {Function} closeConnection
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
protected handshake(transportName: TransportName, req: EngineRequest, closeConnection: ErrorCallback): Promise<any>;
|
||||
onWebTransportSession(session: any): Promise<any>;
|
||||
protected abstract createTransport(transportName: TransportName, req: EngineRequest): any;
|
||||
/**
|
||||
* Protocol errors mappings.
|
||||
*/
|
||||
static errors: {
|
||||
readonly UNKNOWN_TRANSPORT: 0;
|
||||
readonly UNKNOWN_SID: 1;
|
||||
readonly BAD_HANDSHAKE_METHOD: 2;
|
||||
readonly BAD_REQUEST: 3;
|
||||
readonly FORBIDDEN: 4;
|
||||
readonly UNSUPPORTED_PROTOCOL_VERSION: 5;
|
||||
};
|
||||
static errorMessages: {
|
||||
readonly 0: "Transport unknown";
|
||||
readonly 1: "Session ID unknown";
|
||||
readonly 2: "Bad handshake method";
|
||||
readonly 3: "Bad request";
|
||||
readonly 4: "Forbidden";
|
||||
readonly 5: "Unsupported protocol version";
|
||||
};
|
||||
}
|
||||
/**
|
||||
* An Engine.IO server based on Node.js built-in HTTP server and the `ws` package for WebSocket connections.
|
||||
*/
|
||||
export declare class Server extends BaseServer {
|
||||
httpServer?: HttpServer;
|
||||
private ws;
|
||||
/**
|
||||
* Initialize websocket server
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
protected init(): void;
|
||||
protected cleanup(): void;
|
||||
/**
|
||||
* Prepares a request by processing the query string.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private prepare;
|
||||
protected createTransport(transportName: TransportName, req: IncomingMessage): Transport;
|
||||
/**
|
||||
* Handles an Engine.IO HTTP request.
|
||||
*
|
||||
* @param {EngineRequest} req
|
||||
* @param {ServerResponse} res
|
||||
*/
|
||||
handleRequest(req: EngineRequest, res: ServerResponse): void;
|
||||
/**
|
||||
* Handles an Engine.IO HTTP Upgrade.
|
||||
*/
|
||||
handleUpgrade(req: EngineRequest, socket: Duplex, upgradeHead: Buffer): void;
|
||||
/**
|
||||
* Called upon a ws.io connection.
|
||||
* @param req
|
||||
* @param socket
|
||||
* @param websocket
|
||||
* @private
|
||||
*/
|
||||
private onWebSocket;
|
||||
/**
|
||||
* Captures upgrade requests for a http.Server.
|
||||
*
|
||||
* @param {http.Server} server
|
||||
* @param {Object} options
|
||||
*/
|
||||
attach(server: HttpServer, options?: AttachOptions): void;
|
||||
}
|
||||
export {};
|
||||
787
node_modules/engine.io/build/server.js
generated
vendored
Normal file
787
node_modules/engine.io/build/server.js
generated
vendored
Normal file
@@ -0,0 +1,787 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Server = exports.BaseServer = void 0;
|
||||
const base64id = require("base64id");
|
||||
const transports_1 = require("./transports");
|
||||
const events_1 = require("events");
|
||||
const socket_1 = require("./socket");
|
||||
const debug_1 = require("debug");
|
||||
const cookie_1 = require("cookie");
|
||||
const ws_1 = require("ws");
|
||||
const webtransport_1 = require("./transports/webtransport");
|
||||
const engine_io_parser_1 = require("engine.io-parser");
|
||||
const debug = (0, debug_1.default)("engine");
|
||||
const kResponseHeaders = Symbol("responseHeaders");
|
||||
function parseSessionId(data) {
|
||||
try {
|
||||
const parsed = JSON.parse(data);
|
||||
if (typeof parsed.sid === "string") {
|
||||
return parsed.sid;
|
||||
}
|
||||
}
|
||||
catch (e) { }
|
||||
}
|
||||
class BaseServer extends events_1.EventEmitter {
|
||||
/**
|
||||
* Server constructor.
|
||||
*
|
||||
* @param {Object} opts - options
|
||||
*/
|
||||
constructor(opts = {}) {
|
||||
super();
|
||||
this.middlewares = [];
|
||||
this.clients = {};
|
||||
this.clientsCount = 0;
|
||||
this.opts = Object.assign({
|
||||
wsEngine: ws_1.Server,
|
||||
pingTimeout: 20000,
|
||||
pingInterval: 25000,
|
||||
upgradeTimeout: 10000,
|
||||
maxHttpBufferSize: 1e6,
|
||||
transports: ["polling", "websocket"], // WebTransport is disabled by default
|
||||
allowUpgrades: true,
|
||||
httpCompression: {
|
||||
threshold: 1024,
|
||||
},
|
||||
cors: false,
|
||||
allowEIO3: false,
|
||||
}, opts);
|
||||
if (opts.cookie) {
|
||||
this.opts.cookie = Object.assign({
|
||||
name: "io",
|
||||
path: "/",
|
||||
// @ts-ignore
|
||||
httpOnly: opts.cookie.path !== false,
|
||||
sameSite: "lax",
|
||||
}, opts.cookie);
|
||||
}
|
||||
if (this.opts.cors) {
|
||||
this.use(require("cors")(this.opts.cors));
|
||||
}
|
||||
if (opts.perMessageDeflate) {
|
||||
this.opts.perMessageDeflate = Object.assign({
|
||||
threshold: 1024,
|
||||
}, opts.perMessageDeflate);
|
||||
}
|
||||
this.init();
|
||||
}
|
||||
/**
|
||||
* Compute the pathname of the requests that are handled by the server
|
||||
* @param options
|
||||
* @protected
|
||||
*/
|
||||
_computePath(options) {
|
||||
let path = (options.path || "/engine.io").replace(/\/$/, "");
|
||||
if (options.addTrailingSlash !== false) {
|
||||
// normalize path
|
||||
path += "/";
|
||||
}
|
||||
return path;
|
||||
}
|
||||
/**
|
||||
* Returns a list of available transports for upgrade given a certain transport.
|
||||
*/
|
||||
upgrades(transport) {
|
||||
if (!this.opts.allowUpgrades)
|
||||
return [];
|
||||
return transports_1.default[transport].upgradesTo || [];
|
||||
}
|
||||
/**
|
||||
* Verifies a request.
|
||||
*
|
||||
* @param {EngineRequest} req
|
||||
* @param upgrade - whether it's an upgrade request
|
||||
* @param fn
|
||||
* @protected
|
||||
* @return whether the request is valid
|
||||
*/
|
||||
verify(req, upgrade, fn) {
|
||||
// transport check
|
||||
const transport = req._query.transport;
|
||||
// WebTransport does not go through the verify() method, see the onWebTransportSession() method
|
||||
if (!~this.opts.transports.indexOf(transport) ||
|
||||
transport === "webtransport") {
|
||||
debug('unknown transport "%s"', transport);
|
||||
return fn(Server.errors.UNKNOWN_TRANSPORT, { transport });
|
||||
}
|
||||
// 'Origin' header check
|
||||
const isOriginInvalid = checkInvalidHeaderChar(req.headers.origin);
|
||||
if (isOriginInvalid) {
|
||||
const origin = req.headers.origin;
|
||||
req.headers.origin = null;
|
||||
debug("origin header invalid");
|
||||
return fn(Server.errors.BAD_REQUEST, {
|
||||
name: "INVALID_ORIGIN",
|
||||
origin,
|
||||
});
|
||||
}
|
||||
// sid check
|
||||
const sid = req._query.sid;
|
||||
if (sid) {
|
||||
if (!this.clients.hasOwnProperty(sid)) {
|
||||
debug('unknown sid "%s"', sid);
|
||||
return fn(Server.errors.UNKNOWN_SID, {
|
||||
sid,
|
||||
});
|
||||
}
|
||||
const previousTransport = this.clients[sid].transport.name;
|
||||
if (!upgrade && previousTransport !== transport) {
|
||||
debug("bad request: unexpected transport without upgrade");
|
||||
return fn(Server.errors.BAD_REQUEST, {
|
||||
name: "TRANSPORT_MISMATCH",
|
||||
transport,
|
||||
previousTransport,
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
// handshake is GET only
|
||||
if ("GET" !== req.method) {
|
||||
return fn(Server.errors.BAD_HANDSHAKE_METHOD, {
|
||||
method: req.method,
|
||||
});
|
||||
}
|
||||
if (transport === "websocket" && !upgrade) {
|
||||
debug("invalid transport upgrade");
|
||||
return fn(Server.errors.BAD_REQUEST, {
|
||||
name: "TRANSPORT_HANDSHAKE_ERROR",
|
||||
});
|
||||
}
|
||||
if (!this.opts.allowRequest)
|
||||
return fn();
|
||||
return this.opts.allowRequest(req, (message, success) => {
|
||||
if (!success) {
|
||||
return fn(Server.errors.FORBIDDEN, {
|
||||
message,
|
||||
});
|
||||
}
|
||||
fn();
|
||||
});
|
||||
}
|
||||
fn();
|
||||
}
|
||||
/**
|
||||
* Adds a new middleware.
|
||||
*
|
||||
* @example
|
||||
* import helmet from "helmet";
|
||||
*
|
||||
* engine.use(helmet());
|
||||
*
|
||||
* @param fn
|
||||
*/
|
||||
use(fn) {
|
||||
this.middlewares.push(fn);
|
||||
}
|
||||
/**
|
||||
* Apply the middlewares to the request.
|
||||
*
|
||||
* @param req
|
||||
* @param res
|
||||
* @param callback
|
||||
* @protected
|
||||
*/
|
||||
_applyMiddlewares(req, res, callback) {
|
||||
if (this.middlewares.length === 0) {
|
||||
debug("no middleware to apply, skipping");
|
||||
return callback();
|
||||
}
|
||||
const apply = (i) => {
|
||||
debug("applying middleware n°%d", i + 1);
|
||||
this.middlewares[i](req, res, (err) => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
if (i + 1 < this.middlewares.length) {
|
||||
apply(i + 1);
|
||||
}
|
||||
else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
apply(0);
|
||||
}
|
||||
/**
|
||||
* Closes all clients.
|
||||
*/
|
||||
close() {
|
||||
debug("closing all open clients");
|
||||
for (let i in this.clients) {
|
||||
if (this.clients.hasOwnProperty(i)) {
|
||||
this.clients[i].close(true);
|
||||
}
|
||||
}
|
||||
this.cleanup();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* generate a socket id.
|
||||
* Overwrite this method to generate your custom socket id
|
||||
*
|
||||
* @param {IncomingMessage} req - the request object
|
||||
*/
|
||||
generateId(req) {
|
||||
return base64id.generateId();
|
||||
}
|
||||
/**
|
||||
* Handshakes a new client.
|
||||
*
|
||||
* @param {String} transportName
|
||||
* @param {Object} req - the request object
|
||||
* @param {Function} closeConnection
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
async handshake(transportName, req, closeConnection) {
|
||||
const protocol = req._query.EIO === "4" ? 4 : 3; // 3rd revision by default
|
||||
if (protocol === 3 && !this.opts.allowEIO3) {
|
||||
debug("unsupported protocol version");
|
||||
this.emit("connection_error", {
|
||||
req,
|
||||
code: Server.errors.UNSUPPORTED_PROTOCOL_VERSION,
|
||||
message: Server.errorMessages[Server.errors.UNSUPPORTED_PROTOCOL_VERSION],
|
||||
context: {
|
||||
protocol,
|
||||
},
|
||||
});
|
||||
closeConnection(Server.errors.UNSUPPORTED_PROTOCOL_VERSION);
|
||||
return;
|
||||
}
|
||||
let id;
|
||||
try {
|
||||
id = await this.generateId(req);
|
||||
}
|
||||
catch (e) {
|
||||
debug("error while generating an id");
|
||||
this.emit("connection_error", {
|
||||
req,
|
||||
code: Server.errors.BAD_REQUEST,
|
||||
message: Server.errorMessages[Server.errors.BAD_REQUEST],
|
||||
context: {
|
||||
name: "ID_GENERATION_ERROR",
|
||||
error: e,
|
||||
},
|
||||
});
|
||||
closeConnection(Server.errors.BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
debug('handshaking client "%s"', id);
|
||||
try {
|
||||
var transport = this.createTransport(transportName, req);
|
||||
if ("polling" === transportName) {
|
||||
transport.maxHttpBufferSize = this.opts.maxHttpBufferSize;
|
||||
transport.httpCompression = this.opts.httpCompression;
|
||||
}
|
||||
else if ("websocket" === transportName) {
|
||||
transport.perMessageDeflate = this.opts.perMessageDeflate;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
debug('error handshaking to transport "%s"', transportName);
|
||||
this.emit("connection_error", {
|
||||
req,
|
||||
code: Server.errors.BAD_REQUEST,
|
||||
message: Server.errorMessages[Server.errors.BAD_REQUEST],
|
||||
context: {
|
||||
name: "TRANSPORT_HANDSHAKE_ERROR",
|
||||
error: e,
|
||||
},
|
||||
});
|
||||
closeConnection(Server.errors.BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
const socket = new socket_1.Socket(id, this, transport, req, protocol);
|
||||
transport.on("headers", (headers, req) => {
|
||||
const isInitialRequest = !req._query.sid;
|
||||
if (isInitialRequest) {
|
||||
if (this.opts.cookie) {
|
||||
headers["Set-Cookie"] = [
|
||||
// @ts-ignore
|
||||
(0, cookie_1.serialize)(this.opts.cookie.name, id, this.opts.cookie),
|
||||
];
|
||||
}
|
||||
this.emit("initial_headers", headers, req);
|
||||
}
|
||||
this.emit("headers", headers, req);
|
||||
});
|
||||
transport.onRequest(req);
|
||||
this.clients[id] = socket;
|
||||
this.clientsCount++;
|
||||
socket.once("close", () => {
|
||||
delete this.clients[id];
|
||||
this.clientsCount--;
|
||||
});
|
||||
this.emit("connection", socket);
|
||||
return transport;
|
||||
}
|
||||
async onWebTransportSession(session) {
|
||||
const timeout = setTimeout(() => {
|
||||
debug("the client failed to establish a bidirectional stream in the given period");
|
||||
session.close();
|
||||
}, this.opts.upgradeTimeout);
|
||||
const streamReader = session.incomingBidirectionalStreams.getReader();
|
||||
const result = await streamReader.read();
|
||||
if (result.done) {
|
||||
debug("session is closed");
|
||||
return;
|
||||
}
|
||||
const stream = result.value;
|
||||
const transformStream = (0, engine_io_parser_1.createPacketDecoderStream)(this.opts.maxHttpBufferSize, "nodebuffer");
|
||||
const reader = stream.readable.pipeThrough(transformStream).getReader();
|
||||
// reading the first packet of the stream
|
||||
const { value, done } = await reader.read();
|
||||
if (done) {
|
||||
debug("stream is closed");
|
||||
return;
|
||||
}
|
||||
clearTimeout(timeout);
|
||||
if (value.type !== "open") {
|
||||
debug("invalid WebTransport handshake");
|
||||
return session.close();
|
||||
}
|
||||
if (value.data === undefined) {
|
||||
const transport = new webtransport_1.WebTransport(session, stream, reader);
|
||||
// note: we cannot use "this.generateId()", because there is no "req" argument
|
||||
const id = base64id.generateId();
|
||||
debug('handshaking client "%s" (WebTransport)', id);
|
||||
const socket = new socket_1.Socket(id, this, transport, null, 4);
|
||||
this.clients[id] = socket;
|
||||
this.clientsCount++;
|
||||
socket.once("close", () => {
|
||||
delete this.clients[id];
|
||||
this.clientsCount--;
|
||||
});
|
||||
this.emit("connection", socket);
|
||||
return;
|
||||
}
|
||||
const sid = parseSessionId(value.data);
|
||||
if (!sid) {
|
||||
debug("invalid WebTransport handshake");
|
||||
return session.close();
|
||||
}
|
||||
const client = this.clients[sid];
|
||||
if (!client) {
|
||||
debug("upgrade attempt for closed client");
|
||||
session.close();
|
||||
}
|
||||
else if (client.upgrading) {
|
||||
debug("transport has already been trying to upgrade");
|
||||
session.close();
|
||||
}
|
||||
else if (client.upgraded) {
|
||||
debug("transport had already been upgraded");
|
||||
session.close();
|
||||
}
|
||||
else {
|
||||
debug("upgrading existing transport");
|
||||
const transport = new webtransport_1.WebTransport(session, stream, reader);
|
||||
client._maybeUpgrade(transport);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.BaseServer = BaseServer;
|
||||
/**
|
||||
* Protocol errors mappings.
|
||||
*/
|
||||
BaseServer.errors = {
|
||||
UNKNOWN_TRANSPORT: 0,
|
||||
UNKNOWN_SID: 1,
|
||||
BAD_HANDSHAKE_METHOD: 2,
|
||||
BAD_REQUEST: 3,
|
||||
FORBIDDEN: 4,
|
||||
UNSUPPORTED_PROTOCOL_VERSION: 5,
|
||||
};
|
||||
BaseServer.errorMessages = {
|
||||
0: "Transport unknown",
|
||||
1: "Session ID unknown",
|
||||
2: "Bad handshake method",
|
||||
3: "Bad request",
|
||||
4: "Forbidden",
|
||||
5: "Unsupported protocol version",
|
||||
};
|
||||
/**
|
||||
* Exposes a subset of the http.ServerResponse interface, in order to be able to apply the middlewares to an upgrade
|
||||
* request.
|
||||
*
|
||||
* @see https://nodejs.org/api/http.html#class-httpserverresponse
|
||||
*/
|
||||
class WebSocketResponse {
|
||||
constructor(req, socket) {
|
||||
this.req = req;
|
||||
this.socket = socket;
|
||||
// temporarily store the response headers on the req object (see the "headers" event)
|
||||
req[kResponseHeaders] = {};
|
||||
}
|
||||
setHeader(name, value) {
|
||||
this.req[kResponseHeaders][name] = value;
|
||||
}
|
||||
getHeader(name) {
|
||||
return this.req[kResponseHeaders][name];
|
||||
}
|
||||
removeHeader(name) {
|
||||
delete this.req[kResponseHeaders][name];
|
||||
}
|
||||
write() { }
|
||||
writeHead() { }
|
||||
end() {
|
||||
// we could return a proper error code, but the WebSocket client will emit an "error" event anyway.
|
||||
this.socket.destroy();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* An Engine.IO server based on Node.js built-in HTTP server and the `ws` package for WebSocket connections.
|
||||
*/
|
||||
class Server extends BaseServer {
|
||||
/**
|
||||
* Initialize websocket server
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
init() {
|
||||
if (!~this.opts.transports.indexOf("websocket"))
|
||||
return;
|
||||
if (this.ws)
|
||||
this.ws.close();
|
||||
this.ws = new this.opts.wsEngine({
|
||||
noServer: true,
|
||||
clientTracking: false,
|
||||
perMessageDeflate: this.opts.perMessageDeflate,
|
||||
maxPayload: this.opts.maxHttpBufferSize,
|
||||
});
|
||||
if (typeof this.ws.on === "function") {
|
||||
this.ws.on("headers", (headersArray, req) => {
|
||||
// note: 'ws' uses an array of headers, while Engine.IO uses an object (response.writeHead() accepts both formats)
|
||||
// we could also try to parse the array and then sync the values, but that will be error-prone
|
||||
const additionalHeaders = req[kResponseHeaders] || {};
|
||||
delete req[kResponseHeaders];
|
||||
const isInitialRequest = !req._query.sid;
|
||||
if (isInitialRequest) {
|
||||
this.emit("initial_headers", additionalHeaders, req);
|
||||
}
|
||||
this.emit("headers", additionalHeaders, req);
|
||||
debug("writing headers: %j", additionalHeaders);
|
||||
Object.keys(additionalHeaders).forEach((key) => {
|
||||
headersArray.push(`${key}: ${additionalHeaders[key]}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
cleanup() {
|
||||
if (this.ws) {
|
||||
debug("closing webSocketServer");
|
||||
this.ws.close();
|
||||
// don't delete this.ws because it can be used again if the http server starts listening again
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Prepares a request by processing the query string.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
prepare(req) {
|
||||
// try to leverage pre-existing `req._query` (e.g: from connect)
|
||||
if (!req._query) {
|
||||
const url = new URL(req.url, "https://socket.io");
|
||||
req._query = Object.fromEntries(url.searchParams.entries());
|
||||
}
|
||||
}
|
||||
createTransport(transportName, req) {
|
||||
// @ts-expect-error 'polling' is a plain function used as constructor
|
||||
return new transports_1.default[transportName](req);
|
||||
}
|
||||
/**
|
||||
* Handles an Engine.IO HTTP request.
|
||||
*
|
||||
* @param {EngineRequest} req
|
||||
* @param {ServerResponse} res
|
||||
*/
|
||||
handleRequest(req, res) {
|
||||
debug('handling "%s" http request "%s"', req.method, req.url);
|
||||
this.prepare(req);
|
||||
req.res = res;
|
||||
const callback = (errorCode, errorContext) => {
|
||||
if (errorCode !== undefined) {
|
||||
this.emit("connection_error", {
|
||||
req,
|
||||
code: errorCode,
|
||||
message: Server.errorMessages[errorCode],
|
||||
context: errorContext,
|
||||
});
|
||||
abortRequest(res, errorCode, errorContext);
|
||||
return;
|
||||
}
|
||||
if (req._query.sid) {
|
||||
debug("setting new request for existing client");
|
||||
this.clients[req._query.sid].transport.onRequest(req);
|
||||
}
|
||||
else {
|
||||
const closeConnection = (errorCode, errorContext) => abortRequest(res, errorCode, errorContext);
|
||||
this.handshake(req._query.transport, req, closeConnection);
|
||||
}
|
||||
};
|
||||
this._applyMiddlewares(req, res, (err) => {
|
||||
if (err) {
|
||||
callback(Server.errors.BAD_REQUEST, { name: "MIDDLEWARE_FAILURE" });
|
||||
}
|
||||
else {
|
||||
this.verify(req, false, callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Handles an Engine.IO HTTP Upgrade.
|
||||
*/
|
||||
handleUpgrade(req, socket, upgradeHead) {
|
||||
this.prepare(req);
|
||||
const res = new WebSocketResponse(req, socket);
|
||||
const callback = (errorCode, errorContext) => {
|
||||
if (errorCode !== undefined) {
|
||||
this.emit("connection_error", {
|
||||
req,
|
||||
code: errorCode,
|
||||
message: Server.errorMessages[errorCode],
|
||||
context: errorContext,
|
||||
});
|
||||
abortUpgrade(socket, errorCode, errorContext);
|
||||
return;
|
||||
}
|
||||
const head = Buffer.from(upgradeHead);
|
||||
upgradeHead = null;
|
||||
// some middlewares (like express-session) wait for the writeHead() call to flush their headers
|
||||
// see https://github.com/expressjs/session/blob/1010fadc2f071ddf2add94235d72224cf65159c6/index.js#L220-L244
|
||||
res.writeHead();
|
||||
// delegate to ws
|
||||
this.ws.handleUpgrade(req, socket, head, (websocket) => {
|
||||
this.onWebSocket(req, socket, websocket);
|
||||
});
|
||||
};
|
||||
this._applyMiddlewares(req, res, (err) => {
|
||||
if (err) {
|
||||
callback(Server.errors.BAD_REQUEST, { name: "MIDDLEWARE_FAILURE" });
|
||||
}
|
||||
else {
|
||||
this.verify(req, true, callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Called upon a ws.io connection.
|
||||
* @param req
|
||||
* @param socket
|
||||
* @param websocket
|
||||
* @private
|
||||
*/
|
||||
onWebSocket(req, socket, websocket) {
|
||||
websocket.on("error", onUpgradeError);
|
||||
if (transports_1.default[req._query.transport] !== undefined &&
|
||||
!transports_1.default[req._query.transport].prototype.handlesUpgrades) {
|
||||
debug("transport doesnt handle upgraded requests");
|
||||
websocket.close();
|
||||
return;
|
||||
}
|
||||
// get client id
|
||||
const id = req._query.sid;
|
||||
// keep a reference to the ws.Socket
|
||||
req.websocket = websocket;
|
||||
if (id) {
|
||||
const client = this.clients[id];
|
||||
if (!client) {
|
||||
debug("upgrade attempt for closed client");
|
||||
websocket.close();
|
||||
}
|
||||
else if (client.upgrading) {
|
||||
debug("transport has already been trying to upgrade");
|
||||
websocket.close();
|
||||
}
|
||||
else if (client.upgraded) {
|
||||
debug("transport had already been upgraded");
|
||||
websocket.close();
|
||||
}
|
||||
else {
|
||||
debug("upgrading existing transport");
|
||||
// transport error handling takes over
|
||||
websocket.removeListener("error", onUpgradeError);
|
||||
const transport = this.createTransport(req._query.transport, req);
|
||||
// @ts-expect-error this option is only for WebSocket impl
|
||||
transport.perMessageDeflate = this.opts.perMessageDeflate;
|
||||
client._maybeUpgrade(transport);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const closeConnection = (errorCode, errorContext) => abortUpgrade(socket, errorCode, errorContext);
|
||||
this.handshake(req._query.transport, req, closeConnection);
|
||||
}
|
||||
function onUpgradeError() {
|
||||
debug("websocket error before upgrade");
|
||||
// websocket.close() not needed
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Captures upgrade requests for a http.Server.
|
||||
*
|
||||
* @param {http.Server} server
|
||||
* @param {Object} options
|
||||
*/
|
||||
attach(server, options = {}) {
|
||||
const path = this._computePath(options);
|
||||
const destroyUpgradeTimeout = options.destroyUpgradeTimeout || 1000;
|
||||
function check(req) {
|
||||
// TODO use `path === new URL(...).pathname` in the next major release (ref: https://nodejs.org/api/url.html)
|
||||
return path === req.url.slice(0, path.length);
|
||||
}
|
||||
// cache and clean up listeners
|
||||
const listeners = server.listeners("request").slice(0);
|
||||
server.removeAllListeners("request");
|
||||
server.on("close", this.close.bind(this));
|
||||
server.on("listening", this.init.bind(this));
|
||||
// add request handler
|
||||
server.on("request", (req, res) => {
|
||||
if (check(req)) {
|
||||
debug('intercepting request for path "%s"', path);
|
||||
this.handleRequest(req, res);
|
||||
}
|
||||
else {
|
||||
let i = 0;
|
||||
const l = listeners.length;
|
||||
for (; i < l; i++) {
|
||||
listeners[i].call(server, req, res);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (~this.opts.transports.indexOf("websocket")) {
|
||||
server.on("upgrade", (req, socket, head) => {
|
||||
if (check(req)) {
|
||||
this.handleUpgrade(req, socket, head);
|
||||
}
|
||||
else if (false !== options.destroyUpgrade) {
|
||||
// default node behavior is to disconnect when no handlers
|
||||
// but by adding a handler, we prevent that
|
||||
// and if no eio thing handles the upgrade
|
||||
// then the socket needs to die!
|
||||
setTimeout(function () {
|
||||
// @ts-ignore
|
||||
if (socket.writable && socket.bytesWritten <= 0) {
|
||||
socket.on("error", (e) => {
|
||||
debug("error while destroying upgrade: %s", e.message);
|
||||
});
|
||||
return socket.end();
|
||||
}
|
||||
}, destroyUpgradeTimeout);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.Server = Server;
|
||||
/**
|
||||
* Close the HTTP long-polling request
|
||||
*
|
||||
* @param res - the response object
|
||||
* @param errorCode - the error code
|
||||
* @param errorContext - additional error context
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function abortRequest(res, errorCode, errorContext) {
|
||||
const statusCode = errorCode === Server.errors.FORBIDDEN ? 403 : 400;
|
||||
const message = errorContext && errorContext.message
|
||||
? errorContext.message
|
||||
: Server.errorMessages[errorCode];
|
||||
res.writeHead(statusCode, { "Content-Type": "application/json" });
|
||||
res.end(JSON.stringify({
|
||||
code: errorCode,
|
||||
message,
|
||||
}));
|
||||
}
|
||||
/**
|
||||
* Close the WebSocket connection
|
||||
*
|
||||
* @param {net.Socket} socket
|
||||
* @param {string} errorCode - the error code
|
||||
* @param {object} errorContext - additional error context
|
||||
*/
|
||||
function abortUpgrade(socket, errorCode, errorContext = {}) {
|
||||
socket.on("error", () => {
|
||||
debug("ignoring error from closed connection");
|
||||
});
|
||||
if (socket.writable) {
|
||||
const message = errorContext.message || Server.errorMessages[errorCode];
|
||||
const length = Buffer.byteLength(message);
|
||||
socket.write("HTTP/1.1 400 Bad Request\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"Content-type: text/html\r\n" +
|
||||
"Content-Length: " +
|
||||
length +
|
||||
"\r\n" +
|
||||
"\r\n" +
|
||||
message);
|
||||
}
|
||||
socket.destroy();
|
||||
}
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* From https://github.com/nodejs/node/blob/v8.4.0/lib/_http_common.js#L303-L354
|
||||
*
|
||||
* True if val contains an invalid field-vchar
|
||||
* field-value = *( field-content / obs-fold )
|
||||
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
||||
* field-vchar = VCHAR / obs-text
|
||||
*
|
||||
* checkInvalidHeaderChar() is currently designed to be inlinable by v8,
|
||||
* so take care when making changes to the implementation so that the source
|
||||
* code size does not exceed v8's default max_inlined_source_size setting.
|
||||
**/
|
||||
// prettier-ignore
|
||||
const validHdrChars = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0 - 15
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32 - 47
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48 - 63
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 - 95
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112 - 127
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128 ...
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // ... 255
|
||||
];
|
||||
function checkInvalidHeaderChar(val) {
|
||||
val += "";
|
||||
if (val.length < 1)
|
||||
return false;
|
||||
if (!validHdrChars[val.charCodeAt(0)]) {
|
||||
debug('invalid header, index 0, char "%s"', val.charCodeAt(0));
|
||||
return true;
|
||||
}
|
||||
if (val.length < 2)
|
||||
return false;
|
||||
if (!validHdrChars[val.charCodeAt(1)]) {
|
||||
debug('invalid header, index 1, char "%s"', val.charCodeAt(1));
|
||||
return true;
|
||||
}
|
||||
if (val.length < 3)
|
||||
return false;
|
||||
if (!validHdrChars[val.charCodeAt(2)]) {
|
||||
debug('invalid header, index 2, char "%s"', val.charCodeAt(2));
|
||||
return true;
|
||||
}
|
||||
if (val.length < 4)
|
||||
return false;
|
||||
if (!validHdrChars[val.charCodeAt(3)]) {
|
||||
debug('invalid header, index 3, char "%s"', val.charCodeAt(3));
|
||||
return true;
|
||||
}
|
||||
for (let i = 4; i < val.length; ++i) {
|
||||
if (!validHdrChars[val.charCodeAt(i)]) {
|
||||
debug('invalid header, index "%i", char "%s"', i, val.charCodeAt(i));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
180
node_modules/engine.io/build/socket.d.ts
generated
vendored
Normal file
180
node_modules/engine.io/build/socket.d.ts
generated
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
import { EventEmitter } from "events";
|
||||
import type { IncomingMessage } from "http";
|
||||
import type { EngineRequest, Transport } from "./transport";
|
||||
import type { BaseServer } from "./server";
|
||||
import type { RawData } from "engine.io-parser";
|
||||
export interface SendOptions {
|
||||
compress?: boolean;
|
||||
}
|
||||
type ReadyState = "opening" | "open" | "closing" | "closed";
|
||||
type SendCallback = (transport: Transport) => void;
|
||||
export declare class Socket extends EventEmitter {
|
||||
/**
|
||||
* The revision of the protocol:
|
||||
*
|
||||
* - 3rd is used in Engine.IO v3 / Socket.IO v2
|
||||
* - 4th is used in Engine.IO v4 and above / Socket.IO v3 and above
|
||||
*
|
||||
* It is found in the `EIO` query parameters of the HTTP requests.
|
||||
*
|
||||
* @see https://github.com/socketio/engine.io-protocol
|
||||
*/
|
||||
readonly protocol: number;
|
||||
/**
|
||||
* A reference to the first HTTP request of the session
|
||||
*
|
||||
* TODO for the next major release: remove it
|
||||
*/
|
||||
request: IncomingMessage;
|
||||
/**
|
||||
* The IP address of the client.
|
||||
*/
|
||||
readonly remoteAddress: string;
|
||||
/**
|
||||
* The current state of the socket.
|
||||
*/
|
||||
_readyState: ReadyState;
|
||||
/**
|
||||
* The current low-level transport.
|
||||
*/
|
||||
transport: Transport;
|
||||
private server;
|
||||
upgrading: boolean;
|
||||
upgraded: boolean;
|
||||
private writeBuffer;
|
||||
private packetsFn;
|
||||
private sentCallbackFn;
|
||||
private cleanupFn;
|
||||
private pingTimeoutTimer;
|
||||
private pingIntervalTimer;
|
||||
/**
|
||||
* This is the session identifier that the client will use in the subsequent HTTP requests. It must not be shared with
|
||||
* others parties, as it might lead to session hijacking.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private readonly id;
|
||||
get readyState(): ReadyState;
|
||||
set readyState(state: ReadyState);
|
||||
constructor(id: string, server: BaseServer, transport: Transport, req: EngineRequest, protocol: number);
|
||||
/**
|
||||
* Called upon transport considered open.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private onOpen;
|
||||
/**
|
||||
* Called upon transport packet.
|
||||
*
|
||||
* @param {Object} packet
|
||||
* @private
|
||||
*/
|
||||
private onPacket;
|
||||
/**
|
||||
* Called upon transport error.
|
||||
*
|
||||
* @param {Error} err - error object
|
||||
* @private
|
||||
*/
|
||||
private onError;
|
||||
/**
|
||||
* Pings client every `this.pingInterval` and expects response
|
||||
* within `this.pingTimeout` or closes connection.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private schedulePing;
|
||||
/**
|
||||
* Resets ping timeout.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private resetPingTimeout;
|
||||
/**
|
||||
* Attaches handlers for the given transport.
|
||||
*
|
||||
* @param {Transport} transport
|
||||
* @private
|
||||
*/
|
||||
private setTransport;
|
||||
/**
|
||||
* Upon transport "drain" event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private onDrain;
|
||||
/**
|
||||
* Upgrades socket to the given transport
|
||||
*
|
||||
* @param {Transport} transport
|
||||
* @private
|
||||
*/
|
||||
_maybeUpgrade(transport: Transport): void;
|
||||
/**
|
||||
* Clears listeners and timers associated with current transport.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private clearTransport;
|
||||
/**
|
||||
* Called upon transport considered closed.
|
||||
* Possible reasons: `ping timeout`, `client error`, `parse error`,
|
||||
* `transport error`, `server close`, `transport close`
|
||||
*/
|
||||
private onClose;
|
||||
/**
|
||||
* Sends a message packet.
|
||||
*
|
||||
* @param {Object} data
|
||||
* @param {Object} options
|
||||
* @param {Function} callback
|
||||
* @return {Socket} for chaining
|
||||
*/
|
||||
send(data: RawData, options?: SendOptions, callback?: SendCallback): this;
|
||||
/**
|
||||
* Alias of {@link send}.
|
||||
*
|
||||
* @param data
|
||||
* @param options
|
||||
* @param callback
|
||||
*/
|
||||
write(data: RawData, options?: SendOptions, callback?: SendCallback): this;
|
||||
/**
|
||||
* Sends a packet.
|
||||
*
|
||||
* @param {String} type - packet type
|
||||
* @param {String} data
|
||||
* @param {Object} options
|
||||
* @param {Function} callback
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private sendPacket;
|
||||
/**
|
||||
* Attempts to flush the packets buffer.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private flush;
|
||||
/**
|
||||
* Get available upgrades for this socket.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private getAvailableUpgrades;
|
||||
/**
|
||||
* Closes the socket and underlying transport.
|
||||
*
|
||||
* @param {Boolean} discard - optional, discard the transport
|
||||
* @return {Socket} for chaining
|
||||
*/
|
||||
close(discard?: boolean): void;
|
||||
/**
|
||||
* Closes the underlying transport.
|
||||
*
|
||||
* @param {Boolean} discard
|
||||
* @private
|
||||
*/
|
||||
private closeTransport;
|
||||
}
|
||||
export {};
|
||||
460
node_modules/engine.io/build/socket.js
generated
vendored
Normal file
460
node_modules/engine.io/build/socket.js
generated
vendored
Normal file
@@ -0,0 +1,460 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Socket = void 0;
|
||||
const events_1 = require("events");
|
||||
const debug_1 = require("debug");
|
||||
const timers_1 = require("timers");
|
||||
const debug = (0, debug_1.default)("engine:socket");
|
||||
class Socket extends events_1.EventEmitter {
|
||||
get readyState() {
|
||||
return this._readyState;
|
||||
}
|
||||
set readyState(state) {
|
||||
debug("readyState updated from %s to %s", this._readyState, state);
|
||||
this._readyState = state;
|
||||
}
|
||||
constructor(id, server, transport, req, protocol) {
|
||||
super();
|
||||
/**
|
||||
* The current state of the socket.
|
||||
*/
|
||||
this._readyState = "opening";
|
||||
/* private */ this.upgrading = false;
|
||||
/* private */ this.upgraded = false;
|
||||
this.writeBuffer = [];
|
||||
this.packetsFn = [];
|
||||
this.sentCallbackFn = [];
|
||||
this.cleanupFn = [];
|
||||
this.id = id;
|
||||
this.server = server;
|
||||
this.request = req;
|
||||
this.protocol = protocol;
|
||||
// Cache IP since it might not be in the req later
|
||||
if (req) {
|
||||
if (req.websocket && req.websocket._socket) {
|
||||
this.remoteAddress = req.websocket._socket.remoteAddress;
|
||||
}
|
||||
else {
|
||||
this.remoteAddress = req.connection.remoteAddress;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// TODO there is currently no way to get the IP address of the client when it connects with WebTransport
|
||||
// see https://github.com/fails-components/webtransport/issues/114
|
||||
}
|
||||
this.pingTimeoutTimer = null;
|
||||
this.pingIntervalTimer = null;
|
||||
this.setTransport(transport);
|
||||
this.onOpen();
|
||||
}
|
||||
/**
|
||||
* Called upon transport considered open.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onOpen() {
|
||||
this.readyState = "open";
|
||||
// sends an `open` packet
|
||||
this.transport.sid = this.id;
|
||||
this.sendPacket("open", JSON.stringify({
|
||||
sid: this.id,
|
||||
upgrades: this.getAvailableUpgrades(),
|
||||
pingInterval: this.server.opts.pingInterval,
|
||||
pingTimeout: this.server.opts.pingTimeout,
|
||||
maxPayload: this.server.opts.maxHttpBufferSize,
|
||||
}));
|
||||
if (this.server.opts.initialPacket) {
|
||||
this.sendPacket("message", this.server.opts.initialPacket);
|
||||
}
|
||||
this.emit("open");
|
||||
if (this.protocol === 3) {
|
||||
// in protocol v3, the client sends a ping, and the server answers with a pong
|
||||
this.resetPingTimeout();
|
||||
}
|
||||
else {
|
||||
// in protocol v4, the server sends a ping, and the client answers with a pong
|
||||
this.schedulePing();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Called upon transport packet.
|
||||
*
|
||||
* @param {Object} packet
|
||||
* @private
|
||||
*/
|
||||
onPacket(packet) {
|
||||
if ("open" !== this.readyState) {
|
||||
return debug("packet received with closed socket");
|
||||
}
|
||||
// export packet event
|
||||
debug(`received packet ${packet.type}`);
|
||||
this.emit("packet", packet);
|
||||
switch (packet.type) {
|
||||
case "ping":
|
||||
if (this.transport.protocol !== 3) {
|
||||
this.onError(new Error("invalid heartbeat direction"));
|
||||
return;
|
||||
}
|
||||
debug("got ping");
|
||||
this.pingTimeoutTimer.refresh();
|
||||
this.sendPacket("pong");
|
||||
this.emit("heartbeat");
|
||||
break;
|
||||
case "pong":
|
||||
if (this.transport.protocol === 3) {
|
||||
this.onError(new Error("invalid heartbeat direction"));
|
||||
return;
|
||||
}
|
||||
debug("got pong");
|
||||
(0, timers_1.clearTimeout)(this.pingTimeoutTimer);
|
||||
this.pingIntervalTimer.refresh();
|
||||
this.emit("heartbeat");
|
||||
break;
|
||||
case "error":
|
||||
this.onClose("parse error");
|
||||
break;
|
||||
case "message":
|
||||
this.emit("data", packet.data);
|
||||
this.emit("message", packet.data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Called upon transport error.
|
||||
*
|
||||
* @param {Error} err - error object
|
||||
* @private
|
||||
*/
|
||||
onError(err) {
|
||||
debug("transport error");
|
||||
this.onClose("transport error", err);
|
||||
}
|
||||
/**
|
||||
* Pings client every `this.pingInterval` and expects response
|
||||
* within `this.pingTimeout` or closes connection.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
schedulePing() {
|
||||
this.pingIntervalTimer = (0, timers_1.setTimeout)(() => {
|
||||
debug("writing ping packet - expecting pong within %sms", this.server.opts.pingTimeout);
|
||||
this.sendPacket("ping");
|
||||
this.resetPingTimeout();
|
||||
}, this.server.opts.pingInterval);
|
||||
}
|
||||
/**
|
||||
* Resets ping timeout.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
resetPingTimeout() {
|
||||
(0, timers_1.clearTimeout)(this.pingTimeoutTimer);
|
||||
this.pingTimeoutTimer = (0, timers_1.setTimeout)(() => {
|
||||
if (this.readyState === "closed")
|
||||
return;
|
||||
this.onClose("ping timeout");
|
||||
}, this.protocol === 3
|
||||
? this.server.opts.pingInterval + this.server.opts.pingTimeout
|
||||
: this.server.opts.pingTimeout);
|
||||
}
|
||||
/**
|
||||
* Attaches handlers for the given transport.
|
||||
*
|
||||
* @param {Transport} transport
|
||||
* @private
|
||||
*/
|
||||
setTransport(transport) {
|
||||
const onError = this.onError.bind(this);
|
||||
const onReady = () => this.flush();
|
||||
const onPacket = this.onPacket.bind(this);
|
||||
const onDrain = this.onDrain.bind(this);
|
||||
const onClose = this.onClose.bind(this, "transport close");
|
||||
this.transport = transport;
|
||||
this.transport.once("error", onError);
|
||||
this.transport.on("ready", onReady);
|
||||
this.transport.on("packet", onPacket);
|
||||
this.transport.on("drain", onDrain);
|
||||
this.transport.once("close", onClose);
|
||||
this.cleanupFn.push(function () {
|
||||
transport.removeListener("error", onError);
|
||||
transport.removeListener("ready", onReady);
|
||||
transport.removeListener("packet", onPacket);
|
||||
transport.removeListener("drain", onDrain);
|
||||
transport.removeListener("close", onClose);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Upon transport "drain" event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onDrain() {
|
||||
if (this.sentCallbackFn.length > 0) {
|
||||
debug("executing batch send callback");
|
||||
const seqFn = this.sentCallbackFn.shift();
|
||||
if (seqFn) {
|
||||
for (let i = 0; i < seqFn.length; i++) {
|
||||
seqFn[i](this.transport);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Upgrades socket to the given transport
|
||||
*
|
||||
* @param {Transport} transport
|
||||
* @private
|
||||
*/
|
||||
/* private */ _maybeUpgrade(transport) {
|
||||
debug('might upgrade socket transport from "%s" to "%s"', this.transport.name, transport.name);
|
||||
this.upgrading = true;
|
||||
// set transport upgrade timer
|
||||
const upgradeTimeoutTimer = (0, timers_1.setTimeout)(() => {
|
||||
debug("client did not complete upgrade - closing transport");
|
||||
cleanup();
|
||||
if ("open" === transport.readyState) {
|
||||
transport.close();
|
||||
}
|
||||
}, this.server.opts.upgradeTimeout);
|
||||
let checkIntervalTimer;
|
||||
const onPacket = (packet) => {
|
||||
if ("ping" === packet.type && "probe" === packet.data) {
|
||||
debug("got probe ping packet, sending pong");
|
||||
transport.send([{ type: "pong", data: "probe" }]);
|
||||
this.emit("upgrading", transport);
|
||||
clearInterval(checkIntervalTimer);
|
||||
checkIntervalTimer = setInterval(check, 100);
|
||||
}
|
||||
else if ("upgrade" === packet.type && this.readyState !== "closed") {
|
||||
debug("got upgrade packet - upgrading");
|
||||
cleanup();
|
||||
this.transport.discard();
|
||||
this.upgraded = true;
|
||||
this.clearTransport();
|
||||
this.setTransport(transport);
|
||||
this.emit("upgrade", transport);
|
||||
this.flush();
|
||||
if (this.readyState === "closing") {
|
||||
transport.close(() => {
|
||||
this.onClose("forced close");
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
cleanup();
|
||||
transport.close();
|
||||
}
|
||||
};
|
||||
// we force a polling cycle to ensure a fast upgrade
|
||||
const check = () => {
|
||||
if ("polling" === this.transport.name && this.transport.writable) {
|
||||
debug("writing a noop packet to polling for fast upgrade");
|
||||
this.transport.send([{ type: "noop" }]);
|
||||
}
|
||||
};
|
||||
const cleanup = () => {
|
||||
this.upgrading = false;
|
||||
clearInterval(checkIntervalTimer);
|
||||
(0, timers_1.clearTimeout)(upgradeTimeoutTimer);
|
||||
transport.removeListener("packet", onPacket);
|
||||
transport.removeListener("close", onTransportClose);
|
||||
transport.removeListener("error", onError);
|
||||
this.removeListener("close", onClose);
|
||||
};
|
||||
const onError = (err) => {
|
||||
debug("client did not complete upgrade - %s", err);
|
||||
cleanup();
|
||||
transport.close();
|
||||
transport = null;
|
||||
};
|
||||
const onTransportClose = () => {
|
||||
onError("transport closed");
|
||||
};
|
||||
const onClose = () => {
|
||||
onError("socket closed");
|
||||
};
|
||||
transport.on("packet", onPacket);
|
||||
transport.once("close", onTransportClose);
|
||||
transport.once("error", onError);
|
||||
this.once("close", onClose);
|
||||
}
|
||||
/**
|
||||
* Clears listeners and timers associated with current transport.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
clearTransport() {
|
||||
let cleanup;
|
||||
const toCleanUp = this.cleanupFn.length;
|
||||
for (let i = 0; i < toCleanUp; i++) {
|
||||
cleanup = this.cleanupFn.shift();
|
||||
cleanup();
|
||||
}
|
||||
// silence further transport errors and prevent uncaught exceptions
|
||||
this.transport.on("error", function () {
|
||||
debug("error triggered by discarded transport");
|
||||
});
|
||||
// ensure transport won't stay open
|
||||
this.transport.close();
|
||||
(0, timers_1.clearTimeout)(this.pingTimeoutTimer);
|
||||
}
|
||||
/**
|
||||
* Called upon transport considered closed.
|
||||
* Possible reasons: `ping timeout`, `client error`, `parse error`,
|
||||
* `transport error`, `server close`, `transport close`
|
||||
*/
|
||||
onClose(reason, description) {
|
||||
if ("closed" !== this.readyState) {
|
||||
this.readyState = "closed";
|
||||
// clear timers
|
||||
(0, timers_1.clearTimeout)(this.pingIntervalTimer);
|
||||
(0, timers_1.clearTimeout)(this.pingTimeoutTimer);
|
||||
// clean writeBuffer in next tick, so developers can still
|
||||
// grab the writeBuffer on 'close' event
|
||||
process.nextTick(() => {
|
||||
this.writeBuffer = [];
|
||||
});
|
||||
this.packetsFn = [];
|
||||
this.sentCallbackFn = [];
|
||||
this.clearTransport();
|
||||
this.emit("close", reason, description);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Sends a message packet.
|
||||
*
|
||||
* @param {Object} data
|
||||
* @param {Object} options
|
||||
* @param {Function} callback
|
||||
* @return {Socket} for chaining
|
||||
*/
|
||||
send(data, options, callback) {
|
||||
this.sendPacket("message", data, options, callback);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Alias of {@link send}.
|
||||
*
|
||||
* @param data
|
||||
* @param options
|
||||
* @param callback
|
||||
*/
|
||||
write(data, options, callback) {
|
||||
this.sendPacket("message", data, options, callback);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Sends a packet.
|
||||
*
|
||||
* @param {String} type - packet type
|
||||
* @param {String} data
|
||||
* @param {Object} options
|
||||
* @param {Function} callback
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
sendPacket(type, data, options = {}, callback) {
|
||||
if ("function" === typeof options) {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
if ("closing" !== this.readyState && "closed" !== this.readyState) {
|
||||
debug('sending packet "%s" (%s)', type, data);
|
||||
// compression is enabled by default
|
||||
options.compress = options.compress !== false;
|
||||
const packet = {
|
||||
type,
|
||||
options: options,
|
||||
};
|
||||
if (data)
|
||||
packet.data = data;
|
||||
// exports packetCreate event
|
||||
this.emit("packetCreate", packet);
|
||||
this.writeBuffer.push(packet);
|
||||
// add send callback to object, if defined
|
||||
if ("function" === typeof callback)
|
||||
this.packetsFn.push(callback);
|
||||
this.flush();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Attempts to flush the packets buffer.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
flush() {
|
||||
if ("closed" !== this.readyState &&
|
||||
this.transport.writable &&
|
||||
this.writeBuffer.length) {
|
||||
debug("flushing buffer to transport");
|
||||
this.emit("flush", this.writeBuffer);
|
||||
this.server.emit("flush", this, this.writeBuffer);
|
||||
const wbuf = this.writeBuffer;
|
||||
this.writeBuffer = [];
|
||||
if (this.packetsFn.length) {
|
||||
this.sentCallbackFn.push(this.packetsFn);
|
||||
this.packetsFn = [];
|
||||
}
|
||||
else {
|
||||
this.sentCallbackFn.push(null);
|
||||
}
|
||||
this.transport.send(wbuf);
|
||||
this.emit("drain");
|
||||
this.server.emit("drain", this);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get available upgrades for this socket.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
getAvailableUpgrades() {
|
||||
const availableUpgrades = [];
|
||||
const allUpgrades = this.server.upgrades(this.transport.name);
|
||||
for (let i = 0; i < allUpgrades.length; ++i) {
|
||||
const upg = allUpgrades[i];
|
||||
if (this.server.opts.transports.indexOf(upg) !== -1) {
|
||||
availableUpgrades.push(upg);
|
||||
}
|
||||
}
|
||||
return availableUpgrades;
|
||||
}
|
||||
/**
|
||||
* Closes the socket and underlying transport.
|
||||
*
|
||||
* @param {Boolean} discard - optional, discard the transport
|
||||
* @return {Socket} for chaining
|
||||
*/
|
||||
close(discard) {
|
||||
if (discard &&
|
||||
(this.readyState === "open" || this.readyState === "closing")) {
|
||||
return this.closeTransport(discard);
|
||||
}
|
||||
if ("open" !== this.readyState)
|
||||
return;
|
||||
this.readyState = "closing";
|
||||
if (this.writeBuffer.length) {
|
||||
debug("there are %d remaining packets in the buffer, waiting for the 'drain' event", this.writeBuffer.length);
|
||||
this.once("drain", () => {
|
||||
debug("all packets have been sent, closing the transport");
|
||||
this.closeTransport(discard);
|
||||
});
|
||||
return;
|
||||
}
|
||||
debug("the buffer is empty, closing the transport right away");
|
||||
this.closeTransport(discard);
|
||||
}
|
||||
/**
|
||||
* Closes the underlying transport.
|
||||
*
|
||||
* @param {Boolean} discard
|
||||
* @private
|
||||
*/
|
||||
closeTransport(discard) {
|
||||
debug("closing the transport (discard? %s)", !!discard);
|
||||
if (discard)
|
||||
this.transport.discard();
|
||||
this.transport.close(this.onClose.bind(this, "forced close"));
|
||||
}
|
||||
}
|
||||
exports.Socket = Socket;
|
||||
135
node_modules/engine.io/build/transport.d.ts
generated
vendored
Normal file
135
node_modules/engine.io/build/transport.d.ts
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
import { EventEmitter } from "events";
|
||||
import * as parser_v4 from "engine.io-parser";
|
||||
import * as parser_v3 from "./parser-v3/index";
|
||||
import type { IncomingMessage, ServerResponse } from "http";
|
||||
import { Packet, RawData } from "engine.io-parser";
|
||||
import type { WebSocket } from "ws";
|
||||
type ReadyState = "open" | "closing" | "closed";
|
||||
export type EngineRequest = IncomingMessage & {
|
||||
_query: Record<string, string>;
|
||||
res?: ServerResponse;
|
||||
cleanup?: Function;
|
||||
websocket?: WebSocket & {
|
||||
_socket?: {
|
||||
remoteAddress: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
export declare abstract class Transport extends EventEmitter {
|
||||
/**
|
||||
* The session ID.
|
||||
*/
|
||||
sid: string;
|
||||
/**
|
||||
* Whether the transport is currently ready to send packets.
|
||||
*/
|
||||
writable: boolean;
|
||||
/**
|
||||
* The revision of the protocol:
|
||||
*
|
||||
* - 3 is used in Engine.IO v3 / Socket.IO v2
|
||||
* - 4 is used in Engine.IO v4 and above / Socket.IO v3 and above
|
||||
*
|
||||
* It is found in the `EIO` query parameters of the HTTP requests.
|
||||
*
|
||||
* @see https://github.com/socketio/engine.io-protocol
|
||||
*/
|
||||
protocol: 3 | 4;
|
||||
/**
|
||||
* The current state of the transport.
|
||||
* @protected
|
||||
*/
|
||||
protected _readyState: ReadyState;
|
||||
/**
|
||||
* Whether the transport is discarded and can be safely closed (used during upgrade).
|
||||
* @protected
|
||||
*/
|
||||
protected discarded: boolean;
|
||||
/**
|
||||
* The parser to use (depends on the revision of the {@link Transport#protocol}.
|
||||
* @protected
|
||||
*/
|
||||
protected parser: typeof parser_v4 | typeof parser_v3;
|
||||
/**
|
||||
* Whether the transport supports binary payloads (else it will be base64-encoded)
|
||||
* @protected
|
||||
*/
|
||||
protected supportsBinary: boolean;
|
||||
get readyState(): ReadyState;
|
||||
set readyState(state: ReadyState);
|
||||
/**
|
||||
* The list of transports this transport can be upgraded to.
|
||||
*/
|
||||
static upgradesTo: string[];
|
||||
/**
|
||||
* Transport constructor.
|
||||
*
|
||||
* @param {EngineRequest} req
|
||||
*/
|
||||
constructor(req: {
|
||||
_query: Record<string, string>;
|
||||
});
|
||||
/**
|
||||
* Flags the transport as discarded.
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
discard(): void;
|
||||
/**
|
||||
* Called with an incoming HTTP request.
|
||||
*
|
||||
* @param req
|
||||
* @package
|
||||
*/
|
||||
onRequest(req: any): void;
|
||||
/**
|
||||
* Closes the transport.
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
close(fn?: () => void): void;
|
||||
/**
|
||||
* Called with a transport error.
|
||||
*
|
||||
* @param {String} msg - message error
|
||||
* @param {Object} desc - error description
|
||||
* @protected
|
||||
*/
|
||||
protected onError(msg: string, desc?: any): void;
|
||||
/**
|
||||
* Called with parsed out a packets from the data stream.
|
||||
*
|
||||
* @param {Object} packet
|
||||
* @protected
|
||||
*/
|
||||
protected onPacket(packet: Packet): void;
|
||||
/**
|
||||
* Called with the encoded packet data.
|
||||
*
|
||||
* @param data
|
||||
* @protected
|
||||
*/
|
||||
protected onData(data: RawData): void;
|
||||
/**
|
||||
* Called upon transport close.
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
protected onClose(): void;
|
||||
/**
|
||||
* The name of the transport.
|
||||
*/
|
||||
abstract get name(): string;
|
||||
/**
|
||||
* Sends an array of packets.
|
||||
*
|
||||
* @param {Array} packets
|
||||
* @package
|
||||
*/
|
||||
abstract send(packets: Packet[]): void;
|
||||
/**
|
||||
* Closes the transport.
|
||||
*/
|
||||
abstract doClose(fn?: () => void): void;
|
||||
}
|
||||
export {};
|
||||
121
node_modules/engine.io/build/transport.js
generated
vendored
Normal file
121
node_modules/engine.io/build/transport.js
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Transport = void 0;
|
||||
const events_1 = require("events");
|
||||
const parser_v4 = require("engine.io-parser");
|
||||
const parser_v3 = require("./parser-v3/index");
|
||||
const debug_1 = require("debug");
|
||||
const debug = (0, debug_1.default)("engine:transport");
|
||||
function noop() { }
|
||||
class Transport extends events_1.EventEmitter {
|
||||
get readyState() {
|
||||
return this._readyState;
|
||||
}
|
||||
set readyState(state) {
|
||||
debug("readyState updated from %s to %s (%s)", this._readyState, state, this.name);
|
||||
this._readyState = state;
|
||||
}
|
||||
/**
|
||||
* Transport constructor.
|
||||
*
|
||||
* @param {EngineRequest} req
|
||||
*/
|
||||
constructor(req) {
|
||||
super();
|
||||
/**
|
||||
* Whether the transport is currently ready to send packets.
|
||||
*/
|
||||
this.writable = false;
|
||||
/**
|
||||
* The current state of the transport.
|
||||
* @protected
|
||||
*/
|
||||
this._readyState = "open";
|
||||
/**
|
||||
* Whether the transport is discarded and can be safely closed (used during upgrade).
|
||||
* @protected
|
||||
*/
|
||||
this.discarded = false;
|
||||
this.protocol = req._query.EIO === "4" ? 4 : 3; // 3rd revision by default
|
||||
this.parser = this.protocol === 4 ? parser_v4 : parser_v3;
|
||||
this.supportsBinary = !(req._query && req._query.b64);
|
||||
}
|
||||
/**
|
||||
* Flags the transport as discarded.
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
discard() {
|
||||
this.discarded = true;
|
||||
}
|
||||
/**
|
||||
* Called with an incoming HTTP request.
|
||||
*
|
||||
* @param req
|
||||
* @package
|
||||
*/
|
||||
onRequest(req) { }
|
||||
/**
|
||||
* Closes the transport.
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
close(fn) {
|
||||
if ("closed" === this.readyState || "closing" === this.readyState)
|
||||
return;
|
||||
this.readyState = "closing";
|
||||
this.doClose(fn || noop);
|
||||
}
|
||||
/**
|
||||
* Called with a transport error.
|
||||
*
|
||||
* @param {String} msg - message error
|
||||
* @param {Object} desc - error description
|
||||
* @protected
|
||||
*/
|
||||
onError(msg, desc) {
|
||||
if (this.listeners("error").length) {
|
||||
const err = new Error(msg);
|
||||
// @ts-ignore
|
||||
err.type = "TransportError";
|
||||
// @ts-ignore
|
||||
err.description = desc;
|
||||
this.emit("error", err);
|
||||
}
|
||||
else {
|
||||
debug("ignored transport error %s (%s)", msg, desc);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Called with parsed out a packets from the data stream.
|
||||
*
|
||||
* @param {Object} packet
|
||||
* @protected
|
||||
*/
|
||||
onPacket(packet) {
|
||||
this.emit("packet", packet);
|
||||
}
|
||||
/**
|
||||
* Called with the encoded packet data.
|
||||
*
|
||||
* @param data
|
||||
* @protected
|
||||
*/
|
||||
onData(data) {
|
||||
this.onPacket(this.parser.decodePacket(data));
|
||||
}
|
||||
/**
|
||||
* Called upon transport close.
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
onClose() {
|
||||
this.readyState = "closed";
|
||||
this.emit("close");
|
||||
}
|
||||
}
|
||||
exports.Transport = Transport;
|
||||
/**
|
||||
* The list of transports this transport can be upgraded to.
|
||||
*/
|
||||
Transport.upgradesTo = [];
|
||||
7
node_modules/engine.io/build/transports-uws/index.d.ts
generated
vendored
Normal file
7
node_modules/engine.io/build/transports-uws/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Polling } from "./polling";
|
||||
import { WebSocket } from "./websocket";
|
||||
declare const _default: {
|
||||
polling: typeof Polling;
|
||||
websocket: typeof WebSocket;
|
||||
};
|
||||
export default _default;
|
||||
8
node_modules/engine.io/build/transports-uws/index.js
generated
vendored
Normal file
8
node_modules/engine.io/build/transports-uws/index.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const polling_1 = require("./polling");
|
||||
const websocket_1 = require("./websocket");
|
||||
exports.default = {
|
||||
polling: polling_1.Polling,
|
||||
websocket: websocket_1.WebSocket,
|
||||
};
|
||||
99
node_modules/engine.io/build/transports-uws/polling.d.ts
generated
vendored
Normal file
99
node_modules/engine.io/build/transports-uws/polling.d.ts
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
import { Transport } from "../transport";
|
||||
export declare class Polling extends Transport {
|
||||
maxHttpBufferSize: number;
|
||||
httpCompression: any;
|
||||
private req;
|
||||
private res;
|
||||
private dataReq;
|
||||
private dataRes;
|
||||
private shouldClose;
|
||||
private readonly closeTimeout;
|
||||
/**
|
||||
* HTTP polling constructor.
|
||||
*/
|
||||
constructor(req: any);
|
||||
/**
|
||||
* Transport name
|
||||
*/
|
||||
get name(): string;
|
||||
/**
|
||||
* Overrides onRequest.
|
||||
*
|
||||
* @param req
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onRequest(req: any): void;
|
||||
/**
|
||||
* The client sends a request awaiting for us to send data.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onPollRequest(req: any, res: any): void;
|
||||
/**
|
||||
* The client sends a request with data.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onDataRequest(req: any, res: any): void;
|
||||
/**
|
||||
* Cleanup request.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private onDataRequestCleanup;
|
||||
/**
|
||||
* Processes the incoming data payload.
|
||||
*
|
||||
* @param {String} encoded payload
|
||||
* @private
|
||||
*/
|
||||
onData(data: any): void;
|
||||
/**
|
||||
* Overrides onClose.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onClose(): void;
|
||||
/**
|
||||
* Writes a packet payload.
|
||||
*
|
||||
* @param {Object} packet
|
||||
* @private
|
||||
*/
|
||||
send(packets: any): void;
|
||||
/**
|
||||
* Writes data as response to poll request.
|
||||
*
|
||||
* @param {String} data
|
||||
* @param {Object} options
|
||||
* @private
|
||||
*/
|
||||
write(data: any, options: any): void;
|
||||
/**
|
||||
* Performs the write.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
doWrite(data: any, options: any, callback: any): void;
|
||||
/**
|
||||
* Compresses data.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
compress(data: any, encoding: any, callback: any): void;
|
||||
/**
|
||||
* Closes the transport.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
doClose(fn: any): void;
|
||||
/**
|
||||
* Returns headers for a response.
|
||||
*
|
||||
* @param req - request
|
||||
* @param {Object} extra headers
|
||||
* @private
|
||||
*/
|
||||
headers(req: any, headers: any): any;
|
||||
}
|
||||
364
node_modules/engine.io/build/transports-uws/polling.js
generated
vendored
Normal file
364
node_modules/engine.io/build/transports-uws/polling.js
generated
vendored
Normal file
@@ -0,0 +1,364 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Polling = void 0;
|
||||
const transport_1 = require("../transport");
|
||||
const zlib_1 = require("zlib");
|
||||
const accepts = require("accepts");
|
||||
const debug_1 = require("debug");
|
||||
const debug = (0, debug_1.default)("engine:polling");
|
||||
const compressionMethods = {
|
||||
gzip: zlib_1.createGzip,
|
||||
deflate: zlib_1.createDeflate,
|
||||
};
|
||||
class Polling extends transport_1.Transport {
|
||||
/**
|
||||
* HTTP polling constructor.
|
||||
*/
|
||||
constructor(req) {
|
||||
super(req);
|
||||
this.closeTimeout = 30 * 1000;
|
||||
}
|
||||
/**
|
||||
* Transport name
|
||||
*/
|
||||
get name() {
|
||||
return "polling";
|
||||
}
|
||||
/**
|
||||
* Overrides onRequest.
|
||||
*
|
||||
* @param req
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onRequest(req) {
|
||||
const res = req.res;
|
||||
// remove the reference to the ServerResponse object (as the first request of the session is kept in memory by default)
|
||||
req.res = null;
|
||||
if (req.getMethod() === "get") {
|
||||
this.onPollRequest(req, res);
|
||||
}
|
||||
else if (req.getMethod() === "post") {
|
||||
this.onDataRequest(req, res);
|
||||
}
|
||||
else {
|
||||
res.writeStatus("500 Internal Server Error");
|
||||
res.end();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* The client sends a request awaiting for us to send data.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onPollRequest(req, res) {
|
||||
if (this.req) {
|
||||
debug("request overlap");
|
||||
// assert: this.res, '.req and .res should be (un)set together'
|
||||
this.onError("overlap from client");
|
||||
res.writeStatus("500 Internal Server Error");
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
debug("setting request");
|
||||
this.req = req;
|
||||
this.res = res;
|
||||
const onClose = () => {
|
||||
this.writable = false;
|
||||
this.onError("poll connection closed prematurely");
|
||||
};
|
||||
const cleanup = () => {
|
||||
this.req = this.res = null;
|
||||
};
|
||||
req.cleanup = cleanup;
|
||||
res.onAborted(onClose);
|
||||
this.writable = true;
|
||||
this.emit("ready");
|
||||
// if we're still writable but had a pending close, trigger an empty send
|
||||
if (this.writable && this.shouldClose) {
|
||||
debug("triggering empty send to append close packet");
|
||||
this.send([{ type: "noop" }]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* The client sends a request with data.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onDataRequest(req, res) {
|
||||
if (this.dataReq) {
|
||||
// assert: this.dataRes, '.dataReq and .dataRes should be (un)set together'
|
||||
this.onError("data request overlap from client");
|
||||
res.writeStatus("500 Internal Server Error");
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
const expectedContentLength = Number(req.headers["content-length"]);
|
||||
if (!expectedContentLength) {
|
||||
this.onError("content-length header required");
|
||||
res.writeStatus("411 Length Required").end();
|
||||
return;
|
||||
}
|
||||
if (expectedContentLength > this.maxHttpBufferSize) {
|
||||
this.onError("payload too large");
|
||||
res.writeStatus("413 Payload Too Large").end();
|
||||
return;
|
||||
}
|
||||
const isBinary = "application/octet-stream" === req.headers["content-type"];
|
||||
if (isBinary && this.protocol === 4) {
|
||||
return this.onError("invalid content");
|
||||
}
|
||||
this.dataReq = req;
|
||||
this.dataRes = res;
|
||||
let buffer;
|
||||
let offset = 0;
|
||||
const headers = {
|
||||
// text/html is required instead of text/plain to avoid an
|
||||
// unwanted download dialog on certain user-agents (GH-43)
|
||||
"Content-Type": "text/html",
|
||||
};
|
||||
this.headers(req, headers);
|
||||
for (let key in headers) {
|
||||
res.writeHeader(key, String(headers[key]));
|
||||
}
|
||||
const onEnd = (buffer) => {
|
||||
this.onData(buffer.toString());
|
||||
this.onDataRequestCleanup();
|
||||
res.cork(() => {
|
||||
res.end("ok");
|
||||
});
|
||||
};
|
||||
res.onAborted(() => {
|
||||
this.onDataRequestCleanup();
|
||||
this.onError("data request connection closed prematurely");
|
||||
});
|
||||
res.onData((arrayBuffer, isLast) => {
|
||||
const totalLength = offset + arrayBuffer.byteLength;
|
||||
if (totalLength > expectedContentLength) {
|
||||
this.onError("content-length mismatch");
|
||||
res.close(); // calls onAborted
|
||||
return;
|
||||
}
|
||||
if (!buffer) {
|
||||
if (isLast) {
|
||||
onEnd(Buffer.from(arrayBuffer));
|
||||
return;
|
||||
}
|
||||
buffer = Buffer.allocUnsafe(expectedContentLength);
|
||||
}
|
||||
Buffer.from(arrayBuffer).copy(buffer, offset);
|
||||
if (isLast) {
|
||||
if (totalLength != expectedContentLength) {
|
||||
this.onError("content-length mismatch");
|
||||
res.writeStatus("400 Content-Length Mismatch").end();
|
||||
this.onDataRequestCleanup();
|
||||
return;
|
||||
}
|
||||
onEnd(buffer);
|
||||
return;
|
||||
}
|
||||
offset = totalLength;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Cleanup request.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onDataRequestCleanup() {
|
||||
this.dataReq = this.dataRes = null;
|
||||
}
|
||||
/**
|
||||
* Processes the incoming data payload.
|
||||
*
|
||||
* @param {String} encoded payload
|
||||
* @private
|
||||
*/
|
||||
onData(data) {
|
||||
debug('received "%s"', data);
|
||||
const callback = (packet) => {
|
||||
if ("close" === packet.type) {
|
||||
debug("got xhr close packet");
|
||||
this.onClose();
|
||||
return false;
|
||||
}
|
||||
this.onPacket(packet);
|
||||
};
|
||||
if (this.protocol === 3) {
|
||||
this.parser.decodePayload(data, callback);
|
||||
}
|
||||
else {
|
||||
this.parser.decodePayload(data).forEach(callback);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Overrides onClose.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onClose() {
|
||||
if (this.writable) {
|
||||
// close pending poll request
|
||||
this.send([{ type: "noop" }]);
|
||||
}
|
||||
super.onClose();
|
||||
}
|
||||
/**
|
||||
* Writes a packet payload.
|
||||
*
|
||||
* @param {Object} packet
|
||||
* @private
|
||||
*/
|
||||
send(packets) {
|
||||
this.writable = false;
|
||||
if (this.shouldClose) {
|
||||
debug("appending close packet to payload");
|
||||
packets.push({ type: "close" });
|
||||
this.shouldClose();
|
||||
this.shouldClose = null;
|
||||
}
|
||||
const doWrite = (data) => {
|
||||
const compress = packets.some((packet) => {
|
||||
return packet.options && packet.options.compress;
|
||||
});
|
||||
this.write(data, { compress });
|
||||
};
|
||||
if (this.protocol === 3) {
|
||||
this.parser.encodePayload(packets, this.supportsBinary, doWrite);
|
||||
}
|
||||
else {
|
||||
this.parser.encodePayload(packets, doWrite);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Writes data as response to poll request.
|
||||
*
|
||||
* @param {String} data
|
||||
* @param {Object} options
|
||||
* @private
|
||||
*/
|
||||
write(data, options) {
|
||||
debug('writing "%s"', data);
|
||||
this.doWrite(data, options, () => {
|
||||
this.req.cleanup();
|
||||
this.emit("drain");
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Performs the write.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
doWrite(data, options, callback) {
|
||||
// explicit UTF-8 is required for pages not served under utf
|
||||
const isString = typeof data === "string";
|
||||
const contentType = isString
|
||||
? "text/plain; charset=UTF-8"
|
||||
: "application/octet-stream";
|
||||
const headers = {
|
||||
"Content-Type": contentType,
|
||||
};
|
||||
const respond = (data) => {
|
||||
this.headers(this.req, headers);
|
||||
this.res.cork(() => {
|
||||
Object.keys(headers).forEach((key) => {
|
||||
this.res.writeHeader(key, String(headers[key]));
|
||||
});
|
||||
this.res.end(data);
|
||||
});
|
||||
callback();
|
||||
};
|
||||
if (!this.httpCompression || !options.compress) {
|
||||
respond(data);
|
||||
return;
|
||||
}
|
||||
const len = isString ? Buffer.byteLength(data) : data.length;
|
||||
if (len < this.httpCompression.threshold) {
|
||||
respond(data);
|
||||
return;
|
||||
}
|
||||
const encoding = accepts(this.req).encodings(["gzip", "deflate"]);
|
||||
if (!encoding) {
|
||||
respond(data);
|
||||
return;
|
||||
}
|
||||
this.compress(data, encoding, (err, data) => {
|
||||
if (err) {
|
||||
this.res.writeStatus("500 Internal Server Error");
|
||||
this.res.end();
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
headers["Content-Encoding"] = encoding;
|
||||
respond(data);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Compresses data.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
compress(data, encoding, callback) {
|
||||
debug("compressing");
|
||||
const buffers = [];
|
||||
let nread = 0;
|
||||
compressionMethods[encoding](this.httpCompression)
|
||||
.on("error", callback)
|
||||
.on("data", function (chunk) {
|
||||
buffers.push(chunk);
|
||||
nread += chunk.length;
|
||||
})
|
||||
.on("end", function () {
|
||||
callback(null, Buffer.concat(buffers, nread));
|
||||
})
|
||||
.end(data);
|
||||
}
|
||||
/**
|
||||
* Closes the transport.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
doClose(fn) {
|
||||
debug("closing");
|
||||
let closeTimeoutTimer;
|
||||
const onClose = () => {
|
||||
clearTimeout(closeTimeoutTimer);
|
||||
fn();
|
||||
this.onClose();
|
||||
};
|
||||
if (this.writable) {
|
||||
debug("transport writable - closing right away");
|
||||
this.send([{ type: "close" }]);
|
||||
onClose();
|
||||
}
|
||||
else if (this.discarded) {
|
||||
debug("transport discarded - closing right away");
|
||||
onClose();
|
||||
}
|
||||
else {
|
||||
debug("transport not writable - buffering orderly close");
|
||||
this.shouldClose = onClose;
|
||||
closeTimeoutTimer = setTimeout(onClose, this.closeTimeout);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns headers for a response.
|
||||
*
|
||||
* @param req - request
|
||||
* @param {Object} extra headers
|
||||
* @private
|
||||
*/
|
||||
headers(req, headers) {
|
||||
headers = headers || {};
|
||||
// prevent XSS warnings on IE
|
||||
// https://github.com/LearnBoost/socket.io/pull/1333
|
||||
const ua = req.headers["user-agent"];
|
||||
if (ua && (~ua.indexOf(";MSIE") || ~ua.indexOf("Trident/"))) {
|
||||
headers["X-XSS-Protection"] = "0";
|
||||
}
|
||||
headers["cache-control"] = "no-store";
|
||||
this.emit("headers", headers, req);
|
||||
return headers;
|
||||
}
|
||||
}
|
||||
exports.Polling = Polling;
|
||||
32
node_modules/engine.io/build/transports-uws/websocket.d.ts
generated
vendored
Normal file
32
node_modules/engine.io/build/transports-uws/websocket.d.ts
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
import { Transport } from "../transport";
|
||||
export declare class WebSocket extends Transport {
|
||||
protected perMessageDeflate: any;
|
||||
private socket;
|
||||
/**
|
||||
* WebSocket transport
|
||||
*
|
||||
* @param req
|
||||
*/
|
||||
constructor(req: any);
|
||||
/**
|
||||
* Transport name
|
||||
*/
|
||||
get name(): string;
|
||||
/**
|
||||
* Advertise upgrade support.
|
||||
*/
|
||||
get handlesUpgrades(): boolean;
|
||||
/**
|
||||
* Writes a packet payload.
|
||||
*
|
||||
* @param {Array} packets
|
||||
* @private
|
||||
*/
|
||||
send(packets: any): void;
|
||||
/**
|
||||
* Closes the transport.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
doClose(fn: any): void;
|
||||
}
|
||||
73
node_modules/engine.io/build/transports-uws/websocket.js
generated
vendored
Normal file
73
node_modules/engine.io/build/transports-uws/websocket.js
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.WebSocket = void 0;
|
||||
const transport_1 = require("../transport");
|
||||
const debug_1 = require("debug");
|
||||
const debug = (0, debug_1.default)("engine:ws");
|
||||
class WebSocket extends transport_1.Transport {
|
||||
/**
|
||||
* WebSocket transport
|
||||
*
|
||||
* @param req
|
||||
*/
|
||||
constructor(req) {
|
||||
super(req);
|
||||
this.writable = false;
|
||||
this.perMessageDeflate = null;
|
||||
}
|
||||
/**
|
||||
* Transport name
|
||||
*/
|
||||
get name() {
|
||||
return "websocket";
|
||||
}
|
||||
/**
|
||||
* Advertise upgrade support.
|
||||
*/
|
||||
get handlesUpgrades() {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Writes a packet payload.
|
||||
*
|
||||
* @param {Array} packets
|
||||
* @private
|
||||
*/
|
||||
send(packets) {
|
||||
this.writable = false;
|
||||
for (let i = 0; i < packets.length; i++) {
|
||||
const packet = packets[i];
|
||||
const isLast = i + 1 === packets.length;
|
||||
const send = (data) => {
|
||||
const isBinary = typeof data !== "string";
|
||||
const compress = this.perMessageDeflate &&
|
||||
Buffer.byteLength(data) > this.perMessageDeflate.threshold;
|
||||
debug('writing "%s"', data);
|
||||
this.socket.send(data, isBinary, compress);
|
||||
if (isLast) {
|
||||
this.emit("drain");
|
||||
this.writable = true;
|
||||
this.emit("ready");
|
||||
}
|
||||
};
|
||||
if (packet.options && typeof packet.options.wsPreEncoded === "string") {
|
||||
send(packet.options.wsPreEncoded);
|
||||
}
|
||||
else {
|
||||
this.parser.encodePacket(packet, this.supportsBinary, send);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Closes the transport.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
doClose(fn) {
|
||||
debug("closing");
|
||||
fn && fn();
|
||||
// call fn first since socket.end() immediately emits a "close" event
|
||||
this.socket.end();
|
||||
}
|
||||
}
|
||||
exports.WebSocket = WebSocket;
|
||||
17
node_modules/engine.io/build/transports/index.d.ts
generated
vendored
Normal file
17
node_modules/engine.io/build/transports/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import { Polling as XHR } from "./polling";
|
||||
import { WebSocket } from "./websocket";
|
||||
import { WebTransport } from "./webtransport";
|
||||
import type { EngineRequest } from "../transport";
|
||||
declare const _default: {
|
||||
polling: typeof polling;
|
||||
websocket: typeof WebSocket;
|
||||
webtransport: typeof WebTransport;
|
||||
};
|
||||
export default _default;
|
||||
/**
|
||||
* Polling polymorphic constructor.
|
||||
*/
|
||||
declare function polling(req: EngineRequest): XHR;
|
||||
declare namespace polling {
|
||||
var upgradesTo: string[];
|
||||
}
|
||||
23
node_modules/engine.io/build/transports/index.js
generated
vendored
Normal file
23
node_modules/engine.io/build/transports/index.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const polling_1 = require("./polling");
|
||||
const polling_jsonp_1 = require("./polling-jsonp");
|
||||
const websocket_1 = require("./websocket");
|
||||
const webtransport_1 = require("./webtransport");
|
||||
exports.default = {
|
||||
polling,
|
||||
websocket: websocket_1.WebSocket,
|
||||
webtransport: webtransport_1.WebTransport,
|
||||
};
|
||||
/**
|
||||
* Polling polymorphic constructor.
|
||||
*/
|
||||
function polling(req) {
|
||||
if ("string" === typeof req._query.j) {
|
||||
return new polling_jsonp_1.JSONP(req);
|
||||
}
|
||||
else {
|
||||
return new polling_1.Polling(req);
|
||||
}
|
||||
}
|
||||
polling.upgradesTo = ["websocket", "webtransport"];
|
||||
12
node_modules/engine.io/build/transports/polling-jsonp.d.ts
generated
vendored
Normal file
12
node_modules/engine.io/build/transports/polling-jsonp.d.ts
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Polling } from "./polling";
|
||||
import type { RawData } from "engine.io-parser";
|
||||
export declare class JSONP extends Polling {
|
||||
private readonly head;
|
||||
private readonly foot;
|
||||
/**
|
||||
* JSON-P polling transport.
|
||||
*/
|
||||
constructor(req: any);
|
||||
onData(data: RawData): void;
|
||||
doWrite(data: any, options: any, callback: any): void;
|
||||
}
|
||||
41
node_modules/engine.io/build/transports/polling-jsonp.js
generated
vendored
Normal file
41
node_modules/engine.io/build/transports/polling-jsonp.js
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.JSONP = void 0;
|
||||
const polling_1 = require("./polling");
|
||||
const qs = require("querystring");
|
||||
const rDoubleSlashes = /\\\\n/g;
|
||||
const rSlashes = /(\\)?\\n/g;
|
||||
class JSONP extends polling_1.Polling {
|
||||
/**
|
||||
* JSON-P polling transport.
|
||||
*/
|
||||
constructor(req) {
|
||||
super(req);
|
||||
this.head = "___eio[" + (req._query.j || "").replace(/[^0-9]/g, "") + "](";
|
||||
this.foot = ");";
|
||||
}
|
||||
onData(data) {
|
||||
// we leverage the qs module so that we get built-in DoS protection
|
||||
// and the fast alternative to decodeURIComponent
|
||||
data = qs.parse(data).d;
|
||||
if ("string" === typeof data) {
|
||||
// client will send already escaped newlines as \\\\n and newlines as \\n
|
||||
// \\n must be replaced with \n and \\\\n with \\n
|
||||
data = data.replace(rSlashes, function (match, slashes) {
|
||||
return slashes ? match : "\n";
|
||||
});
|
||||
super.onData(data.replace(rDoubleSlashes, "\\n"));
|
||||
}
|
||||
}
|
||||
doWrite(data, options, callback) {
|
||||
// we must output valid javascript, not valid json
|
||||
// see: http://timelessrepo.com/json-isnt-a-javascript-subset
|
||||
const js = JSON.stringify(data)
|
||||
.replace(/\u2028/g, "\\u2028")
|
||||
.replace(/\u2029/g, "\\u2029");
|
||||
// prepare response
|
||||
data = this.head + js + this.foot;
|
||||
super.doWrite(data, options, callback);
|
||||
}
|
||||
}
|
||||
exports.JSONP = JSONP;
|
||||
87
node_modules/engine.io/build/transports/polling.d.ts
generated
vendored
Normal file
87
node_modules/engine.io/build/transports/polling.d.ts
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
import { EngineRequest, Transport } from "../transport";
|
||||
import type { Packet, RawData } from "engine.io-parser";
|
||||
export declare class Polling extends Transport {
|
||||
maxHttpBufferSize: number;
|
||||
httpCompression: any;
|
||||
private req;
|
||||
private res;
|
||||
private dataReq;
|
||||
private dataRes;
|
||||
private shouldClose;
|
||||
private readonly closeTimeout;
|
||||
/**
|
||||
* HTTP polling constructor.
|
||||
*/
|
||||
constructor(req: any);
|
||||
/**
|
||||
* Transport name
|
||||
*/
|
||||
get name(): string;
|
||||
/**
|
||||
* Overrides onRequest.
|
||||
*
|
||||
* @param {EngineRequest} req
|
||||
* @package
|
||||
*/
|
||||
onRequest(req: EngineRequest): void;
|
||||
/**
|
||||
* The client sends a request awaiting for us to send data.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private onPollRequest;
|
||||
/**
|
||||
* The client sends a request with data.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private onDataRequest;
|
||||
/**
|
||||
* Processes the incoming data payload.
|
||||
*
|
||||
* @param data - encoded payload
|
||||
* @protected
|
||||
*/
|
||||
onData(data: RawData): void;
|
||||
/**
|
||||
* Overrides onClose.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onClose(): void;
|
||||
send(packets: Packet[]): void;
|
||||
/**
|
||||
* Writes data as response to poll request.
|
||||
*
|
||||
* @param {String} data
|
||||
* @param {Object} options
|
||||
* @private
|
||||
*/
|
||||
private write;
|
||||
/**
|
||||
* Performs the write.
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
protected doWrite(data: any, options: any, callback: any): void;
|
||||
/**
|
||||
* Compresses data.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private compress;
|
||||
/**
|
||||
* Closes the transport.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
doClose(fn: () => void): void;
|
||||
/**
|
||||
* Returns headers for a response.
|
||||
*
|
||||
* @param {http.IncomingMessage} req
|
||||
* @param {Object} headers - extra headers
|
||||
* @private
|
||||
*/
|
||||
private headers;
|
||||
}
|
||||
332
node_modules/engine.io/build/transports/polling.js
generated
vendored
Normal file
332
node_modules/engine.io/build/transports/polling.js
generated
vendored
Normal file
@@ -0,0 +1,332 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Polling = void 0;
|
||||
const transport_1 = require("../transport");
|
||||
const zlib_1 = require("zlib");
|
||||
const accepts = require("accepts");
|
||||
const debug_1 = require("debug");
|
||||
const debug = (0, debug_1.default)("engine:polling");
|
||||
const compressionMethods = {
|
||||
gzip: zlib_1.createGzip,
|
||||
deflate: zlib_1.createDeflate,
|
||||
};
|
||||
class Polling extends transport_1.Transport {
|
||||
/**
|
||||
* HTTP polling constructor.
|
||||
*/
|
||||
constructor(req) {
|
||||
super(req);
|
||||
this.closeTimeout = 30 * 1000;
|
||||
}
|
||||
/**
|
||||
* Transport name
|
||||
*/
|
||||
get name() {
|
||||
return "polling";
|
||||
}
|
||||
/**
|
||||
* Overrides onRequest.
|
||||
*
|
||||
* @param {EngineRequest} req
|
||||
* @package
|
||||
*/
|
||||
onRequest(req) {
|
||||
const res = req.res;
|
||||
// remove the reference to the ServerResponse object (as the first request of the session is kept in memory by default)
|
||||
req.res = null;
|
||||
if ("GET" === req.method) {
|
||||
this.onPollRequest(req, res);
|
||||
}
|
||||
else if ("POST" === req.method) {
|
||||
this.onDataRequest(req, res);
|
||||
}
|
||||
else {
|
||||
res.writeHead(500);
|
||||
res.end();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* The client sends a request awaiting for us to send data.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onPollRequest(req, res) {
|
||||
if (this.req) {
|
||||
debug("request overlap");
|
||||
// assert: this.res, '.req and .res should be (un)set together'
|
||||
this.onError("overlap from client");
|
||||
res.writeHead(400);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
debug("setting request");
|
||||
this.req = req;
|
||||
this.res = res;
|
||||
const onClose = () => {
|
||||
this.onError("poll connection closed prematurely");
|
||||
};
|
||||
const cleanup = () => {
|
||||
req.removeListener("close", onClose);
|
||||
this.req = this.res = null;
|
||||
};
|
||||
req.cleanup = cleanup;
|
||||
req.on("close", onClose);
|
||||
this.writable = true;
|
||||
this.emit("ready");
|
||||
// if we're still writable but had a pending close, trigger an empty send
|
||||
if (this.writable && this.shouldClose) {
|
||||
debug("triggering empty send to append close packet");
|
||||
this.send([{ type: "noop" }]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* The client sends a request with data.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onDataRequest(req, res) {
|
||||
if (this.dataReq) {
|
||||
// assert: this.dataRes, '.dataReq and .dataRes should be (un)set together'
|
||||
this.onError("data request overlap from client");
|
||||
res.writeHead(400);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
const isBinary = "application/octet-stream" === req.headers["content-type"];
|
||||
if (isBinary && this.protocol === 4) {
|
||||
return this.onError("invalid content");
|
||||
}
|
||||
this.dataReq = req;
|
||||
this.dataRes = res;
|
||||
let chunks = isBinary ? Buffer.concat([]) : "";
|
||||
const cleanup = () => {
|
||||
req.removeListener("data", onData);
|
||||
req.removeListener("end", onEnd);
|
||||
req.removeListener("close", onClose);
|
||||
this.dataReq = this.dataRes = chunks = null;
|
||||
};
|
||||
const onClose = () => {
|
||||
cleanup();
|
||||
this.onError("data request connection closed prematurely");
|
||||
};
|
||||
const onData = (data) => {
|
||||
let contentLength;
|
||||
if (isBinary) {
|
||||
chunks = Buffer.concat([chunks, data]);
|
||||
contentLength = chunks.length;
|
||||
}
|
||||
else {
|
||||
chunks += data;
|
||||
contentLength = Buffer.byteLength(chunks);
|
||||
}
|
||||
if (contentLength > this.maxHttpBufferSize) {
|
||||
res.writeHead(413).end();
|
||||
cleanup();
|
||||
}
|
||||
};
|
||||
const onEnd = () => {
|
||||
this.onData(chunks);
|
||||
const headers = {
|
||||
// text/html is required instead of text/plain to avoid an
|
||||
// unwanted download dialog on certain user-agents (GH-43)
|
||||
"Content-Type": "text/html",
|
||||
"Content-Length": "2",
|
||||
};
|
||||
res.writeHead(200, this.headers(req, headers));
|
||||
res.end("ok");
|
||||
cleanup();
|
||||
};
|
||||
req.on("close", onClose);
|
||||
if (!isBinary)
|
||||
req.setEncoding("utf8");
|
||||
req.on("data", onData);
|
||||
req.on("end", onEnd);
|
||||
}
|
||||
/**
|
||||
* Processes the incoming data payload.
|
||||
*
|
||||
* @param data - encoded payload
|
||||
* @protected
|
||||
*/
|
||||
onData(data) {
|
||||
debug('received "%s"', data);
|
||||
const callback = (packet) => {
|
||||
if ("close" === packet.type) {
|
||||
debug("got xhr close packet");
|
||||
this.onClose();
|
||||
return false;
|
||||
}
|
||||
this.onPacket(packet);
|
||||
};
|
||||
if (this.protocol === 3) {
|
||||
this.parser.decodePayload(data, callback);
|
||||
}
|
||||
else {
|
||||
this.parser.decodePayload(data).forEach(callback);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Overrides onClose.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onClose() {
|
||||
if (this.writable) {
|
||||
// close pending poll request
|
||||
this.send([{ type: "noop" }]);
|
||||
}
|
||||
super.onClose();
|
||||
}
|
||||
send(packets) {
|
||||
this.writable = false;
|
||||
if (this.shouldClose) {
|
||||
debug("appending close packet to payload");
|
||||
packets.push({ type: "close" });
|
||||
this.shouldClose();
|
||||
this.shouldClose = null;
|
||||
}
|
||||
const doWrite = (data) => {
|
||||
const compress = packets.some((packet) => {
|
||||
return packet.options && packet.options.compress;
|
||||
});
|
||||
this.write(data, { compress });
|
||||
};
|
||||
if (this.protocol === 3) {
|
||||
this.parser.encodePayload(packets, this.supportsBinary, doWrite);
|
||||
}
|
||||
else {
|
||||
this.parser.encodePayload(packets, doWrite);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Writes data as response to poll request.
|
||||
*
|
||||
* @param {String} data
|
||||
* @param {Object} options
|
||||
* @private
|
||||
*/
|
||||
write(data, options) {
|
||||
debug('writing "%s"', data);
|
||||
this.doWrite(data, options, () => {
|
||||
this.req.cleanup();
|
||||
this.emit("drain");
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Performs the write.
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
doWrite(data, options, callback) {
|
||||
// explicit UTF-8 is required for pages not served under utf
|
||||
const isString = typeof data === "string";
|
||||
const contentType = isString
|
||||
? "text/plain; charset=UTF-8"
|
||||
: "application/octet-stream";
|
||||
const headers = {
|
||||
"Content-Type": contentType,
|
||||
};
|
||||
const respond = (data) => {
|
||||
headers["Content-Length"] =
|
||||
"string" === typeof data ? Buffer.byteLength(data) : data.length;
|
||||
this.res.writeHead(200, this.headers(this.req, headers));
|
||||
this.res.end(data);
|
||||
callback();
|
||||
};
|
||||
if (!this.httpCompression || !options.compress) {
|
||||
respond(data);
|
||||
return;
|
||||
}
|
||||
const len = isString ? Buffer.byteLength(data) : data.length;
|
||||
if (len < this.httpCompression.threshold) {
|
||||
respond(data);
|
||||
return;
|
||||
}
|
||||
const encoding = accepts(this.req).encodings(["gzip", "deflate"]);
|
||||
if (!encoding) {
|
||||
respond(data);
|
||||
return;
|
||||
}
|
||||
this.compress(data, encoding, (err, data) => {
|
||||
if (err) {
|
||||
this.res.writeHead(500);
|
||||
this.res.end();
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
headers["Content-Encoding"] = encoding;
|
||||
respond(data);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Compresses data.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
compress(data, encoding, callback) {
|
||||
debug("compressing");
|
||||
const buffers = [];
|
||||
let nread = 0;
|
||||
compressionMethods[encoding](this.httpCompression)
|
||||
.on("error", callback)
|
||||
.on("data", function (chunk) {
|
||||
buffers.push(chunk);
|
||||
nread += chunk.length;
|
||||
})
|
||||
.on("end", function () {
|
||||
callback(null, Buffer.concat(buffers, nread));
|
||||
})
|
||||
.end(data);
|
||||
}
|
||||
/**
|
||||
* Closes the transport.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
doClose(fn) {
|
||||
debug("closing");
|
||||
let closeTimeoutTimer;
|
||||
if (this.dataReq) {
|
||||
debug("aborting ongoing data request");
|
||||
this.dataReq.destroy();
|
||||
}
|
||||
const onClose = () => {
|
||||
clearTimeout(closeTimeoutTimer);
|
||||
fn();
|
||||
this.onClose();
|
||||
};
|
||||
if (this.writable) {
|
||||
debug("transport writable - closing right away");
|
||||
this.send([{ type: "close" }]);
|
||||
onClose();
|
||||
}
|
||||
else if (this.discarded) {
|
||||
debug("transport discarded - closing right away");
|
||||
onClose();
|
||||
}
|
||||
else {
|
||||
debug("transport not writable - buffering orderly close");
|
||||
this.shouldClose = onClose;
|
||||
closeTimeoutTimer = setTimeout(onClose, this.closeTimeout);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns headers for a response.
|
||||
*
|
||||
* @param {http.IncomingMessage} req
|
||||
* @param {Object} headers - extra headers
|
||||
* @private
|
||||
*/
|
||||
headers(req, headers = {}) {
|
||||
// prevent XSS warnings on IE
|
||||
// https://github.com/LearnBoost/socket.io/pull/1333
|
||||
const ua = req.headers["user-agent"];
|
||||
if (ua && (~ua.indexOf(";MSIE") || ~ua.indexOf("Trident/"))) {
|
||||
headers["X-XSS-Protection"] = "0";
|
||||
}
|
||||
headers["cache-control"] = "no-store";
|
||||
this.emit("headers", headers, req);
|
||||
return headers;
|
||||
}
|
||||
}
|
||||
exports.Polling = Polling;
|
||||
33
node_modules/engine.io/build/transports/websocket.d.ts
generated
vendored
Normal file
33
node_modules/engine.io/build/transports/websocket.d.ts
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import { EngineRequest, Transport } from "../transport";
|
||||
import type { Packet } from "engine.io-parser";
|
||||
import type { PerMessageDeflateOptions } from "ws";
|
||||
export declare class WebSocket extends Transport {
|
||||
perMessageDeflate?: boolean | PerMessageDeflateOptions;
|
||||
private socket;
|
||||
/**
|
||||
* WebSocket transport
|
||||
*
|
||||
* @param {EngineRequest} req
|
||||
*/
|
||||
constructor(req: EngineRequest);
|
||||
/**
|
||||
* Transport name
|
||||
*/
|
||||
get name(): string;
|
||||
/**
|
||||
* Advertise upgrade support.
|
||||
*/
|
||||
get handlesUpgrades(): boolean;
|
||||
send(packets: Packet[]): void;
|
||||
/**
|
||||
* Whether the encoding of the WebSocket frame can be skipped.
|
||||
* @param packet
|
||||
* @private
|
||||
*/
|
||||
private _canSendPreEncodedFrame;
|
||||
private _doSend;
|
||||
private _doSendLast;
|
||||
private _onSent;
|
||||
private _onSentLast;
|
||||
doClose(fn?: () => void): void;
|
||||
}
|
||||
93
node_modules/engine.io/build/transports/websocket.js
generated
vendored
Normal file
93
node_modules/engine.io/build/transports/websocket.js
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.WebSocket = void 0;
|
||||
const transport_1 = require("../transport");
|
||||
const debug_1 = require("debug");
|
||||
const debug = (0, debug_1.default)("engine:ws");
|
||||
class WebSocket extends transport_1.Transport {
|
||||
/**
|
||||
* WebSocket transport
|
||||
*
|
||||
* @param {EngineRequest} req
|
||||
*/
|
||||
constructor(req) {
|
||||
super(req);
|
||||
this._doSend = (data) => {
|
||||
this.socket.send(data, this._onSent);
|
||||
};
|
||||
this._doSendLast = (data) => {
|
||||
this.socket.send(data, this._onSentLast);
|
||||
};
|
||||
this._onSent = (err) => {
|
||||
if (err) {
|
||||
this.onError("write error", err.stack);
|
||||
}
|
||||
};
|
||||
this._onSentLast = (err) => {
|
||||
if (err) {
|
||||
this.onError("write error", err.stack);
|
||||
}
|
||||
else {
|
||||
this.emit("drain");
|
||||
this.writable = true;
|
||||
this.emit("ready");
|
||||
}
|
||||
};
|
||||
this.socket = req.websocket;
|
||||
this.socket.on("message", (data, isBinary) => {
|
||||
const message = isBinary ? data : data.toString();
|
||||
debug('received "%s"', message);
|
||||
super.onData(message);
|
||||
});
|
||||
this.socket.once("close", this.onClose.bind(this));
|
||||
this.socket.on("error", this.onError.bind(this));
|
||||
this.writable = true;
|
||||
this.perMessageDeflate = null;
|
||||
}
|
||||
/**
|
||||
* Transport name
|
||||
*/
|
||||
get name() {
|
||||
return "websocket";
|
||||
}
|
||||
/**
|
||||
* Advertise upgrade support.
|
||||
*/
|
||||
get handlesUpgrades() {
|
||||
return true;
|
||||
}
|
||||
send(packets) {
|
||||
this.writable = false;
|
||||
for (let i = 0; i < packets.length; i++) {
|
||||
const packet = packets[i];
|
||||
const isLast = i + 1 === packets.length;
|
||||
if (this._canSendPreEncodedFrame(packet)) {
|
||||
// the WebSocket frame was computed with WebSocket.Sender.frame()
|
||||
// see https://github.com/websockets/ws/issues/617#issuecomment-283002469
|
||||
// @ts-expect-error use of untyped member
|
||||
this.socket._sender.sendFrame(packet.options.wsPreEncodedFrame, isLast ? this._onSentLast : this._onSent);
|
||||
}
|
||||
else {
|
||||
this.parser.encodePacket(packet, this.supportsBinary, isLast ? this._doSendLast : this._doSend);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Whether the encoding of the WebSocket frame can be skipped.
|
||||
* @param packet
|
||||
* @private
|
||||
*/
|
||||
_canSendPreEncodedFrame(packet) {
|
||||
var _a, _b, _c;
|
||||
return (!this.perMessageDeflate &&
|
||||
// @ts-expect-error use of untyped member
|
||||
typeof ((_b = (_a = this.socket) === null || _a === void 0 ? void 0 : _a._sender) === null || _b === void 0 ? void 0 : _b.sendFrame) === "function" &&
|
||||
((_c = packet.options) === null || _c === void 0 ? void 0 : _c.wsPreEncodedFrame) !== undefined);
|
||||
}
|
||||
doClose(fn) {
|
||||
debug("closing");
|
||||
this.socket.close();
|
||||
fn && fn();
|
||||
}
|
||||
}
|
||||
exports.WebSocket = WebSocket;
|
||||
12
node_modules/engine.io/build/transports/webtransport.d.ts
generated
vendored
Normal file
12
node_modules/engine.io/build/transports/webtransport.d.ts
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Transport } from "../transport";
|
||||
/**
|
||||
* Reference: https://developer.mozilla.org/en-US/docs/Web/API/WebTransport_API
|
||||
*/
|
||||
export declare class WebTransport extends Transport {
|
||||
private readonly session;
|
||||
private readonly writer;
|
||||
constructor(session: any, stream: any, reader: any);
|
||||
get name(): string;
|
||||
send(packets: any): Promise<void>;
|
||||
doClose(fn: any): void;
|
||||
}
|
||||
63
node_modules/engine.io/build/transports/webtransport.js
generated
vendored
Normal file
63
node_modules/engine.io/build/transports/webtransport.js
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.WebTransport = void 0;
|
||||
const transport_1 = require("../transport");
|
||||
const debug_1 = require("debug");
|
||||
const engine_io_parser_1 = require("engine.io-parser");
|
||||
const debug = (0, debug_1.default)("engine:webtransport");
|
||||
/**
|
||||
* Reference: https://developer.mozilla.org/en-US/docs/Web/API/WebTransport_API
|
||||
*/
|
||||
class WebTransport extends transport_1.Transport {
|
||||
constructor(session, stream, reader) {
|
||||
super({ _query: { EIO: "4" } });
|
||||
this.session = session;
|
||||
const transformStream = (0, engine_io_parser_1.createPacketEncoderStream)();
|
||||
transformStream.readable.pipeTo(stream.writable).catch(() => {
|
||||
debug("the stream was closed");
|
||||
});
|
||||
this.writer = transformStream.writable.getWriter();
|
||||
(async () => {
|
||||
try {
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done) {
|
||||
debug("session is closed");
|
||||
break;
|
||||
}
|
||||
debug("received chunk: %o", value);
|
||||
this.onPacket(value);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
debug("error while reading: %s", e.message);
|
||||
}
|
||||
})();
|
||||
session.closed.then(() => this.onClose());
|
||||
this.writable = true;
|
||||
}
|
||||
get name() {
|
||||
return "webtransport";
|
||||
}
|
||||
async send(packets) {
|
||||
this.writable = false;
|
||||
try {
|
||||
for (let i = 0; i < packets.length; i++) {
|
||||
const packet = packets[i];
|
||||
await this.writer.write(packet);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
debug("error while writing: %s", e.message);
|
||||
}
|
||||
this.emit("drain");
|
||||
this.writable = true;
|
||||
this.emit("ready");
|
||||
}
|
||||
doClose(fn) {
|
||||
debug("closing WebTransport session");
|
||||
this.session.close();
|
||||
fn && fn();
|
||||
}
|
||||
}
|
||||
exports.WebTransport = WebTransport;
|
||||
43
node_modules/engine.io/build/userver.d.ts
generated
vendored
Normal file
43
node_modules/engine.io/build/userver.d.ts
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
import { AttachOptions, BaseServer } from "./server";
|
||||
import { EngineRequest } from "./transport";
|
||||
export interface uOptions {
|
||||
/**
|
||||
* What permessage-deflate compression to use. uWS.DISABLED, uWS.SHARED_COMPRESSOR or any of the uWS.DEDICATED_COMPRESSOR_xxxKB.
|
||||
* @default uWS.DISABLED
|
||||
*/
|
||||
compression?: number;
|
||||
/**
|
||||
* Maximum amount of seconds that may pass without sending or getting a message. Connection is closed if this timeout passes. Resolution (granularity) for timeouts are typically 4 seconds, rounded to closest. Disable by using 0.
|
||||
* @default 120
|
||||
*/
|
||||
idleTimeout?: number;
|
||||
/**
|
||||
* Maximum length of allowed backpressure per socket when publishing or sending messages. Slow receivers with too high backpressure will be skipped until they catch up or timeout.
|
||||
* @default 1024 * 1024
|
||||
*/
|
||||
maxBackpressure?: number;
|
||||
}
|
||||
/**
|
||||
* An Engine.IO server based on the `uWebSockets.js` package.
|
||||
*/
|
||||
export declare class uServer extends BaseServer {
|
||||
protected init(): void;
|
||||
protected cleanup(): void;
|
||||
/**
|
||||
* Prepares a request by processing the query string.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private prepare;
|
||||
protected createTransport(transportName: string, req: EngineRequest): any;
|
||||
/**
|
||||
* Attach the engine to a µWebSockets.js server
|
||||
* @param app
|
||||
* @param options
|
||||
*/
|
||||
attach(app: any, options?: AttachOptions & uOptions): void;
|
||||
_applyMiddlewares(req: any, res: any, callback: (err?: any) => void): void;
|
||||
private handleRequest;
|
||||
private handleUpgrade;
|
||||
private abortRequest;
|
||||
}
|
||||
280
node_modules/engine.io/build/userver.js
generated
vendored
Normal file
280
node_modules/engine.io/build/userver.js
generated
vendored
Normal file
@@ -0,0 +1,280 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.uServer = void 0;
|
||||
const debug_1 = require("debug");
|
||||
const server_1 = require("./server");
|
||||
const transports_uws_1 = require("./transports-uws");
|
||||
const debug = (0, debug_1.default)("engine:uws");
|
||||
/**
|
||||
* An Engine.IO server based on the `uWebSockets.js` package.
|
||||
*/
|
||||
// TODO export it into its own package
|
||||
class uServer extends server_1.BaseServer {
|
||||
init() { }
|
||||
cleanup() { }
|
||||
/**
|
||||
* Prepares a request by processing the query string.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
prepare(req, res) {
|
||||
req.method = req.getMethod().toUpperCase();
|
||||
req.url = req.getUrl();
|
||||
const params = new URLSearchParams(req.getQuery());
|
||||
req._query = Object.fromEntries(params.entries());
|
||||
req.headers = {};
|
||||
req.forEach((key, value) => {
|
||||
req.headers[key] = value;
|
||||
});
|
||||
// @ts-expect-error
|
||||
req.connection = {
|
||||
remoteAddress: Buffer.from(res.getRemoteAddressAsText()).toString(),
|
||||
};
|
||||
res.onAborted(() => {
|
||||
debug("response has been aborted");
|
||||
});
|
||||
}
|
||||
createTransport(transportName, req) {
|
||||
return new transports_uws_1.default[transportName](req);
|
||||
}
|
||||
/**
|
||||
* Attach the engine to a µWebSockets.js server
|
||||
* @param app
|
||||
* @param options
|
||||
*/
|
||||
attach(app /* : TemplatedApp */, options = {}) {
|
||||
const path = this._computePath(options);
|
||||
app
|
||||
.any(path, this.handleRequest.bind(this))
|
||||
//
|
||||
.ws(path, {
|
||||
compression: options.compression,
|
||||
idleTimeout: options.idleTimeout,
|
||||
maxBackpressure: options.maxBackpressure,
|
||||
maxPayloadLength: this.opts.maxHttpBufferSize,
|
||||
upgrade: this.handleUpgrade.bind(this),
|
||||
open: (ws) => {
|
||||
const transport = ws.getUserData().transport;
|
||||
transport.socket = ws;
|
||||
transport.writable = true;
|
||||
transport.emit("ready");
|
||||
},
|
||||
message: (ws, message, isBinary) => {
|
||||
ws.getUserData().transport.onData(isBinary ? message : Buffer.from(message).toString());
|
||||
},
|
||||
close: (ws, code, message) => {
|
||||
ws.getUserData().transport.onClose(code, message);
|
||||
},
|
||||
});
|
||||
}
|
||||
_applyMiddlewares(req, res, callback) {
|
||||
if (this.middlewares.length === 0) {
|
||||
return callback();
|
||||
}
|
||||
// needed to buffer headers until the status is computed
|
||||
req.res = new ResponseWrapper(res);
|
||||
super._applyMiddlewares(req, req.res, (err) => {
|
||||
// some middlewares (like express-session) wait for the writeHead() call to flush their headers
|
||||
// see https://github.com/expressjs/session/blob/1010fadc2f071ddf2add94235d72224cf65159c6/index.js#L220-L244
|
||||
req.res.writeHead();
|
||||
callback(err);
|
||||
});
|
||||
}
|
||||
handleRequest(res, req) {
|
||||
debug('handling "%s" http request "%s"', req.getMethod(), req.getUrl());
|
||||
this.prepare(req, res);
|
||||
req.res = res;
|
||||
const callback = (errorCode, errorContext) => {
|
||||
if (errorCode !== undefined) {
|
||||
this.emit("connection_error", {
|
||||
req,
|
||||
code: errorCode,
|
||||
message: server_1.Server.errorMessages[errorCode],
|
||||
context: errorContext,
|
||||
});
|
||||
this.abortRequest(req.res, errorCode, errorContext);
|
||||
return;
|
||||
}
|
||||
if (req._query.sid) {
|
||||
debug("setting new request for existing client");
|
||||
// @ts-ignore
|
||||
this.clients[req._query.sid].transport.onRequest(req);
|
||||
}
|
||||
else {
|
||||
const closeConnection = (errorCode, errorContext) => this.abortRequest(res, errorCode, errorContext);
|
||||
this.handshake(req._query.transport, req, closeConnection);
|
||||
}
|
||||
};
|
||||
this._applyMiddlewares(req, res, (err) => {
|
||||
if (err) {
|
||||
callback(server_1.Server.errors.BAD_REQUEST, { name: "MIDDLEWARE_FAILURE" });
|
||||
}
|
||||
else {
|
||||
this.verify(req, false, callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
handleUpgrade(res, req, context) {
|
||||
debug("on upgrade");
|
||||
this.prepare(req, res);
|
||||
req.res = res;
|
||||
const callback = async (errorCode, errorContext) => {
|
||||
if (errorCode !== undefined) {
|
||||
this.emit("connection_error", {
|
||||
req,
|
||||
code: errorCode,
|
||||
message: server_1.Server.errorMessages[errorCode],
|
||||
context: errorContext,
|
||||
});
|
||||
this.abortRequest(res, errorCode, errorContext);
|
||||
return;
|
||||
}
|
||||
const id = req._query.sid;
|
||||
let transport;
|
||||
if (id) {
|
||||
const client = this.clients[id];
|
||||
if (!client) {
|
||||
debug("upgrade attempt for closed client");
|
||||
return res.close();
|
||||
}
|
||||
else if (client.upgrading) {
|
||||
debug("transport has already been trying to upgrade");
|
||||
return res.close();
|
||||
}
|
||||
else if (client.upgraded) {
|
||||
debug("transport had already been upgraded");
|
||||
return res.close();
|
||||
}
|
||||
else {
|
||||
debug("upgrading existing transport");
|
||||
transport = this.createTransport(req._query.transport, req);
|
||||
client._maybeUpgrade(transport);
|
||||
}
|
||||
}
|
||||
else {
|
||||
transport = await this.handshake(req._query.transport, req, (errorCode, errorContext) => this.abortRequest(res, errorCode, errorContext));
|
||||
if (!transport) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// calling writeStatus() triggers the flushing of any header added in a middleware
|
||||
req.res.writeStatus("101 Switching Protocols");
|
||||
res.upgrade({
|
||||
transport,
|
||||
}, req.getHeader("sec-websocket-key"), req.getHeader("sec-websocket-protocol"), req.getHeader("sec-websocket-extensions"), context);
|
||||
};
|
||||
this._applyMiddlewares(req, res, (err) => {
|
||||
if (err) {
|
||||
callback(server_1.Server.errors.BAD_REQUEST, { name: "MIDDLEWARE_FAILURE" });
|
||||
}
|
||||
else {
|
||||
this.verify(req, true, callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
abortRequest(res, errorCode, errorContext) {
|
||||
const statusCode = errorCode === server_1.Server.errors.FORBIDDEN
|
||||
? "403 Forbidden"
|
||||
: "400 Bad Request";
|
||||
const message = errorContext && errorContext.message
|
||||
? errorContext.message
|
||||
: server_1.Server.errorMessages[errorCode];
|
||||
res.writeStatus(statusCode);
|
||||
res.writeHeader("Content-Type", "application/json");
|
||||
res.end(JSON.stringify({
|
||||
code: errorCode,
|
||||
message,
|
||||
}));
|
||||
}
|
||||
}
|
||||
exports.uServer = uServer;
|
||||
class ResponseWrapper {
|
||||
constructor(res) {
|
||||
this.res = res;
|
||||
this.statusWritten = false;
|
||||
this.headers = [];
|
||||
this.isAborted = false;
|
||||
}
|
||||
set statusCode(status) {
|
||||
if (!status) {
|
||||
return;
|
||||
}
|
||||
// FIXME: handle all status codes?
|
||||
this.writeStatus(status === 200 ? "200 OK" : "204 No Content");
|
||||
}
|
||||
writeHead(status) {
|
||||
this.statusCode = status;
|
||||
}
|
||||
setHeader(key, value) {
|
||||
if (Array.isArray(value)) {
|
||||
value.forEach((val) => {
|
||||
this.writeHeader(key, val);
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.writeHeader(key, value);
|
||||
}
|
||||
}
|
||||
removeHeader() {
|
||||
// FIXME: not implemented
|
||||
}
|
||||
// needed by vary: https://github.com/jshttp/vary/blob/5d725d059b3871025cf753e9dfa08924d0bcfa8f/index.js#L134
|
||||
getHeader() { }
|
||||
writeStatus(status) {
|
||||
if (this.isAborted)
|
||||
return;
|
||||
this.res.writeStatus(status);
|
||||
this.statusWritten = true;
|
||||
this.writeBufferedHeaders();
|
||||
return this;
|
||||
}
|
||||
writeHeader(key, value) {
|
||||
if (this.isAborted)
|
||||
return;
|
||||
if (key === "Content-Length") {
|
||||
// the content length is automatically added by uWebSockets.js
|
||||
return;
|
||||
}
|
||||
if (this.statusWritten) {
|
||||
this.res.writeHeader(key, value);
|
||||
}
|
||||
else {
|
||||
this.headers.push([key, value]);
|
||||
}
|
||||
}
|
||||
writeBufferedHeaders() {
|
||||
this.headers.forEach(([key, value]) => {
|
||||
this.res.writeHeader(key, value);
|
||||
});
|
||||
}
|
||||
end(data) {
|
||||
if (this.isAborted)
|
||||
return;
|
||||
this.res.cork(() => {
|
||||
if (!this.statusWritten) {
|
||||
// status will be inferred as "200 OK"
|
||||
this.writeBufferedHeaders();
|
||||
}
|
||||
this.res.end(data);
|
||||
});
|
||||
}
|
||||
onData(fn) {
|
||||
if (this.isAborted)
|
||||
return;
|
||||
this.res.onData(fn);
|
||||
}
|
||||
onAborted(fn) {
|
||||
if (this.isAborted)
|
||||
return;
|
||||
this.res.onAborted(() => {
|
||||
// Any attempt to use the UWS response object after abort will throw!
|
||||
this.isAborted = true;
|
||||
fn();
|
||||
});
|
||||
}
|
||||
cork(fn) {
|
||||
if (this.isAborted)
|
||||
return;
|
||||
this.res.cork(fn);
|
||||
}
|
||||
}
|
||||
243
node_modules/engine.io/node_modules/accepts/HISTORY.md
generated
vendored
Normal file
243
node_modules/engine.io/node_modules/accepts/HISTORY.md
generated
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
1.3.8 / 2022-02-02
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.1.34
|
||||
- deps: mime-db@~1.51.0
|
||||
* deps: negotiator@0.6.3
|
||||
|
||||
1.3.7 / 2019-04-29
|
||||
==================
|
||||
|
||||
* deps: negotiator@0.6.2
|
||||
- Fix sorting charset, encoding, and language with extra parameters
|
||||
|
||||
1.3.6 / 2019-04-28
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.1.24
|
||||
- deps: mime-db@~1.40.0
|
||||
|
||||
1.3.5 / 2018-02-28
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.1.18
|
||||
- deps: mime-db@~1.33.0
|
||||
|
||||
1.3.4 / 2017-08-22
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.1.16
|
||||
- deps: mime-db@~1.29.0
|
||||
|
||||
1.3.3 / 2016-05-02
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.1.11
|
||||
- deps: mime-db@~1.23.0
|
||||
* deps: negotiator@0.6.1
|
||||
- perf: improve `Accept` parsing speed
|
||||
- perf: improve `Accept-Charset` parsing speed
|
||||
- perf: improve `Accept-Encoding` parsing speed
|
||||
- perf: improve `Accept-Language` parsing speed
|
||||
|
||||
1.3.2 / 2016-03-08
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.1.10
|
||||
- Fix extension of `application/dash+xml`
|
||||
- Update primary extension for `audio/mp4`
|
||||
- deps: mime-db@~1.22.0
|
||||
|
||||
1.3.1 / 2016-01-19
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.1.9
|
||||
- deps: mime-db@~1.21.0
|
||||
|
||||
1.3.0 / 2015-09-29
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.1.7
|
||||
- deps: mime-db@~1.19.0
|
||||
* deps: negotiator@0.6.0
|
||||
- Fix including type extensions in parameters in `Accept` parsing
|
||||
- Fix parsing `Accept` parameters with quoted equals
|
||||
- Fix parsing `Accept` parameters with quoted semicolons
|
||||
- Lazy-load modules from main entry point
|
||||
- perf: delay type concatenation until needed
|
||||
- perf: enable strict mode
|
||||
- perf: hoist regular expressions
|
||||
- perf: remove closures getting spec properties
|
||||
- perf: remove a closure from media type parsing
|
||||
- perf: remove property delete from media type parsing
|
||||
|
||||
1.2.13 / 2015-09-06
|
||||
===================
|
||||
|
||||
* deps: mime-types@~2.1.6
|
||||
- deps: mime-db@~1.18.0
|
||||
|
||||
1.2.12 / 2015-07-30
|
||||
===================
|
||||
|
||||
* deps: mime-types@~2.1.4
|
||||
- deps: mime-db@~1.16.0
|
||||
|
||||
1.2.11 / 2015-07-16
|
||||
===================
|
||||
|
||||
* deps: mime-types@~2.1.3
|
||||
- deps: mime-db@~1.15.0
|
||||
|
||||
1.2.10 / 2015-07-01
|
||||
===================
|
||||
|
||||
* deps: mime-types@~2.1.2
|
||||
- deps: mime-db@~1.14.0
|
||||
|
||||
1.2.9 / 2015-06-08
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.1.1
|
||||
- perf: fix deopt during mapping
|
||||
|
||||
1.2.8 / 2015-06-07
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.1.0
|
||||
- deps: mime-db@~1.13.0
|
||||
* perf: avoid argument reassignment & argument slice
|
||||
* perf: avoid negotiator recursive construction
|
||||
* perf: enable strict mode
|
||||
* perf: remove unnecessary bitwise operator
|
||||
|
||||
1.2.7 / 2015-05-10
|
||||
==================
|
||||
|
||||
* deps: negotiator@0.5.3
|
||||
- Fix media type parameter matching to be case-insensitive
|
||||
|
||||
1.2.6 / 2015-05-07
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.0.11
|
||||
- deps: mime-db@~1.9.1
|
||||
* deps: negotiator@0.5.2
|
||||
- Fix comparing media types with quoted values
|
||||
- Fix splitting media types with quoted commas
|
||||
|
||||
1.2.5 / 2015-03-13
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.0.10
|
||||
- deps: mime-db@~1.8.0
|
||||
|
||||
1.2.4 / 2015-02-14
|
||||
==================
|
||||
|
||||
* Support Node.js 0.6
|
||||
* deps: mime-types@~2.0.9
|
||||
- deps: mime-db@~1.7.0
|
||||
* deps: negotiator@0.5.1
|
||||
- Fix preference sorting to be stable for long acceptable lists
|
||||
|
||||
1.2.3 / 2015-01-31
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.0.8
|
||||
- deps: mime-db@~1.6.0
|
||||
|
||||
1.2.2 / 2014-12-30
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.0.7
|
||||
- deps: mime-db@~1.5.0
|
||||
|
||||
1.2.1 / 2014-12-30
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.0.5
|
||||
- deps: mime-db@~1.3.1
|
||||
|
||||
1.2.0 / 2014-12-19
|
||||
==================
|
||||
|
||||
* deps: negotiator@0.5.0
|
||||
- Fix list return order when large accepted list
|
||||
- Fix missing identity encoding when q=0 exists
|
||||
- Remove dynamic building of Negotiator class
|
||||
|
||||
1.1.4 / 2014-12-10
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.0.4
|
||||
- deps: mime-db@~1.3.0
|
||||
|
||||
1.1.3 / 2014-11-09
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.0.3
|
||||
- deps: mime-db@~1.2.0
|
||||
|
||||
1.1.2 / 2014-10-14
|
||||
==================
|
||||
|
||||
* deps: negotiator@0.4.9
|
||||
- Fix error when media type has invalid parameter
|
||||
|
||||
1.1.1 / 2014-09-28
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.0.2
|
||||
- deps: mime-db@~1.1.0
|
||||
* deps: negotiator@0.4.8
|
||||
- Fix all negotiations to be case-insensitive
|
||||
- Stable sort preferences of same quality according to client order
|
||||
|
||||
1.1.0 / 2014-09-02
|
||||
==================
|
||||
|
||||
* update `mime-types`
|
||||
|
||||
1.0.7 / 2014-07-04
|
||||
==================
|
||||
|
||||
* Fix wrong type returned from `type` when match after unknown extension
|
||||
|
||||
1.0.6 / 2014-06-24
|
||||
==================
|
||||
|
||||
* deps: negotiator@0.4.7
|
||||
|
||||
1.0.5 / 2014-06-20
|
||||
==================
|
||||
|
||||
* fix crash when unknown extension given
|
||||
|
||||
1.0.4 / 2014-06-19
|
||||
==================
|
||||
|
||||
* use `mime-types`
|
||||
|
||||
1.0.3 / 2014-06-11
|
||||
==================
|
||||
|
||||
* deps: negotiator@0.4.6
|
||||
- Order by specificity when quality is the same
|
||||
|
||||
1.0.2 / 2014-05-29
|
||||
==================
|
||||
|
||||
* Fix interpretation when header not in request
|
||||
* deps: pin negotiator@0.4.5
|
||||
|
||||
1.0.1 / 2014-01-18
|
||||
==================
|
||||
|
||||
* Identity encoding isn't always acceptable
|
||||
* deps: negotiator@~0.4.0
|
||||
|
||||
1.0.0 / 2013-12-27
|
||||
==================
|
||||
|
||||
* Genesis
|
||||
23
node_modules/engine.io/node_modules/accepts/LICENSE
generated
vendored
Normal file
23
node_modules/engine.io/node_modules/accepts/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
|
||||
Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>
|
||||
|
||||
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.
|
||||
140
node_modules/engine.io/node_modules/accepts/README.md
generated
vendored
Normal file
140
node_modules/engine.io/node_modules/accepts/README.md
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
# accepts
|
||||
|
||||
[![NPM Version][npm-version-image]][npm-url]
|
||||
[![NPM Downloads][npm-downloads-image]][npm-url]
|
||||
[![Node.js Version][node-version-image]][node-version-url]
|
||||
[![Build Status][github-actions-ci-image]][github-actions-ci-url]
|
||||
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||
|
||||
Higher level content negotiation based on [negotiator](https://www.npmjs.com/package/negotiator).
|
||||
Extracted from [koa](https://www.npmjs.com/package/koa) for general use.
|
||||
|
||||
In addition to negotiator, it allows:
|
||||
|
||||
- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])`
|
||||
as well as `('text/html', 'application/json')`.
|
||||
- Allows type shorthands such as `json`.
|
||||
- Returns `false` when no types match
|
||||
- Treats non-existent headers as `*`
|
||||
|
||||
## Installation
|
||||
|
||||
This is a [Node.js](https://nodejs.org/en/) module available through the
|
||||
[npm registry](https://www.npmjs.com/). Installation is done using the
|
||||
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
|
||||
|
||||
```sh
|
||||
$ npm install accepts
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```js
|
||||
var accepts = require('accepts')
|
||||
```
|
||||
|
||||
### accepts(req)
|
||||
|
||||
Create a new `Accepts` object for the given `req`.
|
||||
|
||||
#### .charset(charsets)
|
||||
|
||||
Return the first accepted charset. If nothing in `charsets` is accepted,
|
||||
then `false` is returned.
|
||||
|
||||
#### .charsets()
|
||||
|
||||
Return the charsets that the request accepts, in the order of the client's
|
||||
preference (most preferred first).
|
||||
|
||||
#### .encoding(encodings)
|
||||
|
||||
Return the first accepted encoding. If nothing in `encodings` is accepted,
|
||||
then `false` is returned.
|
||||
|
||||
#### .encodings()
|
||||
|
||||
Return the encodings that the request accepts, in the order of the client's
|
||||
preference (most preferred first).
|
||||
|
||||
#### .language(languages)
|
||||
|
||||
Return the first accepted language. If nothing in `languages` is accepted,
|
||||
then `false` is returned.
|
||||
|
||||
#### .languages()
|
||||
|
||||
Return the languages that the request accepts, in the order of the client's
|
||||
preference (most preferred first).
|
||||
|
||||
#### .type(types)
|
||||
|
||||
Return the first accepted type (and it is returned as the same text as what
|
||||
appears in the `types` array). If nothing in `types` is accepted, then `false`
|
||||
is returned.
|
||||
|
||||
The `types` array can contain full MIME types or file extensions. Any value
|
||||
that is not a full MIME types is passed to `require('mime-types').lookup`.
|
||||
|
||||
#### .types()
|
||||
|
||||
Return the types that the request accepts, in the order of the client's
|
||||
preference (most preferred first).
|
||||
|
||||
## Examples
|
||||
|
||||
### Simple type negotiation
|
||||
|
||||
This simple example shows how to use `accepts` to return a different typed
|
||||
respond body based on what the client wants to accept. The server lists it's
|
||||
preferences in order and will get back the best match between the client and
|
||||
server.
|
||||
|
||||
```js
|
||||
var accepts = require('accepts')
|
||||
var http = require('http')
|
||||
|
||||
function app (req, res) {
|
||||
var accept = accepts(req)
|
||||
|
||||
// the order of this list is significant; should be server preferred order
|
||||
switch (accept.type(['json', 'html'])) {
|
||||
case 'json':
|
||||
res.setHeader('Content-Type', 'application/json')
|
||||
res.write('{"hello":"world!"}')
|
||||
break
|
||||
case 'html':
|
||||
res.setHeader('Content-Type', 'text/html')
|
||||
res.write('<b>hello, world!</b>')
|
||||
break
|
||||
default:
|
||||
// the fallback is text/plain, so no need to specify it above
|
||||
res.setHeader('Content-Type', 'text/plain')
|
||||
res.write('hello, world!')
|
||||
break
|
||||
}
|
||||
|
||||
res.end()
|
||||
}
|
||||
|
||||
http.createServer(app).listen(3000)
|
||||
```
|
||||
|
||||
You can test this out with the cURL program:
|
||||
```sh
|
||||
curl -I -H'Accept: text/html' http://localhost:3000/
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/accepts/master
|
||||
[coveralls-url]: https://coveralls.io/r/jshttp/accepts?branch=master
|
||||
[github-actions-ci-image]: https://badgen.net/github/checks/jshttp/accepts/master?label=ci
|
||||
[github-actions-ci-url]: https://github.com/jshttp/accepts/actions/workflows/ci.yml
|
||||
[node-version-image]: https://badgen.net/npm/node/accepts
|
||||
[node-version-url]: https://nodejs.org/en/download
|
||||
[npm-downloads-image]: https://badgen.net/npm/dm/accepts
|
||||
[npm-url]: https://npmjs.org/package/accepts
|
||||
[npm-version-image]: https://badgen.net/npm/v/accepts
|
||||
238
node_modules/engine.io/node_modules/accepts/index.js
generated
vendored
Normal file
238
node_modules/engine.io/node_modules/accepts/index.js
generated
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
/*!
|
||||
* accepts
|
||||
* Copyright(c) 2014 Jonathan Ong
|
||||
* Copyright(c) 2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var Negotiator = require('negotiator')
|
||||
var mime = require('mime-types')
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = Accepts
|
||||
|
||||
/**
|
||||
* Create a new Accepts object for the given req.
|
||||
*
|
||||
* @param {object} req
|
||||
* @public
|
||||
*/
|
||||
|
||||
function Accepts (req) {
|
||||
if (!(this instanceof Accepts)) {
|
||||
return new Accepts(req)
|
||||
}
|
||||
|
||||
this.headers = req.headers
|
||||
this.negotiator = new Negotiator(req)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given `type(s)` is acceptable, returning
|
||||
* the best match when true, otherwise `undefined`, in which
|
||||
* case you should respond with 406 "Not Acceptable".
|
||||
*
|
||||
* The `type` value may be a single mime type string
|
||||
* such as "application/json", the extension name
|
||||
* such as "json" or an array `["json", "html", "text/plain"]`. When a list
|
||||
* or array is given the _best_ match, if any is returned.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* // Accept: text/html
|
||||
* this.types('html');
|
||||
* // => "html"
|
||||
*
|
||||
* // Accept: text/*, application/json
|
||||
* this.types('html');
|
||||
* // => "html"
|
||||
* this.types('text/html');
|
||||
* // => "text/html"
|
||||
* this.types('json', 'text');
|
||||
* // => "json"
|
||||
* this.types('application/json');
|
||||
* // => "application/json"
|
||||
*
|
||||
* // Accept: text/*, application/json
|
||||
* this.types('image/png');
|
||||
* this.types('png');
|
||||
* // => undefined
|
||||
*
|
||||
* // Accept: text/*;q=.5, application/json
|
||||
* this.types(['html', 'json']);
|
||||
* this.types('html', 'json');
|
||||
* // => "json"
|
||||
*
|
||||
* @param {String|Array} types...
|
||||
* @return {String|Array|Boolean}
|
||||
* @public
|
||||
*/
|
||||
|
||||
Accepts.prototype.type =
|
||||
Accepts.prototype.types = function (types_) {
|
||||
var types = types_
|
||||
|
||||
// support flattened arguments
|
||||
if (types && !Array.isArray(types)) {
|
||||
types = new Array(arguments.length)
|
||||
for (var i = 0; i < types.length; i++) {
|
||||
types[i] = arguments[i]
|
||||
}
|
||||
}
|
||||
|
||||
// no types, return all requested types
|
||||
if (!types || types.length === 0) {
|
||||
return this.negotiator.mediaTypes()
|
||||
}
|
||||
|
||||
// no accept header, return first given type
|
||||
if (!this.headers.accept) {
|
||||
return types[0]
|
||||
}
|
||||
|
||||
var mimes = types.map(extToMime)
|
||||
var accepts = this.negotiator.mediaTypes(mimes.filter(validMime))
|
||||
var first = accepts[0]
|
||||
|
||||
return first
|
||||
? types[mimes.indexOf(first)]
|
||||
: false
|
||||
}
|
||||
|
||||
/**
|
||||
* Return accepted encodings or best fit based on `encodings`.
|
||||
*
|
||||
* Given `Accept-Encoding: gzip, deflate`
|
||||
* an array sorted by quality is returned:
|
||||
*
|
||||
* ['gzip', 'deflate']
|
||||
*
|
||||
* @param {String|Array} encodings...
|
||||
* @return {String|Array}
|
||||
* @public
|
||||
*/
|
||||
|
||||
Accepts.prototype.encoding =
|
||||
Accepts.prototype.encodings = function (encodings_) {
|
||||
var encodings = encodings_
|
||||
|
||||
// support flattened arguments
|
||||
if (encodings && !Array.isArray(encodings)) {
|
||||
encodings = new Array(arguments.length)
|
||||
for (var i = 0; i < encodings.length; i++) {
|
||||
encodings[i] = arguments[i]
|
||||
}
|
||||
}
|
||||
|
||||
// no encodings, return all requested encodings
|
||||
if (!encodings || encodings.length === 0) {
|
||||
return this.negotiator.encodings()
|
||||
}
|
||||
|
||||
return this.negotiator.encodings(encodings)[0] || false
|
||||
}
|
||||
|
||||
/**
|
||||
* Return accepted charsets or best fit based on `charsets`.
|
||||
*
|
||||
* Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5`
|
||||
* an array sorted by quality is returned:
|
||||
*
|
||||
* ['utf-8', 'utf-7', 'iso-8859-1']
|
||||
*
|
||||
* @param {String|Array} charsets...
|
||||
* @return {String|Array}
|
||||
* @public
|
||||
*/
|
||||
|
||||
Accepts.prototype.charset =
|
||||
Accepts.prototype.charsets = function (charsets_) {
|
||||
var charsets = charsets_
|
||||
|
||||
// support flattened arguments
|
||||
if (charsets && !Array.isArray(charsets)) {
|
||||
charsets = new Array(arguments.length)
|
||||
for (var i = 0; i < charsets.length; i++) {
|
||||
charsets[i] = arguments[i]
|
||||
}
|
||||
}
|
||||
|
||||
// no charsets, return all requested charsets
|
||||
if (!charsets || charsets.length === 0) {
|
||||
return this.negotiator.charsets()
|
||||
}
|
||||
|
||||
return this.negotiator.charsets(charsets)[0] || false
|
||||
}
|
||||
|
||||
/**
|
||||
* Return accepted languages or best fit based on `langs`.
|
||||
*
|
||||
* Given `Accept-Language: en;q=0.8, es, pt`
|
||||
* an array sorted by quality is returned:
|
||||
*
|
||||
* ['es', 'pt', 'en']
|
||||
*
|
||||
* @param {String|Array} langs...
|
||||
* @return {Array|String}
|
||||
* @public
|
||||
*/
|
||||
|
||||
Accepts.prototype.lang =
|
||||
Accepts.prototype.langs =
|
||||
Accepts.prototype.language =
|
||||
Accepts.prototype.languages = function (languages_) {
|
||||
var languages = languages_
|
||||
|
||||
// support flattened arguments
|
||||
if (languages && !Array.isArray(languages)) {
|
||||
languages = new Array(arguments.length)
|
||||
for (var i = 0; i < languages.length; i++) {
|
||||
languages[i] = arguments[i]
|
||||
}
|
||||
}
|
||||
|
||||
// no languages, return all requested languages
|
||||
if (!languages || languages.length === 0) {
|
||||
return this.negotiator.languages()
|
||||
}
|
||||
|
||||
return this.negotiator.languages(languages)[0] || false
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert extnames to mime.
|
||||
*
|
||||
* @param {String} type
|
||||
* @return {String}
|
||||
* @private
|
||||
*/
|
||||
|
||||
function extToMime (type) {
|
||||
return type.indexOf('/') === -1
|
||||
? mime.lookup(type)
|
||||
: type
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if mime is valid.
|
||||
*
|
||||
* @param {String} type
|
||||
* @return {String}
|
||||
* @private
|
||||
*/
|
||||
|
||||
function validMime (type) {
|
||||
return typeof type === 'string'
|
||||
}
|
||||
47
node_modules/engine.io/node_modules/accepts/package.json
generated
vendored
Normal file
47
node_modules/engine.io/node_modules/accepts/package.json
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "accepts",
|
||||
"description": "Higher-level content negotiation",
|
||||
"version": "1.3.8",
|
||||
"contributors": [
|
||||
"Douglas Christopher Wilson <doug@somethingdoug.com>",
|
||||
"Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)"
|
||||
],
|
||||
"license": "MIT",
|
||||
"repository": "jshttp/accepts",
|
||||
"dependencies": {
|
||||
"mime-types": "~2.1.34",
|
||||
"negotiator": "0.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"deep-equal": "1.0.1",
|
||||
"eslint": "7.32.0",
|
||||
"eslint-config-standard": "14.1.1",
|
||||
"eslint-plugin-import": "2.25.4",
|
||||
"eslint-plugin-markdown": "2.2.1",
|
||||
"eslint-plugin-node": "11.1.0",
|
||||
"eslint-plugin-promise": "4.3.1",
|
||||
"eslint-plugin-standard": "4.1.0",
|
||||
"mocha": "9.2.0",
|
||||
"nyc": "15.1.0"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE",
|
||||
"HISTORY.md",
|
||||
"index.js"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"test": "mocha --reporter spec --check-leaks --bail test/",
|
||||
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
|
||||
"test-cov": "nyc --reporter=html --reporter=text npm test"
|
||||
},
|
||||
"keywords": [
|
||||
"content",
|
||||
"negotiation",
|
||||
"accept",
|
||||
"accepts"
|
||||
]
|
||||
}
|
||||
507
node_modules/engine.io/node_modules/mime-db/HISTORY.md
generated
vendored
Normal file
507
node_modules/engine.io/node_modules/mime-db/HISTORY.md
generated
vendored
Normal file
@@ -0,0 +1,507 @@
|
||||
1.52.0 / 2022-02-21
|
||||
===================
|
||||
|
||||
* Add extensions from IANA for more `image/*` types
|
||||
* Add extension `.asc` to `application/pgp-keys`
|
||||
* Add extensions to various XML types
|
||||
* Add new upstream MIME types
|
||||
|
||||
1.51.0 / 2021-11-08
|
||||
===================
|
||||
|
||||
* Add new upstream MIME types
|
||||
* Mark `image/vnd.microsoft.icon` as compressible
|
||||
* Mark `image/vnd.ms-dds` as compressible
|
||||
|
||||
1.50.0 / 2021-09-15
|
||||
===================
|
||||
|
||||
* Add deprecated iWorks mime types and extensions
|
||||
* Add new upstream MIME types
|
||||
|
||||
1.49.0 / 2021-07-26
|
||||
===================
|
||||
|
||||
* Add extension `.trig` to `application/trig`
|
||||
* Add new upstream MIME types
|
||||
|
||||
1.48.0 / 2021-05-30
|
||||
===================
|
||||
|
||||
* Add extension `.mvt` to `application/vnd.mapbox-vector-tile`
|
||||
* Add new upstream MIME types
|
||||
* Mark `text/yaml` as compressible
|
||||
|
||||
1.47.0 / 2021-04-01
|
||||
===================
|
||||
|
||||
* Add new upstream MIME types
|
||||
* Remove ambigious extensions from IANA for `application/*+xml` types
|
||||
* Update primary extension to `.es` for `application/ecmascript`
|
||||
|
||||
1.46.0 / 2021-02-13
|
||||
===================
|
||||
|
||||
* Add extension `.amr` to `audio/amr`
|
||||
* Add extension `.m4s` to `video/iso.segment`
|
||||
* Add extension `.opus` to `audio/ogg`
|
||||
* Add new upstream MIME types
|
||||
|
||||
1.45.0 / 2020-09-22
|
||||
===================
|
||||
|
||||
* Add `application/ubjson` with extension `.ubj`
|
||||
* Add `image/avif` with extension `.avif`
|
||||
* Add `image/ktx2` with extension `.ktx2`
|
||||
* Add extension `.dbf` to `application/vnd.dbf`
|
||||
* Add extension `.rar` to `application/vnd.rar`
|
||||
* Add extension `.td` to `application/urc-targetdesc+xml`
|
||||
* Add new upstream MIME types
|
||||
* Fix extension of `application/vnd.apple.keynote` to be `.key`
|
||||
|
||||
1.44.0 / 2020-04-22
|
||||
===================
|
||||
|
||||
* Add charsets from IANA
|
||||
* Add extension `.cjs` to `application/node`
|
||||
* Add new upstream MIME types
|
||||
|
||||
1.43.0 / 2020-01-05
|
||||
===================
|
||||
|
||||
* Add `application/x-keepass2` with extension `.kdbx`
|
||||
* Add extension `.mxmf` to `audio/mobile-xmf`
|
||||
* Add extensions from IANA for `application/*+xml` types
|
||||
* Add new upstream MIME types
|
||||
|
||||
1.42.0 / 2019-09-25
|
||||
===================
|
||||
|
||||
* Add `image/vnd.ms-dds` with extension `.dds`
|
||||
* Add new upstream MIME types
|
||||
* Remove compressible from `multipart/mixed`
|
||||
|
||||
1.41.0 / 2019-08-30
|
||||
===================
|
||||
|
||||
* Add new upstream MIME types
|
||||
* Add `application/toml` with extension `.toml`
|
||||
* Mark `font/ttf` as compressible
|
||||
|
||||
1.40.0 / 2019-04-20
|
||||
===================
|
||||
|
||||
* Add extensions from IANA for `model/*` types
|
||||
* Add `text/mdx` with extension `.mdx`
|
||||
|
||||
1.39.0 / 2019-04-04
|
||||
===================
|
||||
|
||||
* Add extensions `.siv` and `.sieve` to `application/sieve`
|
||||
* Add new upstream MIME types
|
||||
|
||||
1.38.0 / 2019-02-04
|
||||
===================
|
||||
|
||||
* Add extension `.nq` to `application/n-quads`
|
||||
* Add extension `.nt` to `application/n-triples`
|
||||
* Add new upstream MIME types
|
||||
* Mark `text/less` as compressible
|
||||
|
||||
1.37.0 / 2018-10-19
|
||||
===================
|
||||
|
||||
* Add extensions to HEIC image types
|
||||
* Add new upstream MIME types
|
||||
|
||||
1.36.0 / 2018-08-20
|
||||
===================
|
||||
|
||||
* Add Apple file extensions from IANA
|
||||
* Add extensions from IANA for `image/*` types
|
||||
* Add new upstream MIME types
|
||||
|
||||
1.35.0 / 2018-07-15
|
||||
===================
|
||||
|
||||
* Add extension `.owl` to `application/rdf+xml`
|
||||
* Add new upstream MIME types
|
||||
- Removes extension `.woff` from `application/font-woff`
|
||||
|
||||
1.34.0 / 2018-06-03
|
||||
===================
|
||||
|
||||
* Add extension `.csl` to `application/vnd.citationstyles.style+xml`
|
||||
* Add extension `.es` to `application/ecmascript`
|
||||
* Add new upstream MIME types
|
||||
* Add `UTF-8` as default charset for `text/turtle`
|
||||
* Mark all XML-derived types as compressible
|
||||
|
||||
1.33.0 / 2018-02-15
|
||||
===================
|
||||
|
||||
* Add extensions from IANA for `message/*` types
|
||||
* Add new upstream MIME types
|
||||
* Fix some incorrect OOXML types
|
||||
* Remove `application/font-woff2`
|
||||
|
||||
1.32.0 / 2017-11-29
|
||||
===================
|
||||
|
||||
* Add new upstream MIME types
|
||||
* Update `text/hjson` to registered `application/hjson`
|
||||
* Add `text/shex` with extension `.shex`
|
||||
|
||||
1.31.0 / 2017-10-25
|
||||
===================
|
||||
|
||||
* Add `application/raml+yaml` with extension `.raml`
|
||||
* Add `application/wasm` with extension `.wasm`
|
||||
* Add new `font` type from IANA
|
||||
* Add new upstream font extensions
|
||||
* Add new upstream MIME types
|
||||
* Add extensions for JPEG-2000 images
|
||||
|
||||
1.30.0 / 2017-08-27
|
||||
===================
|
||||
|
||||
* Add `application/vnd.ms-outlook`
|
||||
* Add `application/x-arj`
|
||||
* Add extension `.mjs` to `application/javascript`
|
||||
* Add glTF types and extensions
|
||||
* Add new upstream MIME types
|
||||
* Add `text/x-org`
|
||||
* Add VirtualBox MIME types
|
||||
* Fix `source` records for `video/*` types that are IANA
|
||||
* Update `font/opentype` to registered `font/otf`
|
||||
|
||||
1.29.0 / 2017-07-10
|
||||
===================
|
||||
|
||||
* Add `application/fido.trusted-apps+json`
|
||||
* Add extension `.wadl` to `application/vnd.sun.wadl+xml`
|
||||
* Add new upstream MIME types
|
||||
* Add `UTF-8` as default charset for `text/css`
|
||||
|
||||
1.28.0 / 2017-05-14
|
||||
===================
|
||||
|
||||
* Add new upstream MIME types
|
||||
* Add extension `.gz` to `application/gzip`
|
||||
* Update extensions `.md` and `.markdown` to be `text/markdown`
|
||||
|
||||
1.27.0 / 2017-03-16
|
||||
===================
|
||||
|
||||
* Add new upstream MIME types
|
||||
* Add `image/apng` with extension `.apng`
|
||||
|
||||
1.26.0 / 2017-01-14
|
||||
===================
|
||||
|
||||
* Add new upstream MIME types
|
||||
* Add extension `.geojson` to `application/geo+json`
|
||||
|
||||
1.25.0 / 2016-11-11
|
||||
===================
|
||||
|
||||
* Add new upstream MIME types
|
||||
|
||||
1.24.0 / 2016-09-18
|
||||
===================
|
||||
|
||||
* Add `audio/mp3`
|
||||
* Add new upstream MIME types
|
||||
|
||||
1.23.0 / 2016-05-01
|
||||
===================
|
||||
|
||||
* Add new upstream MIME types
|
||||
* Add extension `.3gpp` to `audio/3gpp`
|
||||
|
||||
1.22.0 / 2016-02-15
|
||||
===================
|
||||
|
||||
* Add `text/slim`
|
||||
* Add extension `.rng` to `application/xml`
|
||||
* Add new upstream MIME types
|
||||
* Fix extension of `application/dash+xml` to be `.mpd`
|
||||
* Update primary extension to `.m4a` for `audio/mp4`
|
||||
|
||||
1.21.0 / 2016-01-06
|
||||
===================
|
||||
|
||||
* Add Google document types
|
||||
* Add new upstream MIME types
|
||||
|
||||
1.20.0 / 2015-11-10
|
||||
===================
|
||||
|
||||
* Add `text/x-suse-ymp`
|
||||
* Add new upstream MIME types
|
||||
|
||||
1.19.0 / 2015-09-17
|
||||
===================
|
||||
|
||||
* Add `application/vnd.apple.pkpass`
|
||||
* Add new upstream MIME types
|
||||
|
||||
1.18.0 / 2015-09-03
|
||||
===================
|
||||
|
||||
* Add new upstream MIME types
|
||||
|
||||
1.17.0 / 2015-08-13
|
||||
===================
|
||||
|
||||
* Add `application/x-msdos-program`
|
||||
* Add `audio/g711-0`
|
||||
* Add `image/vnd.mozilla.apng`
|
||||
* Add extension `.exe` to `application/x-msdos-program`
|
||||
|
||||
1.16.0 / 2015-07-29
|
||||
===================
|
||||
|
||||
* Add `application/vnd.uri-map`
|
||||
|
||||
1.15.0 / 2015-07-13
|
||||
===================
|
||||
|
||||
* Add `application/x-httpd-php`
|
||||
|
||||
1.14.0 / 2015-06-25
|
||||
===================
|
||||
|
||||
* Add `application/scim+json`
|
||||
* Add `application/vnd.3gpp.ussd+xml`
|
||||
* Add `application/vnd.biopax.rdf+xml`
|
||||
* Add `text/x-processing`
|
||||
|
||||
1.13.0 / 2015-06-07
|
||||
===================
|
||||
|
||||
* Add nginx as a source
|
||||
* Add `application/x-cocoa`
|
||||
* Add `application/x-java-archive-diff`
|
||||
* Add `application/x-makeself`
|
||||
* Add `application/x-perl`
|
||||
* Add `application/x-pilot`
|
||||
* Add `application/x-redhat-package-manager`
|
||||
* Add `application/x-sea`
|
||||
* Add `audio/x-m4a`
|
||||
* Add `audio/x-realaudio`
|
||||
* Add `image/x-jng`
|
||||
* Add `text/mathml`
|
||||
|
||||
1.12.0 / 2015-06-05
|
||||
===================
|
||||
|
||||
* Add `application/bdoc`
|
||||
* Add `application/vnd.hyperdrive+json`
|
||||
* Add `application/x-bdoc`
|
||||
* Add extension `.rtf` to `text/rtf`
|
||||
|
||||
1.11.0 / 2015-05-31
|
||||
===================
|
||||
|
||||
* Add `audio/wav`
|
||||
* Add `audio/wave`
|
||||
* Add extension `.litcoffee` to `text/coffeescript`
|
||||
* Add extension `.sfd-hdstx` to `application/vnd.hydrostatix.sof-data`
|
||||
* Add extension `.n-gage` to `application/vnd.nokia.n-gage.symbian.install`
|
||||
|
||||
1.10.0 / 2015-05-19
|
||||
===================
|
||||
|
||||
* Add `application/vnd.balsamiq.bmpr`
|
||||
* Add `application/vnd.microsoft.portable-executable`
|
||||
* Add `application/x-ns-proxy-autoconfig`
|
||||
|
||||
1.9.1 / 2015-04-19
|
||||
==================
|
||||
|
||||
* Remove `.json` extension from `application/manifest+json`
|
||||
- This is causing bugs downstream
|
||||
|
||||
1.9.0 / 2015-04-19
|
||||
==================
|
||||
|
||||
* Add `application/manifest+json`
|
||||
* Add `application/vnd.micro+json`
|
||||
* Add `image/vnd.zbrush.pcx`
|
||||
* Add `image/x-ms-bmp`
|
||||
|
||||
1.8.0 / 2015-03-13
|
||||
==================
|
||||
|
||||
* Add `application/vnd.citationstyles.style+xml`
|
||||
* Add `application/vnd.fastcopy-disk-image`
|
||||
* Add `application/vnd.gov.sk.xmldatacontainer+xml`
|
||||
* Add extension `.jsonld` to `application/ld+json`
|
||||
|
||||
1.7.0 / 2015-02-08
|
||||
==================
|
||||
|
||||
* Add `application/vnd.gerber`
|
||||
* Add `application/vnd.msa-disk-image`
|
||||
|
||||
1.6.1 / 2015-02-05
|
||||
==================
|
||||
|
||||
* Community extensions ownership transferred from `node-mime`
|
||||
|
||||
1.6.0 / 2015-01-29
|
||||
==================
|
||||
|
||||
* Add `application/jose`
|
||||
* Add `application/jose+json`
|
||||
* Add `application/json-seq`
|
||||
* Add `application/jwk+json`
|
||||
* Add `application/jwk-set+json`
|
||||
* Add `application/jwt`
|
||||
* Add `application/rdap+json`
|
||||
* Add `application/vnd.gov.sk.e-form+xml`
|
||||
* Add `application/vnd.ims.imsccv1p3`
|
||||
|
||||
1.5.0 / 2014-12-30
|
||||
==================
|
||||
|
||||
* Add `application/vnd.oracle.resource+json`
|
||||
* Fix various invalid MIME type entries
|
||||
- `application/mbox+xml`
|
||||
- `application/oscp-response`
|
||||
- `application/vwg-multiplexed`
|
||||
- `audio/g721`
|
||||
|
||||
1.4.0 / 2014-12-21
|
||||
==================
|
||||
|
||||
* Add `application/vnd.ims.imsccv1p2`
|
||||
* Fix various invalid MIME type entries
|
||||
- `application/vnd-acucobol`
|
||||
- `application/vnd-curl`
|
||||
- `application/vnd-dart`
|
||||
- `application/vnd-dxr`
|
||||
- `application/vnd-fdf`
|
||||
- `application/vnd-mif`
|
||||
- `application/vnd-sema`
|
||||
- `application/vnd-wap-wmlc`
|
||||
- `application/vnd.adobe.flash-movie`
|
||||
- `application/vnd.dece-zip`
|
||||
- `application/vnd.dvb_service`
|
||||
- `application/vnd.micrografx-igx`
|
||||
- `application/vnd.sealed-doc`
|
||||
- `application/vnd.sealed-eml`
|
||||
- `application/vnd.sealed-mht`
|
||||
- `application/vnd.sealed-ppt`
|
||||
- `application/vnd.sealed-tiff`
|
||||
- `application/vnd.sealed-xls`
|
||||
- `application/vnd.sealedmedia.softseal-html`
|
||||
- `application/vnd.sealedmedia.softseal-pdf`
|
||||
- `application/vnd.wap-slc`
|
||||
- `application/vnd.wap-wbxml`
|
||||
- `audio/vnd.sealedmedia.softseal-mpeg`
|
||||
- `image/vnd-djvu`
|
||||
- `image/vnd-svf`
|
||||
- `image/vnd-wap-wbmp`
|
||||
- `image/vnd.sealed-png`
|
||||
- `image/vnd.sealedmedia.softseal-gif`
|
||||
- `image/vnd.sealedmedia.softseal-jpg`
|
||||
- `model/vnd-dwf`
|
||||
- `model/vnd.parasolid.transmit-binary`
|
||||
- `model/vnd.parasolid.transmit-text`
|
||||
- `text/vnd-a`
|
||||
- `text/vnd-curl`
|
||||
- `text/vnd.wap-wml`
|
||||
* Remove example template MIME types
|
||||
- `application/example`
|
||||
- `audio/example`
|
||||
- `image/example`
|
||||
- `message/example`
|
||||
- `model/example`
|
||||
- `multipart/example`
|
||||
- `text/example`
|
||||
- `video/example`
|
||||
|
||||
1.3.1 / 2014-12-16
|
||||
==================
|
||||
|
||||
* Fix missing extensions
|
||||
- `application/json5`
|
||||
- `text/hjson`
|
||||
|
||||
1.3.0 / 2014-12-07
|
||||
==================
|
||||
|
||||
* Add `application/a2l`
|
||||
* Add `application/aml`
|
||||
* Add `application/atfx`
|
||||
* Add `application/atxml`
|
||||
* Add `application/cdfx+xml`
|
||||
* Add `application/dii`
|
||||
* Add `application/json5`
|
||||
* Add `application/lxf`
|
||||
* Add `application/mf4`
|
||||
* Add `application/vnd.apache.thrift.compact`
|
||||
* Add `application/vnd.apache.thrift.json`
|
||||
* Add `application/vnd.coffeescript`
|
||||
* Add `application/vnd.enphase.envoy`
|
||||
* Add `application/vnd.ims.imsccv1p1`
|
||||
* Add `text/csv-schema`
|
||||
* Add `text/hjson`
|
||||
* Add `text/markdown`
|
||||
* Add `text/yaml`
|
||||
|
||||
1.2.0 / 2014-11-09
|
||||
==================
|
||||
|
||||
* Add `application/cea`
|
||||
* Add `application/dit`
|
||||
* Add `application/vnd.gov.sk.e-form+zip`
|
||||
* Add `application/vnd.tmd.mediaflex.api+xml`
|
||||
* Type `application/epub+zip` is now IANA-registered
|
||||
|
||||
1.1.2 / 2014-10-23
|
||||
==================
|
||||
|
||||
* Rebuild database for `application/x-www-form-urlencoded` change
|
||||
|
||||
1.1.1 / 2014-10-20
|
||||
==================
|
||||
|
||||
* Mark `application/x-www-form-urlencoded` as compressible.
|
||||
|
||||
1.1.0 / 2014-09-28
|
||||
==================
|
||||
|
||||
* Add `application/font-woff2`
|
||||
|
||||
1.0.3 / 2014-09-25
|
||||
==================
|
||||
|
||||
* Fix engine requirement in package
|
||||
|
||||
1.0.2 / 2014-09-25
|
||||
==================
|
||||
|
||||
* Add `application/coap-group+json`
|
||||
* Add `application/dcd`
|
||||
* Add `application/vnd.apache.thrift.binary`
|
||||
* Add `image/vnd.tencent.tap`
|
||||
* Mark all JSON-derived types as compressible
|
||||
* Update `text/vtt` data
|
||||
|
||||
1.0.1 / 2014-08-30
|
||||
==================
|
||||
|
||||
* Fix extension ordering
|
||||
|
||||
1.0.0 / 2014-08-30
|
||||
==================
|
||||
|
||||
* Add `application/atf`
|
||||
* Add `application/merge-patch+json`
|
||||
* Add `multipart/x-mixed-replace`
|
||||
* Add `source: 'apache'` metadata
|
||||
* Add `source: 'iana'` metadata
|
||||
* Remove badly-assumed charset data
|
||||
23
node_modules/engine.io/node_modules/mime-db/LICENSE
generated
vendored
Normal file
23
node_modules/engine.io/node_modules/mime-db/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
|
||||
Copyright (c) 2015-2022 Douglas Christopher Wilson <doug@somethingdoug.com>
|
||||
|
||||
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.
|
||||
100
node_modules/engine.io/node_modules/mime-db/README.md
generated
vendored
Normal file
100
node_modules/engine.io/node_modules/mime-db/README.md
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
# mime-db
|
||||
|
||||
[![NPM Version][npm-version-image]][npm-url]
|
||||
[![NPM Downloads][npm-downloads-image]][npm-url]
|
||||
[![Node.js Version][node-image]][node-url]
|
||||
[![Build Status][ci-image]][ci-url]
|
||||
[![Coverage Status][coveralls-image]][coveralls-url]
|
||||
|
||||
This is a large database of mime types and information about them.
|
||||
It consists of a single, public JSON file and does not include any logic,
|
||||
allowing it to remain as un-opinionated as possible with an API.
|
||||
It aggregates data from the following sources:
|
||||
|
||||
- http://www.iana.org/assignments/media-types/media-types.xhtml
|
||||
- http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
|
||||
- http://hg.nginx.org/nginx/raw-file/default/conf/mime.types
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install mime-db
|
||||
```
|
||||
|
||||
### Database Download
|
||||
|
||||
If you're crazy enough to use this in the browser, you can just grab the
|
||||
JSON file using [jsDelivr](https://www.jsdelivr.com/). It is recommended to
|
||||
replace `master` with [a release tag](https://github.com/jshttp/mime-db/tags)
|
||||
as the JSON format may change in the future.
|
||||
|
||||
```
|
||||
https://cdn.jsdelivr.net/gh/jshttp/mime-db@master/db.json
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var db = require('mime-db')
|
||||
|
||||
// grab data on .js files
|
||||
var data = db['application/javascript']
|
||||
```
|
||||
|
||||
## Data Structure
|
||||
|
||||
The JSON file is a map lookup for lowercased mime types.
|
||||
Each mime type has the following properties:
|
||||
|
||||
- `.source` - where the mime type is defined.
|
||||
If not set, it's probably a custom media type.
|
||||
- `apache` - [Apache common media types](http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types)
|
||||
- `iana` - [IANA-defined media types](http://www.iana.org/assignments/media-types/media-types.xhtml)
|
||||
- `nginx` - [nginx media types](http://hg.nginx.org/nginx/raw-file/default/conf/mime.types)
|
||||
- `.extensions[]` - known extensions associated with this mime type.
|
||||
- `.compressible` - whether a file of this type can be gzipped.
|
||||
- `.charset` - the default charset associated with this type, if any.
|
||||
|
||||
If unknown, every property could be `undefined`.
|
||||
|
||||
## Contributing
|
||||
|
||||
To edit the database, only make PRs against `src/custom-types.json` or
|
||||
`src/custom-suffix.json`.
|
||||
|
||||
The `src/custom-types.json` file is a JSON object with the MIME type as the
|
||||
keys and the values being an object with the following keys:
|
||||
|
||||
- `compressible` - leave out if you don't know, otherwise `true`/`false` to
|
||||
indicate whether the data represented by the type is typically compressible.
|
||||
- `extensions` - include an array of file extensions that are associated with
|
||||
the type.
|
||||
- `notes` - human-readable notes about the type, typically what the type is.
|
||||
- `sources` - include an array of URLs of where the MIME type and the associated
|
||||
extensions are sourced from. This needs to be a [primary source](https://en.wikipedia.org/wiki/Primary_source);
|
||||
links to type aggregating sites and Wikipedia are _not acceptable_.
|
||||
|
||||
To update the build, run `npm run build`.
|
||||
|
||||
### Adding Custom Media Types
|
||||
|
||||
The best way to get new media types included in this library is to register
|
||||
them with the IANA. The community registration procedure is outlined in
|
||||
[RFC 6838 section 5](http://tools.ietf.org/html/rfc6838#section-5). Types
|
||||
registered with the IANA are automatically pulled into this library.
|
||||
|
||||
If that is not possible / feasible, they can be added directly here as a
|
||||
"custom" type. To do this, it is required to have a primary source that
|
||||
definitively lists the media type. If an extension is going to be listed as
|
||||
associateed with this media type, the source must definitively link the
|
||||
media type and extension as well.
|
||||
|
||||
[ci-image]: https://badgen.net/github/checks/jshttp/mime-db/master?label=ci
|
||||
[ci-url]: https://github.com/jshttp/mime-db/actions?query=workflow%3Aci
|
||||
[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/mime-db/master
|
||||
[coveralls-url]: https://coveralls.io/r/jshttp/mime-db?branch=master
|
||||
[node-image]: https://badgen.net/npm/node/mime-db
|
||||
[node-url]: https://nodejs.org/en/download
|
||||
[npm-downloads-image]: https://badgen.net/npm/dm/mime-db
|
||||
[npm-url]: https://npmjs.org/package/mime-db
|
||||
[npm-version-image]: https://badgen.net/npm/v/mime-db
|
||||
8519
node_modules/engine.io/node_modules/mime-db/db.json
generated
vendored
Normal file
8519
node_modules/engine.io/node_modules/mime-db/db.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12
node_modules/engine.io/node_modules/mime-db/index.js
generated
vendored
Normal file
12
node_modules/engine.io/node_modules/mime-db/index.js
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
/*!
|
||||
* mime-db
|
||||
* Copyright(c) 2014 Jonathan Ong
|
||||
* Copyright(c) 2015-2022 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
*/
|
||||
|
||||
module.exports = require('./db.json')
|
||||
60
node_modules/engine.io/node_modules/mime-db/package.json
generated
vendored
Normal file
60
node_modules/engine.io/node_modules/mime-db/package.json
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"name": "mime-db",
|
||||
"description": "Media Type Database",
|
||||
"version": "1.52.0",
|
||||
"contributors": [
|
||||
"Douglas Christopher Wilson <doug@somethingdoug.com>",
|
||||
"Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)",
|
||||
"Robert Kieffer <robert@broofa.com> (http://github.com/broofa)"
|
||||
],
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"mime",
|
||||
"db",
|
||||
"type",
|
||||
"types",
|
||||
"database",
|
||||
"charset",
|
||||
"charsets"
|
||||
],
|
||||
"repository": "jshttp/mime-db",
|
||||
"devDependencies": {
|
||||
"bluebird": "3.7.2",
|
||||
"co": "4.6.0",
|
||||
"cogent": "1.0.1",
|
||||
"csv-parse": "4.16.3",
|
||||
"eslint": "7.32.0",
|
||||
"eslint-config-standard": "15.0.1",
|
||||
"eslint-plugin-import": "2.25.4",
|
||||
"eslint-plugin-markdown": "2.2.1",
|
||||
"eslint-plugin-node": "11.1.0",
|
||||
"eslint-plugin-promise": "5.1.1",
|
||||
"eslint-plugin-standard": "4.1.0",
|
||||
"gnode": "0.1.2",
|
||||
"media-typer": "1.1.0",
|
||||
"mocha": "9.2.1",
|
||||
"nyc": "15.1.0",
|
||||
"raw-body": "2.5.0",
|
||||
"stream-to-array": "2.3.0"
|
||||
},
|
||||
"files": [
|
||||
"HISTORY.md",
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"db.json",
|
||||
"index.js"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "node scripts/build",
|
||||
"fetch": "node scripts/fetch-apache && gnode scripts/fetch-iana && node scripts/fetch-nginx",
|
||||
"lint": "eslint .",
|
||||
"test": "mocha --reporter spec --bail --check-leaks test/",
|
||||
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
|
||||
"test-cov": "nyc --reporter=html --reporter=text npm test",
|
||||
"update": "npm run fetch && npm run build",
|
||||
"version": "node scripts/version-history.js && git add HISTORY.md"
|
||||
}
|
||||
}
|
||||
397
node_modules/engine.io/node_modules/mime-types/HISTORY.md
generated
vendored
Normal file
397
node_modules/engine.io/node_modules/mime-types/HISTORY.md
generated
vendored
Normal file
@@ -0,0 +1,397 @@
|
||||
2.1.35 / 2022-03-12
|
||||
===================
|
||||
|
||||
* deps: mime-db@1.52.0
|
||||
- Add extensions from IANA for more `image/*` types
|
||||
- Add extension `.asc` to `application/pgp-keys`
|
||||
- Add extensions to various XML types
|
||||
- Add new upstream MIME types
|
||||
|
||||
2.1.34 / 2021-11-08
|
||||
===================
|
||||
|
||||
* deps: mime-db@1.51.0
|
||||
- Add new upstream MIME types
|
||||
|
||||
2.1.33 / 2021-10-01
|
||||
===================
|
||||
|
||||
* deps: mime-db@1.50.0
|
||||
- Add deprecated iWorks mime types and extensions
|
||||
- Add new upstream MIME types
|
||||
|
||||
2.1.32 / 2021-07-27
|
||||
===================
|
||||
|
||||
* deps: mime-db@1.49.0
|
||||
- Add extension `.trig` to `application/trig`
|
||||
- Add new upstream MIME types
|
||||
|
||||
2.1.31 / 2021-06-01
|
||||
===================
|
||||
|
||||
* deps: mime-db@1.48.0
|
||||
- Add extension `.mvt` to `application/vnd.mapbox-vector-tile`
|
||||
- Add new upstream MIME types
|
||||
|
||||
2.1.30 / 2021-04-02
|
||||
===================
|
||||
|
||||
* deps: mime-db@1.47.0
|
||||
- Add extension `.amr` to `audio/amr`
|
||||
- Remove ambigious extensions from IANA for `application/*+xml` types
|
||||
- Update primary extension to `.es` for `application/ecmascript`
|
||||
|
||||
2.1.29 / 2021-02-17
|
||||
===================
|
||||
|
||||
* deps: mime-db@1.46.0
|
||||
- Add extension `.amr` to `audio/amr`
|
||||
- Add extension `.m4s` to `video/iso.segment`
|
||||
- Add extension `.opus` to `audio/ogg`
|
||||
- Add new upstream MIME types
|
||||
|
||||
2.1.28 / 2021-01-01
|
||||
===================
|
||||
|
||||
* deps: mime-db@1.45.0
|
||||
- Add `application/ubjson` with extension `.ubj`
|
||||
- Add `image/avif` with extension `.avif`
|
||||
- Add `image/ktx2` with extension `.ktx2`
|
||||
- Add extension `.dbf` to `application/vnd.dbf`
|
||||
- Add extension `.rar` to `application/vnd.rar`
|
||||
- Add extension `.td` to `application/urc-targetdesc+xml`
|
||||
- Add new upstream MIME types
|
||||
- Fix extension of `application/vnd.apple.keynote` to be `.key`
|
||||
|
||||
2.1.27 / 2020-04-23
|
||||
===================
|
||||
|
||||
* deps: mime-db@1.44.0
|
||||
- Add charsets from IANA
|
||||
- Add extension `.cjs` to `application/node`
|
||||
- Add new upstream MIME types
|
||||
|
||||
2.1.26 / 2020-01-05
|
||||
===================
|
||||
|
||||
* deps: mime-db@1.43.0
|
||||
- Add `application/x-keepass2` with extension `.kdbx`
|
||||
- Add extension `.mxmf` to `audio/mobile-xmf`
|
||||
- Add extensions from IANA for `application/*+xml` types
|
||||
- Add new upstream MIME types
|
||||
|
||||
2.1.25 / 2019-11-12
|
||||
===================
|
||||
|
||||
* deps: mime-db@1.42.0
|
||||
- Add new upstream MIME types
|
||||
- Add `application/toml` with extension `.toml`
|
||||
- Add `image/vnd.ms-dds` with extension `.dds`
|
||||
|
||||
2.1.24 / 2019-04-20
|
||||
===================
|
||||
|
||||
* deps: mime-db@1.40.0
|
||||
- Add extensions from IANA for `model/*` types
|
||||
- Add `text/mdx` with extension `.mdx`
|
||||
|
||||
2.1.23 / 2019-04-17
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.39.0
|
||||
- Add extensions `.siv` and `.sieve` to `application/sieve`
|
||||
- Add new upstream MIME types
|
||||
|
||||
2.1.22 / 2019-02-14
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.38.0
|
||||
- Add extension `.nq` to `application/n-quads`
|
||||
- Add extension `.nt` to `application/n-triples`
|
||||
- Add new upstream MIME types
|
||||
|
||||
2.1.21 / 2018-10-19
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.37.0
|
||||
- Add extensions to HEIC image types
|
||||
- Add new upstream MIME types
|
||||
|
||||
2.1.20 / 2018-08-26
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.36.0
|
||||
- Add Apple file extensions from IANA
|
||||
- Add extensions from IANA for `image/*` types
|
||||
- Add new upstream MIME types
|
||||
|
||||
2.1.19 / 2018-07-17
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.35.0
|
||||
- Add extension `.csl` to `application/vnd.citationstyles.style+xml`
|
||||
- Add extension `.es` to `application/ecmascript`
|
||||
- Add extension `.owl` to `application/rdf+xml`
|
||||
- Add new upstream MIME types
|
||||
- Add UTF-8 as default charset for `text/turtle`
|
||||
|
||||
2.1.18 / 2018-02-16
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.33.0
|
||||
- Add `application/raml+yaml` with extension `.raml`
|
||||
- Add `application/wasm` with extension `.wasm`
|
||||
- Add `text/shex` with extension `.shex`
|
||||
- Add extensions for JPEG-2000 images
|
||||
- Add extensions from IANA for `message/*` types
|
||||
- Add new upstream MIME types
|
||||
- Update font MIME types
|
||||
- Update `text/hjson` to registered `application/hjson`
|
||||
|
||||
2.1.17 / 2017-09-01
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.30.0
|
||||
- Add `application/vnd.ms-outlook`
|
||||
- Add `application/x-arj`
|
||||
- Add extension `.mjs` to `application/javascript`
|
||||
- Add glTF types and extensions
|
||||
- Add new upstream MIME types
|
||||
- Add `text/x-org`
|
||||
- Add VirtualBox MIME types
|
||||
- Fix `source` records for `video/*` types that are IANA
|
||||
- Update `font/opentype` to registered `font/otf`
|
||||
|
||||
2.1.16 / 2017-07-24
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.29.0
|
||||
- Add `application/fido.trusted-apps+json`
|
||||
- Add extension `.wadl` to `application/vnd.sun.wadl+xml`
|
||||
- Add extension `.gz` to `application/gzip`
|
||||
- Add new upstream MIME types
|
||||
- Update extensions `.md` and `.markdown` to be `text/markdown`
|
||||
|
||||
2.1.15 / 2017-03-23
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.27.0
|
||||
- Add new mime types
|
||||
- Add `image/apng`
|
||||
|
||||
2.1.14 / 2017-01-14
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.26.0
|
||||
- Add new mime types
|
||||
|
||||
2.1.13 / 2016-11-18
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.25.0
|
||||
- Add new mime types
|
||||
|
||||
2.1.12 / 2016-09-18
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.24.0
|
||||
- Add new mime types
|
||||
- Add `audio/mp3`
|
||||
|
||||
2.1.11 / 2016-05-01
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.23.0
|
||||
- Add new mime types
|
||||
|
||||
2.1.10 / 2016-02-15
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.22.0
|
||||
- Add new mime types
|
||||
- Fix extension of `application/dash+xml`
|
||||
- Update primary extension for `audio/mp4`
|
||||
|
||||
2.1.9 / 2016-01-06
|
||||
==================
|
||||
|
||||
* deps: mime-db@~1.21.0
|
||||
- Add new mime types
|
||||
|
||||
2.1.8 / 2015-11-30
|
||||
==================
|
||||
|
||||
* deps: mime-db@~1.20.0
|
||||
- Add new mime types
|
||||
|
||||
2.1.7 / 2015-09-20
|
||||
==================
|
||||
|
||||
* deps: mime-db@~1.19.0
|
||||
- Add new mime types
|
||||
|
||||
2.1.6 / 2015-09-03
|
||||
==================
|
||||
|
||||
* deps: mime-db@~1.18.0
|
||||
- Add new mime types
|
||||
|
||||
2.1.5 / 2015-08-20
|
||||
==================
|
||||
|
||||
* deps: mime-db@~1.17.0
|
||||
- Add new mime types
|
||||
|
||||
2.1.4 / 2015-07-30
|
||||
==================
|
||||
|
||||
* deps: mime-db@~1.16.0
|
||||
- Add new mime types
|
||||
|
||||
2.1.3 / 2015-07-13
|
||||
==================
|
||||
|
||||
* deps: mime-db@~1.15.0
|
||||
- Add new mime types
|
||||
|
||||
2.1.2 / 2015-06-25
|
||||
==================
|
||||
|
||||
* deps: mime-db@~1.14.0
|
||||
- Add new mime types
|
||||
|
||||
2.1.1 / 2015-06-08
|
||||
==================
|
||||
|
||||
* perf: fix deopt during mapping
|
||||
|
||||
2.1.0 / 2015-06-07
|
||||
==================
|
||||
|
||||
* Fix incorrectly treating extension-less file name as extension
|
||||
- i.e. `'path/to/json'` will no longer return `application/json`
|
||||
* Fix `.charset(type)` to accept parameters
|
||||
* Fix `.charset(type)` to match case-insensitive
|
||||
* Improve generation of extension to MIME mapping
|
||||
* Refactor internals for readability and no argument reassignment
|
||||
* Prefer `application/*` MIME types from the same source
|
||||
* Prefer any type over `application/octet-stream`
|
||||
* deps: mime-db@~1.13.0
|
||||
- Add nginx as a source
|
||||
- Add new mime types
|
||||
|
||||
2.0.14 / 2015-06-06
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.12.0
|
||||
- Add new mime types
|
||||
|
||||
2.0.13 / 2015-05-31
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.11.0
|
||||
- Add new mime types
|
||||
|
||||
2.0.12 / 2015-05-19
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.10.0
|
||||
- Add new mime types
|
||||
|
||||
2.0.11 / 2015-05-05
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.9.1
|
||||
- Add new mime types
|
||||
|
||||
2.0.10 / 2015-03-13
|
||||
===================
|
||||
|
||||
* deps: mime-db@~1.8.0
|
||||
- Add new mime types
|
||||
|
||||
2.0.9 / 2015-02-09
|
||||
==================
|
||||
|
||||
* deps: mime-db@~1.7.0
|
||||
- Add new mime types
|
||||
- Community extensions ownership transferred from `node-mime`
|
||||
|
||||
2.0.8 / 2015-01-29
|
||||
==================
|
||||
|
||||
* deps: mime-db@~1.6.0
|
||||
- Add new mime types
|
||||
|
||||
2.0.7 / 2014-12-30
|
||||
==================
|
||||
|
||||
* deps: mime-db@~1.5.0
|
||||
- Add new mime types
|
||||
- Fix various invalid MIME type entries
|
||||
|
||||
2.0.6 / 2014-12-30
|
||||
==================
|
||||
|
||||
* deps: mime-db@~1.4.0
|
||||
- Add new mime types
|
||||
- Fix various invalid MIME type entries
|
||||
- Remove example template MIME types
|
||||
|
||||
2.0.5 / 2014-12-29
|
||||
==================
|
||||
|
||||
* deps: mime-db@~1.3.1
|
||||
- Fix missing extensions
|
||||
|
||||
2.0.4 / 2014-12-10
|
||||
==================
|
||||
|
||||
* deps: mime-db@~1.3.0
|
||||
- Add new mime types
|
||||
|
||||
2.0.3 / 2014-11-09
|
||||
==================
|
||||
|
||||
* deps: mime-db@~1.2.0
|
||||
- Add new mime types
|
||||
|
||||
2.0.2 / 2014-09-28
|
||||
==================
|
||||
|
||||
* deps: mime-db@~1.1.0
|
||||
- Add new mime types
|
||||
- Update charsets
|
||||
|
||||
2.0.1 / 2014-09-07
|
||||
==================
|
||||
|
||||
* Support Node.js 0.6
|
||||
|
||||
2.0.0 / 2014-09-02
|
||||
==================
|
||||
|
||||
* Use `mime-db`
|
||||
* Remove `.define()`
|
||||
|
||||
1.0.2 / 2014-08-04
|
||||
==================
|
||||
|
||||
* Set charset=utf-8 for `text/javascript`
|
||||
|
||||
1.0.1 / 2014-06-24
|
||||
==================
|
||||
|
||||
* Add `text/jsx` type
|
||||
|
||||
1.0.0 / 2014-05-12
|
||||
==================
|
||||
|
||||
* Return `false` for unknown types
|
||||
* Set charset=utf-8 for `application/json`
|
||||
|
||||
0.1.0 / 2014-05-02
|
||||
==================
|
||||
|
||||
* Initial release
|
||||
23
node_modules/engine.io/node_modules/mime-types/LICENSE
generated
vendored
Normal file
23
node_modules/engine.io/node_modules/mime-types/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
|
||||
Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>
|
||||
|
||||
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.
|
||||
113
node_modules/engine.io/node_modules/mime-types/README.md
generated
vendored
Normal file
113
node_modules/engine.io/node_modules/mime-types/README.md
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
# mime-types
|
||||
|
||||
[![NPM Version][npm-version-image]][npm-url]
|
||||
[![NPM Downloads][npm-downloads-image]][npm-url]
|
||||
[![Node.js Version][node-version-image]][node-version-url]
|
||||
[![Build Status][ci-image]][ci-url]
|
||||
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||
|
||||
The ultimate javascript content-type utility.
|
||||
|
||||
Similar to [the `mime@1.x` module](https://www.npmjs.com/package/mime), except:
|
||||
|
||||
- __No fallbacks.__ Instead of naively returning the first available type,
|
||||
`mime-types` simply returns `false`, so do
|
||||
`var type = mime.lookup('unrecognized') || 'application/octet-stream'`.
|
||||
- No `new Mime()` business, so you could do `var lookup = require('mime-types').lookup`.
|
||||
- No `.define()` functionality
|
||||
- Bug fixes for `.lookup(path)`
|
||||
|
||||
Otherwise, the API is compatible with `mime` 1.x.
|
||||
|
||||
## Install
|
||||
|
||||
This is a [Node.js](https://nodejs.org/en/) module available through the
|
||||
[npm registry](https://www.npmjs.com/). Installation is done using the
|
||||
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
|
||||
|
||||
```sh
|
||||
$ npm install mime-types
|
||||
```
|
||||
|
||||
## Adding Types
|
||||
|
||||
All mime types are based on [mime-db](https://www.npmjs.com/package/mime-db),
|
||||
so open a PR there if you'd like to add mime types.
|
||||
|
||||
## API
|
||||
|
||||
```js
|
||||
var mime = require('mime-types')
|
||||
```
|
||||
|
||||
All functions return `false` if input is invalid or not found.
|
||||
|
||||
### mime.lookup(path)
|
||||
|
||||
Lookup the content-type associated with a file.
|
||||
|
||||
```js
|
||||
mime.lookup('json') // 'application/json'
|
||||
mime.lookup('.md') // 'text/markdown'
|
||||
mime.lookup('file.html') // 'text/html'
|
||||
mime.lookup('folder/file.js') // 'application/javascript'
|
||||
mime.lookup('folder/.htaccess') // false
|
||||
|
||||
mime.lookup('cats') // false
|
||||
```
|
||||
|
||||
### mime.contentType(type)
|
||||
|
||||
Create a full content-type header given a content-type or extension.
|
||||
When given an extension, `mime.lookup` is used to get the matching
|
||||
content-type, otherwise the given content-type is used. Then if the
|
||||
content-type does not already have a `charset` parameter, `mime.charset`
|
||||
is used to get the default charset and add to the returned content-type.
|
||||
|
||||
```js
|
||||
mime.contentType('markdown') // 'text/x-markdown; charset=utf-8'
|
||||
mime.contentType('file.json') // 'application/json; charset=utf-8'
|
||||
mime.contentType('text/html') // 'text/html; charset=utf-8'
|
||||
mime.contentType('text/html; charset=iso-8859-1') // 'text/html; charset=iso-8859-1'
|
||||
|
||||
// from a full path
|
||||
mime.contentType(path.extname('/path/to/file.json')) // 'application/json; charset=utf-8'
|
||||
```
|
||||
|
||||
### mime.extension(type)
|
||||
|
||||
Get the default extension for a content-type.
|
||||
|
||||
```js
|
||||
mime.extension('application/octet-stream') // 'bin'
|
||||
```
|
||||
|
||||
### mime.charset(type)
|
||||
|
||||
Lookup the implied default charset of a content-type.
|
||||
|
||||
```js
|
||||
mime.charset('text/markdown') // 'UTF-8'
|
||||
```
|
||||
|
||||
### var type = mime.types[extension]
|
||||
|
||||
A map of content-types by extension.
|
||||
|
||||
### [extensions...] = mime.extensions[type]
|
||||
|
||||
A map of extensions by content-type.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
[ci-image]: https://badgen.net/github/checks/jshttp/mime-types/master?label=ci
|
||||
[ci-url]: https://github.com/jshttp/mime-types/actions/workflows/ci.yml
|
||||
[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/mime-types/master
|
||||
[coveralls-url]: https://coveralls.io/r/jshttp/mime-types?branch=master
|
||||
[node-version-image]: https://badgen.net/npm/node/mime-types
|
||||
[node-version-url]: https://nodejs.org/en/download
|
||||
[npm-downloads-image]: https://badgen.net/npm/dm/mime-types
|
||||
[npm-url]: https://npmjs.org/package/mime-types
|
||||
[npm-version-image]: https://badgen.net/npm/v/mime-types
|
||||
188
node_modules/engine.io/node_modules/mime-types/index.js
generated
vendored
Normal file
188
node_modules/engine.io/node_modules/mime-types/index.js
generated
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
/*!
|
||||
* mime-types
|
||||
* Copyright(c) 2014 Jonathan Ong
|
||||
* Copyright(c) 2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var db = require('mime-db')
|
||||
var extname = require('path').extname
|
||||
|
||||
/**
|
||||
* Module variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var EXTRACT_TYPE_REGEXP = /^\s*([^;\s]*)(?:;|\s|$)/
|
||||
var TEXT_TYPE_REGEXP = /^text\//i
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
exports.charset = charset
|
||||
exports.charsets = { lookup: charset }
|
||||
exports.contentType = contentType
|
||||
exports.extension = extension
|
||||
exports.extensions = Object.create(null)
|
||||
exports.lookup = lookup
|
||||
exports.types = Object.create(null)
|
||||
|
||||
// Populate the extensions/types maps
|
||||
populateMaps(exports.extensions, exports.types)
|
||||
|
||||
/**
|
||||
* Get the default charset for a MIME type.
|
||||
*
|
||||
* @param {string} type
|
||||
* @return {boolean|string}
|
||||
*/
|
||||
|
||||
function charset (type) {
|
||||
if (!type || typeof type !== 'string') {
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO: use media-typer
|
||||
var match = EXTRACT_TYPE_REGEXP.exec(type)
|
||||
var mime = match && db[match[1].toLowerCase()]
|
||||
|
||||
if (mime && mime.charset) {
|
||||
return mime.charset
|
||||
}
|
||||
|
||||
// default text/* to utf-8
|
||||
if (match && TEXT_TYPE_REGEXP.test(match[1])) {
|
||||
return 'UTF-8'
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a full Content-Type header given a MIME type or extension.
|
||||
*
|
||||
* @param {string} str
|
||||
* @return {boolean|string}
|
||||
*/
|
||||
|
||||
function contentType (str) {
|
||||
// TODO: should this even be in this module?
|
||||
if (!str || typeof str !== 'string') {
|
||||
return false
|
||||
}
|
||||
|
||||
var mime = str.indexOf('/') === -1
|
||||
? exports.lookup(str)
|
||||
: str
|
||||
|
||||
if (!mime) {
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO: use content-type or other module
|
||||
if (mime.indexOf('charset') === -1) {
|
||||
var charset = exports.charset(mime)
|
||||
if (charset) mime += '; charset=' + charset.toLowerCase()
|
||||
}
|
||||
|
||||
return mime
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default extension for a MIME type.
|
||||
*
|
||||
* @param {string} type
|
||||
* @return {boolean|string}
|
||||
*/
|
||||
|
||||
function extension (type) {
|
||||
if (!type || typeof type !== 'string') {
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO: use media-typer
|
||||
var match = EXTRACT_TYPE_REGEXP.exec(type)
|
||||
|
||||
// get extensions
|
||||
var exts = match && exports.extensions[match[1].toLowerCase()]
|
||||
|
||||
if (!exts || !exts.length) {
|
||||
return false
|
||||
}
|
||||
|
||||
return exts[0]
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the MIME type for a file path/extension.
|
||||
*
|
||||
* @param {string} path
|
||||
* @return {boolean|string}
|
||||
*/
|
||||
|
||||
function lookup (path) {
|
||||
if (!path || typeof path !== 'string') {
|
||||
return false
|
||||
}
|
||||
|
||||
// get the extension ("ext" or ".ext" or full path)
|
||||
var extension = extname('x.' + path)
|
||||
.toLowerCase()
|
||||
.substr(1)
|
||||
|
||||
if (!extension) {
|
||||
return false
|
||||
}
|
||||
|
||||
return exports.types[extension] || false
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the extensions and types maps.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function populateMaps (extensions, types) {
|
||||
// source preference (least -> most)
|
||||
var preference = ['nginx', 'apache', undefined, 'iana']
|
||||
|
||||
Object.keys(db).forEach(function forEachMimeType (type) {
|
||||
var mime = db[type]
|
||||
var exts = mime.extensions
|
||||
|
||||
if (!exts || !exts.length) {
|
||||
return
|
||||
}
|
||||
|
||||
// mime -> extensions
|
||||
extensions[type] = exts
|
||||
|
||||
// extension -> mime
|
||||
for (var i = 0; i < exts.length; i++) {
|
||||
var extension = exts[i]
|
||||
|
||||
if (types[extension]) {
|
||||
var from = preference.indexOf(db[types[extension]].source)
|
||||
var to = preference.indexOf(mime.source)
|
||||
|
||||
if (types[extension] !== 'application/octet-stream' &&
|
||||
(from > to || (from === to && types[extension].substr(0, 12) === 'application/'))) {
|
||||
// skip the remapping
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// set the extension -> mime
|
||||
types[extension] = type
|
||||
}
|
||||
})
|
||||
}
|
||||
44
node_modules/engine.io/node_modules/mime-types/package.json
generated
vendored
Normal file
44
node_modules/engine.io/node_modules/mime-types/package.json
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "mime-types",
|
||||
"description": "The ultimate javascript content-type utility.",
|
||||
"version": "2.1.35",
|
||||
"contributors": [
|
||||
"Douglas Christopher Wilson <doug@somethingdoug.com>",
|
||||
"Jeremiah Senkpiel <fishrock123@rocketmail.com> (https://searchbeam.jit.su)",
|
||||
"Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)"
|
||||
],
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"mime",
|
||||
"types"
|
||||
],
|
||||
"repository": "jshttp/mime-types",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "7.32.0",
|
||||
"eslint-config-standard": "14.1.1",
|
||||
"eslint-plugin-import": "2.25.4",
|
||||
"eslint-plugin-markdown": "2.2.1",
|
||||
"eslint-plugin-node": "11.1.0",
|
||||
"eslint-plugin-promise": "5.2.0",
|
||||
"eslint-plugin-standard": "4.1.0",
|
||||
"mocha": "9.2.2",
|
||||
"nyc": "15.1.0"
|
||||
},
|
||||
"files": [
|
||||
"HISTORY.md",
|
||||
"LICENSE",
|
||||
"index.js"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"test": "mocha --reporter spec test/test.js",
|
||||
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
|
||||
"test-cov": "nyc --reporter=html --reporter=text npm test"
|
||||
}
|
||||
}
|
||||
108
node_modules/engine.io/node_modules/negotiator/HISTORY.md
generated
vendored
Normal file
108
node_modules/engine.io/node_modules/negotiator/HISTORY.md
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
0.6.3 / 2022-01-22
|
||||
==================
|
||||
|
||||
* Revert "Lazy-load modules from main entry point"
|
||||
|
||||
0.6.2 / 2019-04-29
|
||||
==================
|
||||
|
||||
* Fix sorting charset, encoding, and language with extra parameters
|
||||
|
||||
0.6.1 / 2016-05-02
|
||||
==================
|
||||
|
||||
* perf: improve `Accept` parsing speed
|
||||
* perf: improve `Accept-Charset` parsing speed
|
||||
* perf: improve `Accept-Encoding` parsing speed
|
||||
* perf: improve `Accept-Language` parsing speed
|
||||
|
||||
0.6.0 / 2015-09-29
|
||||
==================
|
||||
|
||||
* Fix including type extensions in parameters in `Accept` parsing
|
||||
* Fix parsing `Accept` parameters with quoted equals
|
||||
* Fix parsing `Accept` parameters with quoted semicolons
|
||||
* Lazy-load modules from main entry point
|
||||
* perf: delay type concatenation until needed
|
||||
* perf: enable strict mode
|
||||
* perf: hoist regular expressions
|
||||
* perf: remove closures getting spec properties
|
||||
* perf: remove a closure from media type parsing
|
||||
* perf: remove property delete from media type parsing
|
||||
|
||||
0.5.3 / 2015-05-10
|
||||
==================
|
||||
|
||||
* Fix media type parameter matching to be case-insensitive
|
||||
|
||||
0.5.2 / 2015-05-06
|
||||
==================
|
||||
|
||||
* Fix comparing media types with quoted values
|
||||
* Fix splitting media types with quoted commas
|
||||
|
||||
0.5.1 / 2015-02-14
|
||||
==================
|
||||
|
||||
* Fix preference sorting to be stable for long acceptable lists
|
||||
|
||||
0.5.0 / 2014-12-18
|
||||
==================
|
||||
|
||||
* Fix list return order when large accepted list
|
||||
* Fix missing identity encoding when q=0 exists
|
||||
* Remove dynamic building of Negotiator class
|
||||
|
||||
0.4.9 / 2014-10-14
|
||||
==================
|
||||
|
||||
* Fix error when media type has invalid parameter
|
||||
|
||||
0.4.8 / 2014-09-28
|
||||
==================
|
||||
|
||||
* Fix all negotiations to be case-insensitive
|
||||
* Stable sort preferences of same quality according to client order
|
||||
* Support Node.js 0.6
|
||||
|
||||
0.4.7 / 2014-06-24
|
||||
==================
|
||||
|
||||
* Handle invalid provided languages
|
||||
* Handle invalid provided media types
|
||||
|
||||
0.4.6 / 2014-06-11
|
||||
==================
|
||||
|
||||
* Order by specificity when quality is the same
|
||||
|
||||
0.4.5 / 2014-05-29
|
||||
==================
|
||||
|
||||
* Fix regression in empty header handling
|
||||
|
||||
0.4.4 / 2014-05-29
|
||||
==================
|
||||
|
||||
* Fix behaviors when headers are not present
|
||||
|
||||
0.4.3 / 2014-04-16
|
||||
==================
|
||||
|
||||
* Handle slashes on media params correctly
|
||||
|
||||
0.4.2 / 2014-02-28
|
||||
==================
|
||||
|
||||
* Fix media type sorting
|
||||
* Handle media types params strictly
|
||||
|
||||
0.4.1 / 2014-01-16
|
||||
==================
|
||||
|
||||
* Use most specific matches
|
||||
|
||||
0.4.0 / 2014-01-09
|
||||
==================
|
||||
|
||||
* Remove preferred prefix from methods
|
||||
24
node_modules/engine.io/node_modules/negotiator/LICENSE
generated
vendored
Normal file
24
node_modules/engine.io/node_modules/negotiator/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2012-2014 Federico Romero
|
||||
Copyright (c) 2012-2014 Isaac Z. Schlueter
|
||||
Copyright (c) 2014-2015 Douglas Christopher Wilson
|
||||
|
||||
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.
|
||||
203
node_modules/engine.io/node_modules/negotiator/README.md
generated
vendored
Normal file
203
node_modules/engine.io/node_modules/negotiator/README.md
generated
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
# negotiator
|
||||
|
||||
[![NPM Version][npm-image]][npm-url]
|
||||
[![NPM Downloads][downloads-image]][downloads-url]
|
||||
[![Node.js Version][node-version-image]][node-version-url]
|
||||
[![Build Status][github-actions-ci-image]][github-actions-ci-url]
|
||||
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||
|
||||
An HTTP content negotiator for Node.js
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
$ npm install negotiator
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```js
|
||||
var Negotiator = require('negotiator')
|
||||
```
|
||||
|
||||
### Accept Negotiation
|
||||
|
||||
```js
|
||||
availableMediaTypes = ['text/html', 'text/plain', 'application/json']
|
||||
|
||||
// The negotiator constructor receives a request object
|
||||
negotiator = new Negotiator(request)
|
||||
|
||||
// Let's say Accept header is 'text/html, application/*;q=0.2, image/jpeg;q=0.8'
|
||||
|
||||
negotiator.mediaTypes()
|
||||
// -> ['text/html', 'image/jpeg', 'application/*']
|
||||
|
||||
negotiator.mediaTypes(availableMediaTypes)
|
||||
// -> ['text/html', 'application/json']
|
||||
|
||||
negotiator.mediaType(availableMediaTypes)
|
||||
// -> 'text/html'
|
||||
```
|
||||
|
||||
You can check a working example at `examples/accept.js`.
|
||||
|
||||
#### Methods
|
||||
|
||||
##### mediaType()
|
||||
|
||||
Returns the most preferred media type from the client.
|
||||
|
||||
##### mediaType(availableMediaType)
|
||||
|
||||
Returns the most preferred media type from a list of available media types.
|
||||
|
||||
##### mediaTypes()
|
||||
|
||||
Returns an array of preferred media types ordered by the client preference.
|
||||
|
||||
##### mediaTypes(availableMediaTypes)
|
||||
|
||||
Returns an array of preferred media types ordered by priority from a list of
|
||||
available media types.
|
||||
|
||||
### Accept-Language Negotiation
|
||||
|
||||
```js
|
||||
negotiator = new Negotiator(request)
|
||||
|
||||
availableLanguages = ['en', 'es', 'fr']
|
||||
|
||||
// Let's say Accept-Language header is 'en;q=0.8, es, pt'
|
||||
|
||||
negotiator.languages()
|
||||
// -> ['es', 'pt', 'en']
|
||||
|
||||
negotiator.languages(availableLanguages)
|
||||
// -> ['es', 'en']
|
||||
|
||||
language = negotiator.language(availableLanguages)
|
||||
// -> 'es'
|
||||
```
|
||||
|
||||
You can check a working example at `examples/language.js`.
|
||||
|
||||
#### Methods
|
||||
|
||||
##### language()
|
||||
|
||||
Returns the most preferred language from the client.
|
||||
|
||||
##### language(availableLanguages)
|
||||
|
||||
Returns the most preferred language from a list of available languages.
|
||||
|
||||
##### languages()
|
||||
|
||||
Returns an array of preferred languages ordered by the client preference.
|
||||
|
||||
##### languages(availableLanguages)
|
||||
|
||||
Returns an array of preferred languages ordered by priority from a list of
|
||||
available languages.
|
||||
|
||||
### Accept-Charset Negotiation
|
||||
|
||||
```js
|
||||
availableCharsets = ['utf-8', 'iso-8859-1', 'iso-8859-5']
|
||||
|
||||
negotiator = new Negotiator(request)
|
||||
|
||||
// Let's say Accept-Charset header is 'utf-8, iso-8859-1;q=0.8, utf-7;q=0.2'
|
||||
|
||||
negotiator.charsets()
|
||||
// -> ['utf-8', 'iso-8859-1', 'utf-7']
|
||||
|
||||
negotiator.charsets(availableCharsets)
|
||||
// -> ['utf-8', 'iso-8859-1']
|
||||
|
||||
negotiator.charset(availableCharsets)
|
||||
// -> 'utf-8'
|
||||
```
|
||||
|
||||
You can check a working example at `examples/charset.js`.
|
||||
|
||||
#### Methods
|
||||
|
||||
##### charset()
|
||||
|
||||
Returns the most preferred charset from the client.
|
||||
|
||||
##### charset(availableCharsets)
|
||||
|
||||
Returns the most preferred charset from a list of available charsets.
|
||||
|
||||
##### charsets()
|
||||
|
||||
Returns an array of preferred charsets ordered by the client preference.
|
||||
|
||||
##### charsets(availableCharsets)
|
||||
|
||||
Returns an array of preferred charsets ordered by priority from a list of
|
||||
available charsets.
|
||||
|
||||
### Accept-Encoding Negotiation
|
||||
|
||||
```js
|
||||
availableEncodings = ['identity', 'gzip']
|
||||
|
||||
negotiator = new Negotiator(request)
|
||||
|
||||
// Let's say Accept-Encoding header is 'gzip, compress;q=0.2, identity;q=0.5'
|
||||
|
||||
negotiator.encodings()
|
||||
// -> ['gzip', 'identity', 'compress']
|
||||
|
||||
negotiator.encodings(availableEncodings)
|
||||
// -> ['gzip', 'identity']
|
||||
|
||||
negotiator.encoding(availableEncodings)
|
||||
// -> 'gzip'
|
||||
```
|
||||
|
||||
You can check a working example at `examples/encoding.js`.
|
||||
|
||||
#### Methods
|
||||
|
||||
##### encoding()
|
||||
|
||||
Returns the most preferred encoding from the client.
|
||||
|
||||
##### encoding(availableEncodings)
|
||||
|
||||
Returns the most preferred encoding from a list of available encodings.
|
||||
|
||||
##### encodings()
|
||||
|
||||
Returns an array of preferred encodings ordered by the client preference.
|
||||
|
||||
##### encodings(availableEncodings)
|
||||
|
||||
Returns an array of preferred encodings ordered by priority from a list of
|
||||
available encodings.
|
||||
|
||||
## See Also
|
||||
|
||||
The [accepts](https://npmjs.org/package/accepts#readme) module builds on
|
||||
this module and provides an alternative interface, mime type validation,
|
||||
and more.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/negotiator.svg
|
||||
[npm-url]: https://npmjs.org/package/negotiator
|
||||
[node-version-image]: https://img.shields.io/node/v/negotiator.svg
|
||||
[node-version-url]: https://nodejs.org/en/download/
|
||||
[coveralls-image]: https://img.shields.io/coveralls/jshttp/negotiator/master.svg
|
||||
[coveralls-url]: https://coveralls.io/r/jshttp/negotiator?branch=master
|
||||
[downloads-image]: https://img.shields.io/npm/dm/negotiator.svg
|
||||
[downloads-url]: https://npmjs.org/package/negotiator
|
||||
[github-actions-ci-image]: https://img.shields.io/github/workflow/status/jshttp/negotiator/ci/master?label=ci
|
||||
[github-actions-ci-url]: https://github.com/jshttp/negotiator/actions/workflows/ci.yml
|
||||
82
node_modules/engine.io/node_modules/negotiator/index.js
generated
vendored
Normal file
82
node_modules/engine.io/node_modules/negotiator/index.js
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
/*!
|
||||
* negotiator
|
||||
* Copyright(c) 2012 Federico Romero
|
||||
* Copyright(c) 2012-2014 Isaac Z. Schlueter
|
||||
* Copyright(c) 2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var preferredCharsets = require('./lib/charset')
|
||||
var preferredEncodings = require('./lib/encoding')
|
||||
var preferredLanguages = require('./lib/language')
|
||||
var preferredMediaTypes = require('./lib/mediaType')
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = Negotiator;
|
||||
module.exports.Negotiator = Negotiator;
|
||||
|
||||
/**
|
||||
* Create a Negotiator instance from a request.
|
||||
* @param {object} request
|
||||
* @public
|
||||
*/
|
||||
|
||||
function Negotiator(request) {
|
||||
if (!(this instanceof Negotiator)) {
|
||||
return new Negotiator(request);
|
||||
}
|
||||
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
Negotiator.prototype.charset = function charset(available) {
|
||||
var set = this.charsets(available);
|
||||
return set && set[0];
|
||||
};
|
||||
|
||||
Negotiator.prototype.charsets = function charsets(available) {
|
||||
return preferredCharsets(this.request.headers['accept-charset'], available);
|
||||
};
|
||||
|
||||
Negotiator.prototype.encoding = function encoding(available) {
|
||||
var set = this.encodings(available);
|
||||
return set && set[0];
|
||||
};
|
||||
|
||||
Negotiator.prototype.encodings = function encodings(available) {
|
||||
return preferredEncodings(this.request.headers['accept-encoding'], available);
|
||||
};
|
||||
|
||||
Negotiator.prototype.language = function language(available) {
|
||||
var set = this.languages(available);
|
||||
return set && set[0];
|
||||
};
|
||||
|
||||
Negotiator.prototype.languages = function languages(available) {
|
||||
return preferredLanguages(this.request.headers['accept-language'], available);
|
||||
};
|
||||
|
||||
Negotiator.prototype.mediaType = function mediaType(available) {
|
||||
var set = this.mediaTypes(available);
|
||||
return set && set[0];
|
||||
};
|
||||
|
||||
Negotiator.prototype.mediaTypes = function mediaTypes(available) {
|
||||
return preferredMediaTypes(this.request.headers.accept, available);
|
||||
};
|
||||
|
||||
// Backwards compatibility
|
||||
Negotiator.prototype.preferredCharset = Negotiator.prototype.charset;
|
||||
Negotiator.prototype.preferredCharsets = Negotiator.prototype.charsets;
|
||||
Negotiator.prototype.preferredEncoding = Negotiator.prototype.encoding;
|
||||
Negotiator.prototype.preferredEncodings = Negotiator.prototype.encodings;
|
||||
Negotiator.prototype.preferredLanguage = Negotiator.prototype.language;
|
||||
Negotiator.prototype.preferredLanguages = Negotiator.prototype.languages;
|
||||
Negotiator.prototype.preferredMediaType = Negotiator.prototype.mediaType;
|
||||
Negotiator.prototype.preferredMediaTypes = Negotiator.prototype.mediaTypes;
|
||||
169
node_modules/engine.io/node_modules/negotiator/lib/charset.js
generated
vendored
Normal file
169
node_modules/engine.io/node_modules/negotiator/lib/charset.js
generated
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* negotiator
|
||||
* Copyright(c) 2012 Isaac Z. Schlueter
|
||||
* Copyright(c) 2014 Federico Romero
|
||||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = preferredCharsets;
|
||||
module.exports.preferredCharsets = preferredCharsets;
|
||||
|
||||
/**
|
||||
* Module variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var simpleCharsetRegExp = /^\s*([^\s;]+)\s*(?:;(.*))?$/;
|
||||
|
||||
/**
|
||||
* Parse the Accept-Charset header.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function parseAcceptCharset(accept) {
|
||||
var accepts = accept.split(',');
|
||||
|
||||
for (var i = 0, j = 0; i < accepts.length; i++) {
|
||||
var charset = parseCharset(accepts[i].trim(), i);
|
||||
|
||||
if (charset) {
|
||||
accepts[j++] = charset;
|
||||
}
|
||||
}
|
||||
|
||||
// trim accepts
|
||||
accepts.length = j;
|
||||
|
||||
return accepts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a charset from the Accept-Charset header.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function parseCharset(str, i) {
|
||||
var match = simpleCharsetRegExp.exec(str);
|
||||
if (!match) return null;
|
||||
|
||||
var charset = match[1];
|
||||
var q = 1;
|
||||
if (match[2]) {
|
||||
var params = match[2].split(';')
|
||||
for (var j = 0; j < params.length; j++) {
|
||||
var p = params[j].trim().split('=');
|
||||
if (p[0] === 'q') {
|
||||
q = parseFloat(p[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
charset: charset,
|
||||
q: q,
|
||||
i: i
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the priority of a charset.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getCharsetPriority(charset, accepted, index) {
|
||||
var priority = {o: -1, q: 0, s: 0};
|
||||
|
||||
for (var i = 0; i < accepted.length; i++) {
|
||||
var spec = specify(charset, accepted[i], index);
|
||||
|
||||
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
|
||||
priority = spec;
|
||||
}
|
||||
}
|
||||
|
||||
return priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specificity of the charset.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function specify(charset, spec, index) {
|
||||
var s = 0;
|
||||
if(spec.charset.toLowerCase() === charset.toLowerCase()){
|
||||
s |= 1;
|
||||
} else if (spec.charset !== '*' ) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
i: index,
|
||||
o: spec.i,
|
||||
q: spec.q,
|
||||
s: s
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the preferred charsets from an Accept-Charset header.
|
||||
* @public
|
||||
*/
|
||||
|
||||
function preferredCharsets(accept, provided) {
|
||||
// RFC 2616 sec 14.2: no header = *
|
||||
var accepts = parseAcceptCharset(accept === undefined ? '*' : accept || '');
|
||||
|
||||
if (!provided) {
|
||||
// sorted list of all charsets
|
||||
return accepts
|
||||
.filter(isQuality)
|
||||
.sort(compareSpecs)
|
||||
.map(getFullCharset);
|
||||
}
|
||||
|
||||
var priorities = provided.map(function getPriority(type, index) {
|
||||
return getCharsetPriority(type, accepts, index);
|
||||
});
|
||||
|
||||
// sorted list of accepted charsets
|
||||
return priorities.filter(isQuality).sort(compareSpecs).map(function getCharset(priority) {
|
||||
return provided[priorities.indexOf(priority)];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two specs.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function compareSpecs(a, b) {
|
||||
return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full charset string.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getFullCharset(spec) {
|
||||
return spec.charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a spec has any quality.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function isQuality(spec) {
|
||||
return spec.q > 0;
|
||||
}
|
||||
184
node_modules/engine.io/node_modules/negotiator/lib/encoding.js
generated
vendored
Normal file
184
node_modules/engine.io/node_modules/negotiator/lib/encoding.js
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* negotiator
|
||||
* Copyright(c) 2012 Isaac Z. Schlueter
|
||||
* Copyright(c) 2014 Federico Romero
|
||||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = preferredEncodings;
|
||||
module.exports.preferredEncodings = preferredEncodings;
|
||||
|
||||
/**
|
||||
* Module variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var simpleEncodingRegExp = /^\s*([^\s;]+)\s*(?:;(.*))?$/;
|
||||
|
||||
/**
|
||||
* Parse the Accept-Encoding header.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function parseAcceptEncoding(accept) {
|
||||
var accepts = accept.split(',');
|
||||
var hasIdentity = false;
|
||||
var minQuality = 1;
|
||||
|
||||
for (var i = 0, j = 0; i < accepts.length; i++) {
|
||||
var encoding = parseEncoding(accepts[i].trim(), i);
|
||||
|
||||
if (encoding) {
|
||||
accepts[j++] = encoding;
|
||||
hasIdentity = hasIdentity || specify('identity', encoding);
|
||||
minQuality = Math.min(minQuality, encoding.q || 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasIdentity) {
|
||||
/*
|
||||
* If identity doesn't explicitly appear in the accept-encoding header,
|
||||
* it's added to the list of acceptable encoding with the lowest q
|
||||
*/
|
||||
accepts[j++] = {
|
||||
encoding: 'identity',
|
||||
q: minQuality,
|
||||
i: i
|
||||
};
|
||||
}
|
||||
|
||||
// trim accepts
|
||||
accepts.length = j;
|
||||
|
||||
return accepts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an encoding from the Accept-Encoding header.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function parseEncoding(str, i) {
|
||||
var match = simpleEncodingRegExp.exec(str);
|
||||
if (!match) return null;
|
||||
|
||||
var encoding = match[1];
|
||||
var q = 1;
|
||||
if (match[2]) {
|
||||
var params = match[2].split(';');
|
||||
for (var j = 0; j < params.length; j++) {
|
||||
var p = params[j].trim().split('=');
|
||||
if (p[0] === 'q') {
|
||||
q = parseFloat(p[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
encoding: encoding,
|
||||
q: q,
|
||||
i: i
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the priority of an encoding.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getEncodingPriority(encoding, accepted, index) {
|
||||
var priority = {o: -1, q: 0, s: 0};
|
||||
|
||||
for (var i = 0; i < accepted.length; i++) {
|
||||
var spec = specify(encoding, accepted[i], index);
|
||||
|
||||
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
|
||||
priority = spec;
|
||||
}
|
||||
}
|
||||
|
||||
return priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specificity of the encoding.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function specify(encoding, spec, index) {
|
||||
var s = 0;
|
||||
if(spec.encoding.toLowerCase() === encoding.toLowerCase()){
|
||||
s |= 1;
|
||||
} else if (spec.encoding !== '*' ) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
i: index,
|
||||
o: spec.i,
|
||||
q: spec.q,
|
||||
s: s
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the preferred encodings from an Accept-Encoding header.
|
||||
* @public
|
||||
*/
|
||||
|
||||
function preferredEncodings(accept, provided) {
|
||||
var accepts = parseAcceptEncoding(accept || '');
|
||||
|
||||
if (!provided) {
|
||||
// sorted list of all encodings
|
||||
return accepts
|
||||
.filter(isQuality)
|
||||
.sort(compareSpecs)
|
||||
.map(getFullEncoding);
|
||||
}
|
||||
|
||||
var priorities = provided.map(function getPriority(type, index) {
|
||||
return getEncodingPriority(type, accepts, index);
|
||||
});
|
||||
|
||||
// sorted list of accepted encodings
|
||||
return priorities.filter(isQuality).sort(compareSpecs).map(function getEncoding(priority) {
|
||||
return provided[priorities.indexOf(priority)];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two specs.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function compareSpecs(a, b) {
|
||||
return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full encoding string.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getFullEncoding(spec) {
|
||||
return spec.encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a spec has any quality.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function isQuality(spec) {
|
||||
return spec.q > 0;
|
||||
}
|
||||
179
node_modules/engine.io/node_modules/negotiator/lib/language.js
generated
vendored
Normal file
179
node_modules/engine.io/node_modules/negotiator/lib/language.js
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* negotiator
|
||||
* Copyright(c) 2012 Isaac Z. Schlueter
|
||||
* Copyright(c) 2014 Federico Romero
|
||||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = preferredLanguages;
|
||||
module.exports.preferredLanguages = preferredLanguages;
|
||||
|
||||
/**
|
||||
* Module variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var simpleLanguageRegExp = /^\s*([^\s\-;]+)(?:-([^\s;]+))?\s*(?:;(.*))?$/;
|
||||
|
||||
/**
|
||||
* Parse the Accept-Language header.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function parseAcceptLanguage(accept) {
|
||||
var accepts = accept.split(',');
|
||||
|
||||
for (var i = 0, j = 0; i < accepts.length; i++) {
|
||||
var language = parseLanguage(accepts[i].trim(), i);
|
||||
|
||||
if (language) {
|
||||
accepts[j++] = language;
|
||||
}
|
||||
}
|
||||
|
||||
// trim accepts
|
||||
accepts.length = j;
|
||||
|
||||
return accepts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a language from the Accept-Language header.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function parseLanguage(str, i) {
|
||||
var match = simpleLanguageRegExp.exec(str);
|
||||
if (!match) return null;
|
||||
|
||||
var prefix = match[1]
|
||||
var suffix = match[2]
|
||||
var full = prefix
|
||||
|
||||
if (suffix) full += "-" + suffix;
|
||||
|
||||
var q = 1;
|
||||
if (match[3]) {
|
||||
var params = match[3].split(';')
|
||||
for (var j = 0; j < params.length; j++) {
|
||||
var p = params[j].split('=');
|
||||
if (p[0] === 'q') q = parseFloat(p[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
prefix: prefix,
|
||||
suffix: suffix,
|
||||
q: q,
|
||||
i: i,
|
||||
full: full
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the priority of a language.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getLanguagePriority(language, accepted, index) {
|
||||
var priority = {o: -1, q: 0, s: 0};
|
||||
|
||||
for (var i = 0; i < accepted.length; i++) {
|
||||
var spec = specify(language, accepted[i], index);
|
||||
|
||||
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
|
||||
priority = spec;
|
||||
}
|
||||
}
|
||||
|
||||
return priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specificity of the language.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function specify(language, spec, index) {
|
||||
var p = parseLanguage(language)
|
||||
if (!p) return null;
|
||||
var s = 0;
|
||||
if(spec.full.toLowerCase() === p.full.toLowerCase()){
|
||||
s |= 4;
|
||||
} else if (spec.prefix.toLowerCase() === p.full.toLowerCase()) {
|
||||
s |= 2;
|
||||
} else if (spec.full.toLowerCase() === p.prefix.toLowerCase()) {
|
||||
s |= 1;
|
||||
} else if (spec.full !== '*' ) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
i: index,
|
||||
o: spec.i,
|
||||
q: spec.q,
|
||||
s: s
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the preferred languages from an Accept-Language header.
|
||||
* @public
|
||||
*/
|
||||
|
||||
function preferredLanguages(accept, provided) {
|
||||
// RFC 2616 sec 14.4: no header = *
|
||||
var accepts = parseAcceptLanguage(accept === undefined ? '*' : accept || '');
|
||||
|
||||
if (!provided) {
|
||||
// sorted list of all languages
|
||||
return accepts
|
||||
.filter(isQuality)
|
||||
.sort(compareSpecs)
|
||||
.map(getFullLanguage);
|
||||
}
|
||||
|
||||
var priorities = provided.map(function getPriority(type, index) {
|
||||
return getLanguagePriority(type, accepts, index);
|
||||
});
|
||||
|
||||
// sorted list of accepted languages
|
||||
return priorities.filter(isQuality).sort(compareSpecs).map(function getLanguage(priority) {
|
||||
return provided[priorities.indexOf(priority)];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two specs.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function compareSpecs(a, b) {
|
||||
return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full language string.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getFullLanguage(spec) {
|
||||
return spec.full;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a spec has any quality.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function isQuality(spec) {
|
||||
return spec.q > 0;
|
||||
}
|
||||
294
node_modules/engine.io/node_modules/negotiator/lib/mediaType.js
generated
vendored
Normal file
294
node_modules/engine.io/node_modules/negotiator/lib/mediaType.js
generated
vendored
Normal file
@@ -0,0 +1,294 @@
|
||||
/**
|
||||
* negotiator
|
||||
* Copyright(c) 2012 Isaac Z. Schlueter
|
||||
* Copyright(c) 2014 Federico Romero
|
||||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = preferredMediaTypes;
|
||||
module.exports.preferredMediaTypes = preferredMediaTypes;
|
||||
|
||||
/**
|
||||
* Module variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var simpleMediaTypeRegExp = /^\s*([^\s\/;]+)\/([^;\s]+)\s*(?:;(.*))?$/;
|
||||
|
||||
/**
|
||||
* Parse the Accept header.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function parseAccept(accept) {
|
||||
var accepts = splitMediaTypes(accept);
|
||||
|
||||
for (var i = 0, j = 0; i < accepts.length; i++) {
|
||||
var mediaType = parseMediaType(accepts[i].trim(), i);
|
||||
|
||||
if (mediaType) {
|
||||
accepts[j++] = mediaType;
|
||||
}
|
||||
}
|
||||
|
||||
// trim accepts
|
||||
accepts.length = j;
|
||||
|
||||
return accepts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a media type from the Accept header.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function parseMediaType(str, i) {
|
||||
var match = simpleMediaTypeRegExp.exec(str);
|
||||
if (!match) return null;
|
||||
|
||||
var params = Object.create(null);
|
||||
var q = 1;
|
||||
var subtype = match[2];
|
||||
var type = match[1];
|
||||
|
||||
if (match[3]) {
|
||||
var kvps = splitParameters(match[3]).map(splitKeyValuePair);
|
||||
|
||||
for (var j = 0; j < kvps.length; j++) {
|
||||
var pair = kvps[j];
|
||||
var key = pair[0].toLowerCase();
|
||||
var val = pair[1];
|
||||
|
||||
// get the value, unwrapping quotes
|
||||
var value = val && val[0] === '"' && val[val.length - 1] === '"'
|
||||
? val.substr(1, val.length - 2)
|
||||
: val;
|
||||
|
||||
if (key === 'q') {
|
||||
q = parseFloat(value);
|
||||
break;
|
||||
}
|
||||
|
||||
// store parameter
|
||||
params[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: type,
|
||||
subtype: subtype,
|
||||
params: params,
|
||||
q: q,
|
||||
i: i
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the priority of a media type.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getMediaTypePriority(type, accepted, index) {
|
||||
var priority = {o: -1, q: 0, s: 0};
|
||||
|
||||
for (var i = 0; i < accepted.length; i++) {
|
||||
var spec = specify(type, accepted[i], index);
|
||||
|
||||
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
|
||||
priority = spec;
|
||||
}
|
||||
}
|
||||
|
||||
return priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specificity of the media type.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function specify(type, spec, index) {
|
||||
var p = parseMediaType(type);
|
||||
var s = 0;
|
||||
|
||||
if (!p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(spec.type.toLowerCase() == p.type.toLowerCase()) {
|
||||
s |= 4
|
||||
} else if(spec.type != '*') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(spec.subtype.toLowerCase() == p.subtype.toLowerCase()) {
|
||||
s |= 2
|
||||
} else if(spec.subtype != '*') {
|
||||
return null;
|
||||
}
|
||||
|
||||
var keys = Object.keys(spec.params);
|
||||
if (keys.length > 0) {
|
||||
if (keys.every(function (k) {
|
||||
return spec.params[k] == '*' || (spec.params[k] || '').toLowerCase() == (p.params[k] || '').toLowerCase();
|
||||
})) {
|
||||
s |= 1
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
i: index,
|
||||
o: spec.i,
|
||||
q: spec.q,
|
||||
s: s,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the preferred media types from an Accept header.
|
||||
* @public
|
||||
*/
|
||||
|
||||
function preferredMediaTypes(accept, provided) {
|
||||
// RFC 2616 sec 14.2: no header = */*
|
||||
var accepts = parseAccept(accept === undefined ? '*/*' : accept || '');
|
||||
|
||||
if (!provided) {
|
||||
// sorted list of all types
|
||||
return accepts
|
||||
.filter(isQuality)
|
||||
.sort(compareSpecs)
|
||||
.map(getFullType);
|
||||
}
|
||||
|
||||
var priorities = provided.map(function getPriority(type, index) {
|
||||
return getMediaTypePriority(type, accepts, index);
|
||||
});
|
||||
|
||||
// sorted list of accepted types
|
||||
return priorities.filter(isQuality).sort(compareSpecs).map(function getType(priority) {
|
||||
return provided[priorities.indexOf(priority)];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two specs.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function compareSpecs(a, b) {
|
||||
return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full type string.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getFullType(spec) {
|
||||
return spec.type + '/' + spec.subtype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a spec has any quality.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function isQuality(spec) {
|
||||
return spec.q > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of quotes in a string.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function quoteCount(string) {
|
||||
var count = 0;
|
||||
var index = 0;
|
||||
|
||||
while ((index = string.indexOf('"', index)) !== -1) {
|
||||
count++;
|
||||
index++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a key value pair.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function splitKeyValuePair(str) {
|
||||
var index = str.indexOf('=');
|
||||
var key;
|
||||
var val;
|
||||
|
||||
if (index === -1) {
|
||||
key = str;
|
||||
} else {
|
||||
key = str.substr(0, index);
|
||||
val = str.substr(index + 1);
|
||||
}
|
||||
|
||||
return [key, val];
|
||||
}
|
||||
|
||||
/**
|
||||
* Split an Accept header into media types.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function splitMediaTypes(accept) {
|
||||
var accepts = accept.split(',');
|
||||
|
||||
for (var i = 1, j = 0; i < accepts.length; i++) {
|
||||
if (quoteCount(accepts[j]) % 2 == 0) {
|
||||
accepts[++j] = accepts[i];
|
||||
} else {
|
||||
accepts[j] += ',' + accepts[i];
|
||||
}
|
||||
}
|
||||
|
||||
// trim accepts
|
||||
accepts.length = j + 1;
|
||||
|
||||
return accepts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a string of parameters.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function splitParameters(str) {
|
||||
var parameters = str.split(';');
|
||||
|
||||
for (var i = 1, j = 0; i < parameters.length; i++) {
|
||||
if (quoteCount(parameters[j]) % 2 == 0) {
|
||||
parameters[++j] = parameters[i];
|
||||
} else {
|
||||
parameters[j] += ';' + parameters[i];
|
||||
}
|
||||
}
|
||||
|
||||
// trim parameters
|
||||
parameters.length = j + 1;
|
||||
|
||||
for (var i = 0; i < parameters.length; i++) {
|
||||
parameters[i] = parameters[i].trim();
|
||||
}
|
||||
|
||||
return parameters;
|
||||
}
|
||||
42
node_modules/engine.io/node_modules/negotiator/package.json
generated
vendored
Normal file
42
node_modules/engine.io/node_modules/negotiator/package.json
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "negotiator",
|
||||
"description": "HTTP content negotiation",
|
||||
"version": "0.6.3",
|
||||
"contributors": [
|
||||
"Douglas Christopher Wilson <doug@somethingdoug.com>",
|
||||
"Federico Romero <federico.romero@outboxlabs.com>",
|
||||
"Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)"
|
||||
],
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"http",
|
||||
"content negotiation",
|
||||
"accept",
|
||||
"accept-language",
|
||||
"accept-encoding",
|
||||
"accept-charset"
|
||||
],
|
||||
"repository": "jshttp/negotiator",
|
||||
"devDependencies": {
|
||||
"eslint": "7.32.0",
|
||||
"eslint-plugin-markdown": "2.2.1",
|
||||
"mocha": "9.1.3",
|
||||
"nyc": "15.1.0"
|
||||
},
|
||||
"files": [
|
||||
"lib/",
|
||||
"HISTORY.md",
|
||||
"LICENSE",
|
||||
"index.js",
|
||||
"README.md"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"test": "mocha --reporter spec --check-leaks --bail test/",
|
||||
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
|
||||
"test-cov": "nyc --reporter=html --reporter=text npm test"
|
||||
}
|
||||
}
|
||||
70
node_modules/engine.io/package.json
generated
vendored
Normal file
70
node_modules/engine.io/package.json
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"name": "engine.io",
|
||||
"version": "6.6.5",
|
||||
"description": "The realtime engine behind Socket.IO. Provides the foundation of a bidirectional connection between client and server",
|
||||
"type": "commonjs",
|
||||
"main": "./build/engine.io.js",
|
||||
"types": "./build/engine.io.d.ts",
|
||||
"exports": {
|
||||
"types": "./build/engine.io.d.ts",
|
||||
"import": "./wrapper.mjs",
|
||||
"require": "./build/engine.io.js"
|
||||
},
|
||||
"author": "Guillermo Rauch <guillermo@learnboost.com>",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Eugen Dueck",
|
||||
"web": "https://github.com/EugenDueck"
|
||||
},
|
||||
{
|
||||
"name": "Afshin Mehrabani",
|
||||
"web": "https://github.com/afshinm"
|
||||
},
|
||||
{
|
||||
"name": "Christoph Dorn",
|
||||
"web": "https://github.com/cadorn"
|
||||
},
|
||||
{
|
||||
"name": "Mark Mokryn",
|
||||
"email": "mokesmokes@gmail.com"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/cors": "^2.8.12",
|
||||
"@types/node": ">=10.0.0",
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "2.0.0",
|
||||
"cookie": "~0.7.2",
|
||||
"cors": "~2.8.5",
|
||||
"debug": "~4.4.1",
|
||||
"engine.io-parser": "~5.2.1",
|
||||
"ws": "~8.18.3"
|
||||
},
|
||||
"scripts": {
|
||||
"compile": "rimraf ./build && tsc",
|
||||
"test": "npm run compile && npm run format:check && npm run test:default && npm run test:compat-v3",
|
||||
"test:default": "mocha --bail --exit",
|
||||
"test:compat-v3": "EIO_CLIENT=3 mocha --exit",
|
||||
"test:eiows": "EIO_WS_ENGINE=eiows mocha --exit",
|
||||
"test:uws": "EIO_WS_ENGINE=uws mocha --exit",
|
||||
"format:check": "prettier --check \"wrapper.mjs\" \"lib/**/*.ts\" \"test/**/*.js\" \"test/webtransport.mjs\"",
|
||||
"format:fix": "prettier --write \"wrapper.mjs\" \"lib/**/*.ts\" \"test/**/*.js\" \"test/webtransport.mjs\"",
|
||||
"prepack": "npm run compile"
|
||||
},
|
||||
"homepage": "https://github.com/socketio/socket.io/tree/main/packages/engine.io#readme",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/socketio/socket.io.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/socketio/socket.io/issues"
|
||||
},
|
||||
"files": [
|
||||
"build/",
|
||||
"wrapper.mjs"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10.2.0"
|
||||
}
|
||||
}
|
||||
10
node_modules/engine.io/wrapper.mjs
generated
vendored
Normal file
10
node_modules/engine.io/wrapper.mjs
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
export {
|
||||
Server,
|
||||
Socket,
|
||||
Transport,
|
||||
transports,
|
||||
listen,
|
||||
attach,
|
||||
parser,
|
||||
protocol,
|
||||
} from "./build/engine.io.js";
|
||||
Reference in New Issue
Block a user