Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/testing/xpcshell/node-ws/test/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 132 kB image not shown  

Quelle  websocket.test.js   Sprache: JAVA

 
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^ws$" }] */

'use strict';

const assert = require('assert');
const crypto = require('crypto');
const https = require('https');
const http = require('http');
const path = require('path');
const net = require('net');
const tls = require('tls');
const os = require('os');
const fs = require('fs');
const { URL } = require('url');

const Sender = require('../lib/sender');
const WebSocket = require('..');
const {
  CloseEvent,
  ErrorEvent,
  Event,
  MessageEvent
} = require('../lib/event-target');
const { EMPTY_BUFFER, GUID, kListener, NOOP } = require('../lib/constants');

class CustomAgent extends http.Agent {
  addRequest() {}
}

describe('WebSocket', () => {
  describe('#ctor', () => {
    it('throws an error when using an invalid url', () => {
      assert.throws(
        () => new WebSocket('foo'),
        /^SyntaxError: Invalid URL: foo$/
      );

      assert.throws(
        () => new WebSocket('https://websocket-echo.com'),
        /^SyntaxError: The URL's protocol must be one of "ws:", "wss:", or "ws\+unix:"$/
      );

      assert.throws(
        () => new WebSocket('ws+unix:'),
        /^SyntaxError: The URL's pathname is empty$/
      );

      assert.throws(
        () => new WebSocket('wss://websocket-echo.com#foo'),
        /^SyntaxError: The URL contains a fragment identifier$/
      );
    });

    it('throws an error if a subprotocol is invalid or duplicated', () => {
      for (const subprotocol of [null'''a,b', ['a''a']]) {
        assert.throws(
          () => new WebSocket('ws://localhost', subprotocol),
          /^SyntaxError: An invalid or duplicated subprotocol was specified$/
        );
      }
    });

    it('accepts `url.URL` objects as url', (done) => {
      const agent = new CustomAgent();

      agent.addRequest = (req, opts) => {
        assert.strictEqual(opts.host, '::1');
        assert.strictEqual(req.path, '/');
        done();
      };

      const ws = new WebSocket(new URL('ws://[::1]'), { agent });
    });

    describe('options', () => {
      it('accepts the `options` object as 3rd argument', () => {
        const agent = new CustomAgent();
        let count = 0;
        let ws;

        agent.addRequest = (req) => {
          assert.strictEqual(
            req.getHeader('sec-websocket-protocol'),
            undefined
          );
          count++;
        };

        ws = new WebSocket('ws://localhost', undefined, { agent });
        ws = new WebSocket('ws://localhost', [], { agent });

        assert.strictEqual(count, 2);
      });

      it('accepts the `maxPayload` option', (done) => {
        const maxPayload = 20480;
        const wss = new WebSocket.Server(
          {
            perMessageDeflate: true,
            port: 0
          },
          () => {
            const ws = new WebSocket(`ws://localhost:${wss.address().port}`, {
              perMessageDeflate: true,
              maxPayload
            });

            ws.on('open', () => {
              assert.strictEqual(ws._receiver._maxPayload, maxPayload);
              assert.strictEqual(
                ws._receiver._extensions['permessage-deflate']._maxPayload,
                maxPayload
              );
              wss.close(done);
            });
          }
        );

        wss.on('connection', (ws) => {
          ws.close();
        });
      });

      it('throws an error when using an invalid `protocolVersion`', () => {
        const options = { agent: new CustomAgent(), protocolVersion: 1000 };

        assert.throws(
          () => new WebSocket('ws://localhost', options),
          /^RangeError: Unsupported protocol version: 1000 \(supported versions: 8, 13\)$/
        );
      });

      it('honors the `generateMask` option', (done) => {
        const data = Buffer.from('foo');
        const wss = new WebSocket.Server({ port: 0 }, () => {
          const ws = new WebSocket(`ws://localhost:${wss.address().port}`, {
            generateMask() {}
          });

          ws.on('open', () => {
            ws.send(data);
          });

          ws.on('close', (code, reason) => {
            assert.strictEqual(code, 1005);
            assert.deepStrictEqual(reason, EMPTY_BUFFER);

            wss.close(done);
          });
        });

        wss.on('connection', (ws) => {
          const chunks = [];

          ws._socket.prependListener('data', (chunk) => {
            chunks.push(chunk);
          });

          ws.on('message', (message) => {
            assert.deepStrictEqual(message, data);
            assert.deepStrictEqual(
              Buffer.concat(chunks).slice(2, 6),
              Buffer.alloc(4)
            );

            ws.close();
          });
        });
      });
    });
  });

  describe('Constants', () => {
    const readyStates = {
      CONNECTING: 0,
      OPEN: 1,
      CLOSING: 2,
      CLOSED: 3
    };

    Object.keys(readyStates).forEach((state) => {
      describe(`\`${state}\``, () => {
        it('is enumerable property of class', () => {
          const descriptor = Object.getOwnPropertyDescriptor(WebSocket, state);

          assert.deepStrictEqual(descriptor, {
            configurable: false,
            enumerable: true,
            value: readyStates[state],
            writable: false
          });
        });

        it('is enumerable property of prototype', () => {
          const descriptor = Object.getOwnPropertyDescriptor(
            WebSocket.prototype,
            state
          );

          assert.deepStrictEqual(descriptor, {
            configurable: false,
            enumerable: true,
            value: readyStates[state],
            writable: false
          });
        });
      });
    });
  });

  describe('Attributes', () => {
    describe('`binaryType`', () => {
      it('is enumerable and configurable', () => {
        const descriptor = Object.getOwnPropertyDescriptor(
          WebSocket.prototype,
          'binaryType'
        );

        assert.strictEqual(descriptor.configurable, true);
        assert.strictEqual(descriptor.enumerable, true);
        assert.ok(descriptor.get !== undefined);
        assert.ok(descriptor.set !== undefined);
      });

      it("defaults to 'nodebuffer'", () => {
        const ws = new WebSocket('ws://localhost', {
          agent: new CustomAgent()
        });

        assert.strictEqual(ws.binaryType, 'nodebuffer');
      });

      it("can be changed to 'arraybuffer' or 'fragments'", () => {
        const ws = new WebSocket('ws://localhost', {
          agent: new CustomAgent()
        });

        ws.binaryType = 'arraybuffer';
        assert.strictEqual(ws.binaryType, 'arraybuffer');

        ws.binaryType = 'foo';
        assert.strictEqual(ws.binaryType, 'arraybuffer');

        ws.binaryType = 'fragments';
        assert.strictEqual(ws.binaryType, 'fragments');

        ws.binaryType = '';
        assert.strictEqual(ws.binaryType, 'fragments');

        ws.binaryType = 'nodebuffer';
        assert.strictEqual(ws.binaryType, 'nodebuffer');
      });
    });

    describe('`bufferedAmount`', () => {
      it('is enumerable and configurable', () => {
        const descriptor = Object.getOwnPropertyDescriptor(
          WebSocket.prototype,
          'bufferedAmount'
        );

        assert.strictEqual(descriptor.configurable, true);
        assert.strictEqual(descriptor.enumerable, true);
        assert.ok(descriptor.get !== undefined);
        assert.ok(descriptor.set === undefined);
      });

      it('defaults to zero', () => {
        const ws = new WebSocket('ws://localhost', {
          agent: new CustomAgent()
        });

        assert.strictEqual(ws.bufferedAmount, 0);
      });

      it('defaults to zero upon "open"', (done) => {
        const wss = new WebSocket.Server({ port: 0 }, () => {
          const ws = new WebSocket(`ws://localhost:${wss.address().port}`);

          ws.onopen = () => {
            assert.strictEqual(ws.bufferedAmount, 0);
            wss.close(done);
          };
        });

        wss.on('connection', (ws) => {
          ws.close();
        });
      });

      it('takes into account the data in the sender queue', (done) => {
        const wss = new WebSocket.Server(
          {
            perMessageDeflate: true,
            port: 0
          },
          () => {
            const ws = new WebSocket(`ws://localhost:${wss.address().port}`, {
              perMessageDeflate: { threshold: 0 }
            });

            ws.on('open', () => {
              ws.send('foo');

              assert.strictEqual(ws.bufferedAmount, 3);

              ws.send('bar', (err) => {
                assert.ifError(err);
                assert.strictEqual(ws.bufferedAmount, 0);
                wss.close(done);
              });

              assert.strictEqual(ws.bufferedAmount, 6);
            });
          }
        );

        wss.on('connection', (ws) => {
          ws.close();
        });
      });

      it('takes into account the data in the socket queue', (done) => {
        const wss = new WebSocket.Server({ port: 0 }, () => {
          const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
        });

        wss.on('connection', (ws) => {
          const data = Buffer.alloc(1024, 61);

          while (ws.bufferedAmount === 0) {
            ws.send(data);
          }

          assert.ok(ws.bufferedAmount > 0);
          assert.strictEqual(
            ws.bufferedAmount,
            ws._socket._writableState.length
          );

          ws.on('close', () => wss.close(done));
          ws.close();
        });
      });
    });

    describe('`extensions`', () => {
      it('is enumerable and configurable', () => {
        const descriptor = Object.getOwnPropertyDescriptor(
          WebSocket.prototype,
          'bufferedAmount'
        );

        assert.strictEqual(descriptor.configurable, true);
        assert.strictEqual(descriptor.enumerable, true);
        assert.ok(descriptor.get !== undefined);
        assert.ok(descriptor.set === undefined);
      });

      it('exposes the negotiated extensions names (1/2)', (done) => {
        const wss = new WebSocket.Server({ port: 0 }, () => {
          const ws = new WebSocket(`ws://localhost:${wss.address().port}`);

          assert.strictEqual(ws.extensions, '');

          ws.on('open', () => {
            assert.strictEqual(ws.extensions, '');
            ws.on('close', () => wss.close(done));
          });
        });

        wss.on('connection', (ws) => {
          assert.strictEqual(ws.extensions, '');
          ws.close();
        });
      });

      it('exposes the negotiated extensions names (2/2)', (done) => {
        const wss = new WebSocket.Server(
          {
            perMessageDeflate: true,
            port: 0
          },
          () => {
            const ws = new WebSocket(`ws://localhost:${wss.address().port}`);

            assert.strictEqual(ws.extensions, '');

            ws.on('open', () => {
              assert.strictEqual(ws.extensions, 'permessage-deflate');
              ws.on('close', () => wss.close(done));
            });
          }
        );

        wss.on('connection', (ws) => {
          assert.strictEqual(ws.extensions, 'permessage-deflate');
          ws.close();
        });
      });
    });

    describe('`isPaused`', () => {
      it('is enumerable and configurable', () => {
        const descriptor = Object.getOwnPropertyDescriptor(
          WebSocket.prototype,
          'isPaused'
        );

        assert.strictEqual(descriptor.configurable, true);
        assert.strictEqual(descriptor.enumerable, true);
        assert.ok(descriptor.get !== undefined);
        assert.ok(descriptor.set === undefined);
      });

      it('indicates whether the websocket is paused', (done) => {
        const wss = new WebSocket.Server({ port: 0 }, () => {
          const ws = new WebSocket(`ws://localhost:${wss.address().port}`);

          ws.on('open', () => {
            ws.pause();
            assert.ok(ws.isPaused);

            ws.resume();
            assert.ok(!ws.isPaused);

            ws.close();
            wss.close(done);
          });

          assert.ok(!ws.isPaused);
        });
      });
    });

    describe('`protocol`', () => {
      it('is enumerable and configurable', () => {
        const descriptor = Object.getOwnPropertyDescriptor(
          WebSocket.prototype,
          'protocol'
        );

        assert.strictEqual(descriptor.configurable, true);
        assert.strictEqual(descriptor.enumerable, true);
        assert.ok(descriptor.get !== undefined);
        assert.ok(descriptor.set === undefined);
      });

      it('exposes the subprotocol selected by the server', (done) => {
        const wss = new WebSocket.Server({ port: 0 }, () => {
          const port = wss.address().port;
          const ws = new WebSocket(`ws://localhost:${port}`, 'foo');

          assert.strictEqual(ws.extensions, '');

          ws.on('open', () => {
            assert.strictEqual(ws.protocol, 'foo');
            ws.on('close', () => wss.close(done));
          });
        });

        wss.on('connection', (ws) => {
          assert.strictEqual(ws.protocol, 'foo');
          ws.close();
        });
      });
    });

    describe('`readyState`', () => {
      it('is enumerable and configurable', () => {
        const descriptor = Object.getOwnPropertyDescriptor(
          WebSocket.prototype,
          'readyState'
        );

        assert.strictEqual(descriptor.configurable, true);
        assert.strictEqual(descriptor.enumerable, true);
        assert.ok(descriptor.get !== undefined);
        assert.ok(descriptor.set === undefined);
      });

      it('defaults to `CONNECTING`', () => {
        const ws = new WebSocket('ws://localhost', {
          agent: new CustomAgent()
        });

        assert.strictEqual(ws.readyState, WebSocket.CONNECTING);
      });

      it('is set to `OPEN` once connection is established', (done) => {
        const wss = new WebSocket.Server({ port: 0 }, () => {
          const ws = new WebSocket(`ws://localhost:${wss.address().port}`);

          ws.on('open', () => {
            assert.strictEqual(ws.readyState, WebSocket.OPEN);
            ws.close();
          });

          ws.on('close', () => wss.close(done));
        });
      });

      it('is set to `CLOSED` once connection is closed', (done) => {
        const wss = new WebSocket.Server({ port: 0 }, () => {
          const ws = new WebSocket(`ws://localhost:${wss.address().port}`);

          ws.on('close', () => {
            assert.strictEqual(ws.readyState, WebSocket.CLOSED);
            wss.close(done);
          });

          ws.on('open', () => ws.close(1001));
        });
      });

      it('is set to `CLOSED` once connection is terminated', (done) => {
        const wss = new WebSocket.Server({ port: 0 }, () => {
          const ws = new WebSocket(`ws://localhost:${wss.address().port}`);

          ws.on('close', () => {
            assert.strictEqual(ws.readyState, WebSocket.CLOSED);
            wss.close(done);
          });

          ws.on('open', () => ws.terminate());
        });
      });
    });

    describe('`url`', () => {
      it('is enumerable and configurable', () => {
        const descriptor = Object.getOwnPropertyDescriptor(
          WebSocket.prototype,
          'url'
        );

        assert.strictEqual(descriptor.configurable, true);
        assert.strictEqual(descriptor.enumerable, true);
        assert.ok(descriptor.get !== undefined);
        assert.ok(descriptor.set === undefined);
      });

      it('exposes the server url', () => {
        const url = 'ws://localhost';
        const ws = new WebSocket(url, { agent: new CustomAgent() });

        assert.strictEqual(ws.url, url);
      });
    });
  });

  describe('Events', () => {
    it("emits an 'error' event if an error occurs", (done) => {
      let clientCloseEventEmitted = false;
      let serverClientCloseEventEmitted = false;

      const wss = new WebSocket.Server({ port: 0 }, () => {
        const ws = new WebSocket(`ws://localhost:${wss.address().port}`);

        ws.on('error', (err) => {
          assert.ok(err instanceof RangeError);
          assert.strictEqual(err.code, 'WS_ERR_INVALID_OPCODE');
          assert.strictEqual(
            err.message,
            'Invalid WebSocket frame: invalid opcode 5'
          );

          ws.on('close', (code, reason) => {
            assert.strictEqual(code, 1006);
            assert.strictEqual(reason, EMPTY_BUFFER);

            clientCloseEventEmitted = true;
            if (serverClientCloseEventEmitted) wss.close(done);
          });
        });
      });

      wss.on('connection', (ws) => {
        ws.on('close', (code, reason) => {
          assert.strictEqual(code, 1002);
          assert.deepStrictEqual(reason, EMPTY_BUFFER);

          serverClientCloseEventEmitted = true;
          if (clientCloseEventEmitted) wss.close(done);
        });

        ws._socket.write(Buffer.from([0x85, 0x00]));
      });
    });

    it('does not re-emit `net.Socket` errors', (done) => {
      const codes = ['EPIPE''ECONNABORTED''ECANCELED''ECONNRESET'];
      const wss = new WebSocket.Server({ port: 0 }, () => {
        const ws = new WebSocket(`ws://localhost:${wss.address().port}`);

        ws.on('open', () => {
          ws._socket.on('error', (err) => {
            assert.ok(err instanceof Error);
            assert.ok(codes.includes(err.code), `Unexpected code: ${err.code}`);
            ws.on('close', (code, message) => {
              assert.strictEqual(code, 1006);
              assert.strictEqual(message, EMPTY_BUFFER);
              wss.close(done);
            });
          });

          for (const client of wss.clients) client.terminate();
          ws.send('foo');
          ws.send('bar');
        });
      });
    });

    it("emits an 'upgrade' event", (done) => {
      const wss = new WebSocket.Server({ port: 0 }, () => {
        const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
        ws.on('upgrade', (res) => {
          assert.ok(res instanceof http.IncomingMessage);
          wss.close(done);
        });
      });

      wss.on('connection', (ws) => {
        ws.close();
      });
    });

    it("emits a 'ping' event", (done) => {
      const wss = new WebSocket.Server({ port: 0 }, () => {
        const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
        ws.on('ping', () => wss.close(done));
      });

      wss.on('connection', (ws) => {
        ws.ping();
        ws.close();
      });
    });

    it("emits a 'pong' event", (done) => {
      const wss = new WebSocket.Server({ port: 0 }, () => {
        const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
        ws.on('pong', () => wss.close(done));
      });

      wss.on('connection', (ws) => {
        ws.pong();
        ws.close();
      });
    });

    it("emits a 'redirect' event", (done) => {
      const server = http.createServer();
      const wss = new WebSocket.Server({ noServer: true, path: '/foo' });

      server.once('upgrade', (req, socket) => {
        socket.end('HTTP/1.1 302 Found\r\nLocation: /foo\r\n\r\n');
        server.once('upgrade', (req, socket, head) => {
          wss.handleUpgrade(req, socket, head, (ws) => {
            ws.close();
          });
        });
      });

      server.listen(() => {
        const port = server.address().port;
        const ws = new WebSocket(`ws://localhost:${port}`, {
          followRedirects: true
        });

        ws.on('redirect', (url, req) => {
          assert.strictEqual(ws._redirects, 1);
          assert.strictEqual(url, `ws://localhost:${port}/foo`);
          assert.ok(req instanceof http.ClientRequest);

          ws.on('close', (code) => {
            assert.strictEqual(code, 1005);
            server.close(done);
          });
        });
      });
    });
  });

  describe('Connection establishing', () => {
    const server = http.createServer();

    beforeEach((done) => server.listen(0, done));
    afterEach((done) => server.close(done));

    it('fails if the Upgrade header field value is not "websocket"', (done) => {
      server.once('upgrade', (req, socket) => {
        socket.on('end', socket.end);
        socket.write(
          'HTTP/1.1 101 Switching Protocols\r\n' +
            'Connection: Upgrade\r\n' +
            'Upgrade: foo\r\n' +
            '\r\n'
        );
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`);

      ws.on('error', (err) => {
        assert.ok(err instanceof Error);
        assert.strictEqual(err.message, 'Invalid Upgrade header');
        done();
      });
    });

    it('fails if the Sec-WebSocket-Accept header is invalid', (done) => {
      server.once('upgrade', (req, socket) => {
        socket.on('end', socket.end);
        socket.write(
          'HTTP/1.1 101 Switching Protocols\r\n' +
            'Upgrade: websocket\r\n' +
            'Connection: Upgrade\r\n' +
            'Sec-WebSocket-Accept: CxYS6+NgJSBG74mdgLvGscRvpns=\r\n' +
            '\r\n'
        );
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`);

      ws.on('error', (err) => {
        assert.ok(err instanceof Error);
        assert.strictEqual(err.message, 'Invalid Sec-WebSocket-Accept header');
        done();
      });
    });

    it('close event is raised when server closes connection', (done) => {
      server.once('upgrade', (req, socket) => {
        const key = crypto
          .createHash('sha1')
          .update(req.headers['sec-websocket-key'] + GUID)
          .digest('base64');

        socket.end(
          'HTTP/1.1 101 Switching Protocols\r\n' +
            'Upgrade: websocket\r\n' +
            'Connection: Upgrade\r\n' +
            `Sec-WebSocket-Accept: ${key}\r\n` +
            '\r\n'
        );
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`);

      ws.on('close', (code, reason) => {
        assert.strictEqual(code, 1006);
        assert.strictEqual(reason, EMPTY_BUFFER);
        done();
      });
    });

    it('error is emitted if server aborts connection', (done) => {
      server.once('upgrade', (req, socket) => {
        socket.end(
          `HTTP/1.1 401 ${http.STATUS_CODES[401]}\r\n` +
            'Connection: close\r\n' +
            'Content-type: text/html\r\n' +
            `Content-Length: ${http.STATUS_CODES[401].length}\r\n` +
            '\r\n'
        );
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`);

      ws.on('open', () => done(new Error("Unexpected 'open' event")));
      ws.on('error', (err) => {
        assert.ok(err instanceof Error);
        assert.strictEqual(err.message, 'Unexpected server response: 401');
        done();
      });
    });

    it('unexpected response can be read when sent by server', (done) => {
      server.once('upgrade', (req, socket) => {
        socket.end(
          `HTTP/1.1 401 ${http.STATUS_CODES[401]}\r\n` +
            'Connection: close\r\n' +
            'Content-type: text/html\r\n' +
            'Content-Length: 3\r\n' +
            '\r\n' +
            'foo'
        );
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`);

      ws.on('open', () => done(new Error("Unexpected 'open' event")));
      ws.on('error', () => done(new Error("Unexpected 'error' event")));
      ws.on('unexpected-response', (req, res) => {
        assert.strictEqual(res.statusCode, 401);

        let data = '';

        res.on('data', (v) => {
          data += v;
        });

        res.on('end', () => {
          assert.strictEqual(data, 'foo');
          done();
        });
      });
    });

    it('request can be aborted when unexpected response is sent by server', (done) => {
      server.once('upgrade', (req, socket) => {
        socket.end(
          `HTTP/1.1 401 ${http.STATUS_CODES[401]}\r\n` +
            'Connection: close\r\n' +
            'Content-type: text/html\r\n' +
            'Content-Length: 3\r\n' +
            '\r\n' +
            'foo'
        );
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`);

      ws.on('open', () => done(new Error("Unexpected 'open' event")));
      ws.on('error', () => done(new Error("Unexpected 'error' event")));
      ws.on('unexpected-response', (req, res) => {
        assert.strictEqual(res.statusCode, 401);

        res.on('end', done);
        req.abort();
      });
    });

    it('fails if the opening handshake timeout expires', (done) => {
      server.once('upgrade', (req, socket) => socket.on('end', socket.end));

      const port = server.address().port;
      const ws = new WebSocket(`ws://localhost:${port}`, {
        handshakeTimeout: 100
      });

      ws.on('open', () => done(new Error("Unexpected 'open' event")));
      ws.on('error', (err) => {
        assert.ok(err instanceof Error);
        assert.strictEqual(err.message, 'Opening handshake has timed out');
        done();
      });
    });

    it('fails if an unexpected Sec-WebSocket-Extensions header is received', (done) => {
      server.once('upgrade', (req, socket) => {
        const key = crypto
          .createHash('sha1')
          .update(req.headers['sec-websocket-key'] + GUID)
          .digest('base64');

        socket.end(
          'HTTP/1.1 101 Switching Protocols\r\n' +
            'Upgrade: websocket\r\n' +
            'Connection: Upgrade\r\n' +
            `Sec-WebSocket-Accept: ${key}\r\n` +
            'Sec-WebSocket-Extensions: foo\r\n' +
            '\r\n'
        );
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`, {
        perMessageDeflate: false
      });

      ws.on('open', () => done(new Error("Unexpected 'open' event")));
      ws.on('error', (err) => {
        assert.ok(err instanceof Error);
        assert.strictEqual(
          err.message,
          'Server sent a Sec-WebSocket-Extensions header but no extension ' +
            'was requested'
        );
        ws.on('close', () => done());
      });
    });

    it('fails if the Sec-WebSocket-Extensions header is invalid (1/2)', (done) => {
      server.once('upgrade', (req, socket) => {
        const key = crypto
          .createHash('sha1')
          .update(req.headers['sec-websocket-key'] + GUID)
          .digest('base64');

        socket.end(
          'HTTP/1.1 101 Switching Protocols\r\n' +
            'Upgrade: websocket\r\n' +
            'Connection: Upgrade\r\n' +
            `Sec-WebSocket-Accept: ${key}\r\n` +
            'Sec-WebSocket-Extensions: foo;=\r\n' +
            '\r\n'
        );
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`);

      ws.on('open', () => done(new Error("Unexpected 'open' event")));
      ws.on('error', (err) => {
        assert.ok(err instanceof Error);
        assert.strictEqual(
          err.message,
          'Invalid Sec-WebSocket-Extensions header'
        );
        ws.on('close', () => done());
      });
    });

    it('fails if the Sec-WebSocket-Extensions header is invalid (2/2)', (done) => {
      server.once('upgrade', (req, socket) => {
        const key = crypto
          .createHash('sha1')
          .update(req.headers['sec-websocket-key'] + GUID)
          .digest('base64');

        socket.end(
          'HTTP/1.1 101 Switching Protocols\r\n' +
            'Upgrade: websocket\r\n' +
            'Connection: Upgrade\r\n' +
            `Sec-WebSocket-Accept: ${key}\r\n` +
            'Sec-WebSocket-Extensions: ' +
            'permessage-deflate; client_max_window_bits=7\r\n' +
            '\r\n'
        );
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`);

      ws.on('open', () => done(new Error("Unexpected 'open' event")));
      ws.on('error', (err) => {
        assert.ok(err instanceof Error);
        assert.strictEqual(
          err.message,
          'Invalid Sec-WebSocket-Extensions header'
        );
        ws.on('close', () => done());
      });
    });

    it('fails if an unexpected extension is received (1/2)', (done) => {
      server.once('upgrade', (req, socket) => {
        const key = crypto
          .createHash('sha1')
          .update(req.headers['sec-websocket-key'] + GUID)
          .digest('base64');

        socket.end(
          'HTTP/1.1 101 Switching Protocols\r\n' +
            'Upgrade: websocket\r\n' +
            'Connection: Upgrade\r\n' +
            `Sec-WebSocket-Accept: ${key}\r\n` +
            'Sec-WebSocket-Extensions: foo\r\n' +
            '\r\n'
        );
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`);

      ws.on('open', () => done(new Error("Unexpected 'open' event")));
      ws.on('error', (err) => {
        assert.ok(err instanceof Error);
        assert.strictEqual(
          err.message,
          'Server indicated an extension that was not requested'
        );
        ws.on('close', () => done());
      });
    });

    it('fails if an unexpected extension is received (2/2)', (done) => {
      server.once('upgrade', (req, socket) => {
        const key = crypto
          .createHash('sha1')
          .update(req.headers['sec-websocket-key'] + GUID)
          .digest('base64');

        socket.end(
          'HTTP/1.1 101 Switching Protocols\r\n' +
            'Upgrade: websocket\r\n' +
            'Connection: Upgrade\r\n' +
            `Sec-WebSocket-Accept: ${key}\r\n` +
            'Sec-WebSocket-Extensions: permessage-deflate,foo\r\n' +
            '\r\n'
        );
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`);

      ws.on('open', () => done(new Error("Unexpected 'open' event")));
      ws.on('error', (err) => {
        assert.ok(err instanceof Error);
        assert.strictEqual(
          err.message,
          'Server indicated an extension that was not requested'
        );
        ws.on('close', () => done());
      });
    });

    it('fails if server sends a subprotocol when none was requested', (done) => {
      const wss = new WebSocket.Server({ server });

      wss.on('headers', (headers) => {
        headers.push('Sec-WebSocket-Protocol: foo');
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`);

      ws.on('open', () => done(new Error("Unexpected 'open' event")));
      ws.on('error', (err) => {
        assert.ok(err instanceof Error);
        assert.strictEqual(
          err.message,
          'Server sent a subprotocol but none was requested'
        );
        ws.on('close', () => wss.close(done));
      });
    });

    it('fails if server sends an invalid subprotocol (1/2)', (done) => {
      const wss = new WebSocket.Server({
        handleProtocols: () => 'baz',
        server
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`, [
        'foo',
        'bar'
      ]);

      ws.on('open', () => done(new Error("Unexpected 'open' event")));
      ws.on('error', (err) => {
        assert.ok(err instanceof Error);
        assert.strictEqual(err.message, 'Server sent an invalid subprotocol');
        ws.on('close', () => wss.close(done));
      });
    });

    it('fails if server sends an invalid subprotocol (2/2)', (done) => {
      server.once('upgrade', (req, socket) => {
        const key = crypto
          .createHash('sha1')
          .update(req.headers['sec-websocket-key'] + GUID)
          .digest('base64');

        socket.end(
          'HTTP/1.1 101 Switching Protocols\r\n' +
            'Upgrade: websocket\r\n' +
            'Connection: Upgrade\r\n' +
            `Sec-WebSocket-Accept: ${key}\r\n` +
            'Sec-WebSocket-Protocol:\r\n' +
            '\r\n'
        );
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`, [
        'foo',
        'bar'
      ]);

      ws.on('open', () => done(new Error("Unexpected 'open' event")));
      ws.on('error', (err) => {
        assert.ok(err instanceof Error);
        assert.strictEqual(err.message, 'Server sent an invalid subprotocol');
        ws.on('close', () => done());
      });
    });

    it('fails if server sends no subprotocol', (done) => {
      const wss = new WebSocket.Server({
        handleProtocols() {},
        server
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`, [
        'foo',
        'bar'
      ]);

      ws.on('open', () => done(new Error("Unexpected 'open' event")));
      ws.on('error', (err) => {
        assert.ok(err instanceof Error);
        assert.strictEqual(err.message, 'Server sent no subprotocol');
        ws.on('close', () => wss.close(done));
      });
    });

    it('does not follow redirects by default', (done) => {
      server.once('upgrade', (req, socket) => {
        socket.end(
          'HTTP/1.1 301 Moved Permanently\r\n' +
            'Location: ws://localhost:8080\r\n' +
            '\r\n'
        );
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`);

      ws.on('open', () => done(new Error("Unexpected 'open' event")));
      ws.on('error', (err) => {
        assert.ok(err instanceof Error);
        assert.strictEqual(err.message, 'Unexpected server response: 301');
        assert.strictEqual(ws._redirects, 0);
        ws.on('close', () => done());
      });
    });

    it('honors the `followRedirects` option', (done) => {
      const wss = new WebSocket.Server({ noServer: true, path: '/foo' });

      server.once('upgrade', (req, socket) => {
        socket.end('HTTP/1.1 302 Found\r\nLocation: /foo\r\n\r\n');
        server.once('upgrade', (req, socket, head) => {
          wss.handleUpgrade(req, socket, head, NOOP);
        });
      });

      const port = server.address().port;
      const ws = new WebSocket(`ws://localhost:${port}`, {
        followRedirects: true
      });

      ws.on('open', () => {
        assert.strictEqual(ws.url, `ws://localhost:${port}/foo`);
        assert.strictEqual(ws._redirects, 1);
        ws.on('close', () => done());
        ws.close();
      });
    });

    it('honors the `maxRedirects` option', (done) => {
      const onUpgrade = (req, socket) => {
        socket.end('HTTP/1.1 302 Found\r\nLocation: /\r\n\r\n');
      };

      server.on('upgrade', onUpgrade);

      const ws = new WebSocket(`ws://localhost:${server.address().port}`, {
        followRedirects: true,
        maxRedirects: 1
      });

      ws.on('open', () => done(new Error("Unexpected 'open' event")));
      ws.on('error', (err) => {
        assert.ok(err instanceof Error);
        assert.strictEqual(err.message, 'Maximum redirects exceeded');
        assert.strictEqual(ws._redirects, 2);

        server.removeListener('upgrade', onUpgrade);
        ws.on('close', () => done());
      });
    });

    it('emits an error if the redirect URL is invalid (1/2)', (done) => {
      server.once('upgrade', (req, socket) => {
        socket.end('HTTP/1.1 302 Found\r\nLocation: ws://\r\n\r\n');
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`, {
        followRedirects: true
      });

      ws.on('open', () => done(new Error("Unexpected 'open' event")));
      ws.on('error', (err) => {
        assert.ok(err instanceof SyntaxError);
        assert.strictEqual(err.message, 'Invalid URL: ws://');
        assert.strictEqual(ws._redirects, 1);

        ws.on('close', () => done());
      });
    });

    it('emits an error if the redirect URL is invalid (2/2)', (done) => {
      server.once('upgrade', (req, socket) => {
        socket.end('HTTP/1.1 302 Found\r\nLocation: http://localhost\r\n\r\n');
      });

      const ws = new WebSocket(`ws://localhost:${server.address().port}`, {
        followRedirects: true
      });

      ws.on('open', () => done(new Error("Unexpected 'open' event")));
      ws.on('error', (err) => {
        assert.ok(err instanceof SyntaxError);
        assert.strictEqual(
          err.message,
          'The URL\'s protocol must be one of "ws:""wss:", or "ws+unix:"'
        );
        assert.strictEqual(ws._redirects, 1);

        ws.on('close', () => done());
      });
    });

    it('uses the first url userinfo when following redirects', (done) => {
      const wss = new WebSocket.Server({ noServer: true, path: '/foo' });
      const authorization = 'Basic Zm9vOmJhcg==';

      server.once('upgrade', (req, socket) => {
        socket.end(
          'HTTP/1.1 302 Found\r\n' +
            `Location: ws://baz:qux@localhost:${port}/foo\r\n\r\n`
        );
        server.once('upgrade', (req, socket, head) => {
          wss.handleUpgrade(req, socket, head, (ws, req) => {
            assert.strictEqual(req.headers.authorization, authorization);
            ws.close();
          });
        });
      });

      const port = server.address().port;
      const ws = new WebSocket(`ws://foo:bar@localhost:${port}`, {
        followRedirects: true
      });

      assert.strictEqual(ws._req.getHeader('Authorization'), authorization);

      ws.on('close', (code) => {
        assert.strictEqual(code, 1005);
        assert.strictEqual(ws.url, `ws://baz:qux@localhost:${port}/foo`);
        assert.strictEqual(ws._redirects, 1);

        wss.close(done);
      });
    });

    describe('When moving away from a secure context', () => {
      function proxy(httpServer, httpsServer) {
        const server = net.createServer({ allowHalfOpen: true });

        server.on('connection', (socket) => {
          socket.on('readable'function read() {
            socket.removeListener('readable', read);

            const buf = socket.read(1);
            const target = buf[0] === 22 ? httpsServer : httpServer;

            socket.unshift(buf);
            target.emit('connection', socket);
          });
        });

        return server;
      }

      describe("If there is no 'redirect' event listener", () => {
        it('drops the `auth` option', (done) => {
          const httpServer = http.createServer();
          const httpsServer = https.createServer({
            cert: fs.readFileSync('test/fixtures/certificate.pem'),
            key: fs.readFileSync('test/fixtures/key.pem')
          });
          const server = proxy(httpServer, httpsServer);

          server.listen(() => {
            const port = server.address().port;

            httpsServer.on('upgrade', (req, socket) => {
              socket.on('error', NOOP);
              socket.end(
                'HTTP/1.1 302 Found\r\n' +
                  `Location: ws://localhost:${port}/\r\n\r\n`
              );
            });

            const wss = new WebSocket.Server({ server: httpServer });

            wss.on('connection', (ws, req) => {
              assert.strictEqual(req.headers.authorization, undefined);
              ws.close();
            });

            const ws = new WebSocket(`wss://localhost:${port}`, {
              auth: 'foo:bar',
              followRedirects: true,
              rejectUnauthorized: false
            });

            assert.strictEqual(
              ws._req.getHeader('Authorization'),
              'Basic Zm9vOmJhcg=='
            );

            ws.on('close', (code) => {
              assert.strictEqual(code, 1005);
              assert.strictEqual(ws.url, `ws://localhost:${port}/`);
              assert.strictEqual(ws._redirects, 1);

              server.close(done);
            });
          });
        });

        it('drops the Authorization and Cookie headers', (done) => {
          const httpServer = http.createServer();
          const httpsServer = https.createServer({
            cert: fs.readFileSync('test/fixtures/certificate.pem'),
            key: fs.readFileSync('test/fixtures/key.pem')
          });
          const server = proxy(httpServer, httpsServer);

          server.listen(() => {
            const port = server.address().port;

            httpsServer.on('upgrade', (req, socket) => {
              socket.on('error', NOOP);
              socket.end(
                'HTTP/1.1 302 Found\r\n' +
                  `Location: ws://localhost:${port}/\r\n\r\n`
              );
            });

            const headers = {
              authorization: 'Basic Zm9vOmJhcg==',
              cookie: 'foo=bar',
              host: 'foo'
            };

            const wss = new WebSocket.Server({ server: httpServer });

            wss.on('connection', (ws, req) => {
              assert.strictEqual(req.headers.authorization, undefined);
              assert.strictEqual(req.headers.cookie, undefined);
              assert.strictEqual(req.headers.host, headers.host);

              ws.close();
            });

            const ws = new WebSocket(`wss://localhost:${port}`, {
              followRedirects: true,
              headers,
              rejectUnauthorized: false
            });

            const firstRequest = ws._req;

            assert.strictEqual(
              firstRequest.getHeader('Authorization'),
              headers.authorization
            );
            assert.strictEqual(
              firstRequest.getHeader('Cookie'),
              headers.cookie
            );
            assert.strictEqual(firstRequest.getHeader('Host'), headers.host);

            ws.on('close', (code) => {
              assert.strictEqual(code, 1005);
              assert.strictEqual(ws.url, `ws://localhost:${port}/`);
              assert.strictEqual(ws._redirects, 1);

              server.close(done);
            });
          });
        });
      });

      describe("If there is at least one 'redirect' event listener", () => {
        it('does not drop any headers by default', (done) => {
          const httpServer = http.createServer();
          const httpsServer = https.createServer({
            cert: fs.readFileSync('test/fixtures/certificate.pem'),
            key: fs.readFileSync('test/fixtures/key.pem')
          });
          const server = proxy(httpServer, httpsServer);

          server.listen(() => {
            const port = server.address().port;

            httpsServer.on('upgrade', (req, socket) => {
              socket.on('error', NOOP);
              socket.end(
                'HTTP/1.1 302 Found\r\n' +
                  `Location: ws://localhost:${port}/\r\n\r\n`
              );
            });

            const headers = {
              authorization: 'Basic Zm9vOmJhcg==',
              cookie: 'foo=bar',
              host: 'foo'
            };

            const wss = new WebSocket.Server({ server: httpServer });

            wss.on('connection', (ws, req) => {
              assert.strictEqual(
                req.headers.authorization,
                headers.authorization
              );
              assert.strictEqual(req.headers.cookie, headers.cookie);
              assert.strictEqual(req.headers.host, headers.host);

              ws.close();
            });

            const ws = new WebSocket(`wss://localhost:${port}`, {
              followRedirects: true,
              headers,
              rejectUnauthorized: false
            });

            const firstRequest = ws._req;

            assert.strictEqual(
              firstRequest.getHeader('Authorization'),
              headers.authorization
            );
            assert.strictEqual(
              firstRequest.getHeader('Cookie'),
              headers.cookie
            );
            assert.strictEqual(firstRequest.getHeader('Host'), headers.host);

            ws.on('redirect', (url, req) => {
              assert.strictEqual(ws._redirects, 1);
              assert.strictEqual(url, `ws://localhost:${port}/`);
              assert.notStrictEqual(firstRequest, req);
              assert.strictEqual(
                req.getHeader('Authorization'),
                headers.authorization
              );
              assert.strictEqual(req.getHeader('Cookie'), headers.cookie);
              assert.strictEqual(req.getHeader('Host'), headers.host);

              ws.on('close', (code) => {
                assert.strictEqual(code, 1005);
                server.close(done);
              });
            });
          });
        });
      });
    });

    describe('When the redirect host is different', () => {
      describe("If there is no 'redirect' event listener", () => {
        it('drops the `auth` option', (done) => {
          const wss = new WebSocket.Server({ port: 0 }, () => {
            const port = wss.address().port;

            server.once('upgrade', (req, socket) => {
              socket.end(
                'HTTP/1.1 302 Found\r\n' +
                  `Location: ws://localhost:${port}/\r\n\r\n`
              );
            });

            const ws = new WebSocket(
              `ws://localhost:${server.address().port}`,
              {
                auth: 'foo:bar',
                followRedirects: true
              }
            );

            assert.strictEqual(
              ws._req.getHeader('Authorization'),
              'Basic Zm9vOmJhcg=='
            );

            ws.on('close', (code) => {
              assert.strictEqual(code, 1005);
              assert.strictEqual(ws.url, `ws://localhost:${port}/`);
              assert.strictEqual(ws._redirects, 1);

              wss.close(done);
            });
          });

          wss.on('connection', (ws, req) => {
            assert.strictEqual(req.headers.authorization, undefined);
            ws.close();
          });
        });

        it('drops the Authorization, Cookie and Host headers (1/4)', (done) => {
          // Test the `ws:` to `ws:` case.

          const wss = new WebSocket.Server({ port: 0 }, () => {
            const port = wss.address().port;

            server.once('upgrade', (req, socket) => {
              socket.end(
                'HTTP/1.1 302 Found\r\n' +
                  `Location: ws://localhost:${port}/\r\n\r\n`
              );
            });

            const headers = {
              authorization: 'Basic Zm9vOmJhcg==',
              cookie: 'foo=bar',
              host: 'foo'
            };

            const ws = new WebSocket(
              `ws://localhost:${server.address().port}`,
              { followRedirects: true, headers }
            );

            const firstRequest = ws._req;

            assert.strictEqual(
              firstRequest.getHeader('Authorization'),
              headers.authorization
            );
            assert.strictEqual(
              firstRequest.getHeader('Cookie'),
              headers.cookie
            );
            assert.strictEqual(firstRequest.getHeader('Host'), headers.host);

            ws.on('close', (code) => {
              assert.strictEqual(code, 1005);
              assert.strictEqual(ws.url, `ws://localhost:${port}/`);
              assert.strictEqual(ws._redirects, 1);

              wss.close(done);
            });
          });

          wss.on('connection', (ws, req) => {
            assert.strictEqual(req.headers.authorization, undefined);
            assert.strictEqual(req.headers.cookie, undefined);
            assert.strictEqual(
              req.headers.host,
              `localhost:${wss.address().port}`
            );

            ws.close();
          });
        });

        it('drops the Authorization, Cookie and Host headers (2/4)'function (done) {
          if (process.platform === 'win32'return this.skip();

          // Test the `ws:` to `ws+unix:` case.

          const socketPath = path.join(
            os.tmpdir(),
            `ws.${crypto.randomBytes(16).toString('hex')}.sock`
          );

          server.once('upgrade', (req, socket) => {
            socket.end(
              `HTTP/1.1 302 Found\r\nLocation: ws+unix://${socketPath}\r\n\r\n`
            );
          });

          const redirectedServer = http.createServer();
          const wss = new WebSocket.Server({ server: redirectedServer });

          wss.on('connection', (ws, req) => {
            assert.strictEqual(req.headers.authorization, undefined);
            assert.strictEqual(req.headers.cookie, undefined);
            assert.strictEqual(req.headers.host, 'localhost');

            ws.close();
          });

          redirectedServer.listen(socketPath, () => {
            const headers = {
              authorization: 'Basic Zm9vOmJhcg==',
              cookie: 'foo=bar',
              host: 'foo'
            };

            const ws = new WebSocket(
              `ws://localhost:${server.address().port}`,
              { followRedirects: true, headers }
            );

            const firstRequest = ws._req;

            assert.strictEqual(
              firstRequest.getHeader('Authorization'),
              headers.authorization
            );
            assert.strictEqual(
              firstRequest.getHeader('Cookie'),
              headers.cookie
            );
            assert.strictEqual(firstRequest.getHeader('Host'), headers.host);

            ws.on('close', (code) => {
              assert.strictEqual(code, 1005);
              assert.strictEqual(ws.url, `ws+unix://${socketPath}`);
              assert.strictEqual(ws._redirects, 1);

              redirectedServer.close(done);
            });
          });
        });

        it('drops the Authorization, Cookie and Host headers (3/4)'function (done) {
          if (process.platform === 'win32'return this.skip();

          // Test the `ws+unix:` to `ws+unix:` case.

          const redirectingServerSocketPath = path.join(
            os.tmpdir(),
            `ws.${crypto.randomBytes(16).toString('hex')}.sock`
          );
          const redirectedServerSocketPath = path.join(
            os.tmpdir(),
            `ws.${crypto.randomBytes(16).toString('hex')}.sock`
          );

          const redirectingServer = http.createServer();

          redirectingServer.on('upgrade', (req, socket) => {
            socket.end(
              'HTTP/1.1 302 Found\r\n' +
                `Location: ws+unix://${redirectedServerSocketPath}\r\n\r\n`
            );
          });

          const redirectedServer = http.createServer();
          const wss = new WebSocket.Server({ server: redirectedServer });

          wss.on('connection', (ws, req) => {
            assert.strictEqual(req.headers.authorization, undefined);
            assert.strictEqual(req.headers.cookie, undefined);
            assert.strictEqual(req.headers.host, 'localhost');

            ws.close();
          });

          redirectingServer.listen(redirectingServerSocketPath, listening);
          redirectedServer.listen(redirectedServerSocketPath, listening);

          let callCount = 0;

          function listening() {
            if (++callCount !== 2) return;

            const headers = {
              authorization: 'Basic Zm9vOmJhcg==',
              cookie: 'foo=bar',
              host: 'foo'
            };

            const ws = new WebSocket(
              `ws+unix://${redirectingServerSocketPath}`,
              { followRedirects: true, headers }
            );

            const firstRequest = ws._req;

            assert.strictEqual(
              firstRequest.getHeader('Authorization'),
              headers.authorization
            );
            assert.strictEqual(
              firstRequest.getHeader('Cookie'),
              headers.cookie
            );
            assert.strictEqual(firstRequest.getHeader('Host'), headers.host);

            ws.on('close', (code) => {
              assert.strictEqual(code, 1005);
              assert.strictEqual(
                ws.url,
                `ws+unix://${redirectedServerSocketPath}`
              );
              assert.strictEqual(ws._redirects, 1);

              redirectingServer.close();
              redirectedServer.close(done);
            });
          }
        });

        it('drops the Authorization, Cookie and Host headers (4/4)'function (done) {
          if (process.platform === 'win32'return this.skip();

          // Test the `ws+unix:` to `ws:` case.

          const redirectingServer = http.createServer();
          const redirectedServer = http.createServer();
          const wss = new WebSocket.Server({ server: redirectedServer });

          wss.on('connection', (ws, req) => {
            assert.strictEqual(req.headers.authorization, undefined);
            assert.strictEqual(req.headers.cookie, undefined);
            assert.strictEqual(
              req.headers.host,
              `localhost:${redirectedServer.address().port}`
            );

            ws.close();
          });

          const socketPath = path.join(
            os.tmpdir(),
            `ws.${crypto.randomBytes(16).toString('hex')}.sock`
          );

          redirectingServer.listen(socketPath, listening);
          redirectedServer.listen(0, listening);

          let callCount = 0;

          function listening() {
            if (++callCount !== 2) return;

            const port = redirectedServer.address().port;

            redirectingServer.on('upgrade', (req, socket) => {
              socket.end(
                `HTTP/1.1 302 Found\r\nLocation: ws://localhost:${port}\r\n\r\n`
              );
            });

            const headers = {
              authorization: 'Basic Zm9vOmJhcg==',
              cookie: 'foo=bar',
              host: 'foo'
            };

            const ws = new WebSocket(`ws+unix://${socketPath}`, {
              followRedirects: true,
              headers
            });

            const firstRequest = ws._req;

            assert.strictEqual(
              firstRequest.getHeader('Authorization'),
              headers.authorization
            );
            assert.strictEqual(
              firstRequest.getHeader('Cookie'),
              headers.cookie
            );
            assert.strictEqual(firstRequest.getHeader('Host'), headers.host);

            ws.on('close', (code) => {
              assert.strictEqual(code, 1005);
              assert.strictEqual(ws.url, `ws://localhost:${port}/`);
              assert.strictEqual(ws._redirects, 1);

              redirectingServer.close();
              redirectedServer.close(done);
            });
          }
        });
      });

      describe("If there is at least one 'redirect' event listener", () => {
        it('does not drop any headers by default', (done) => {
          const headers = {
            authorization: 'Basic Zm9vOmJhcg==',
            cookie: 'foo=bar',
            host: 'foo'
          };

          const wss = new WebSocket.Server({ port: 0 }, () => {
            const port = wss.address().port;

            server.once('upgrade', (req, socket) => {
              socket.end(
                'HTTP/1.1 302 Found\r\n' +
                  `Location: ws://localhost:${port}/\r\n\r\n`
              );
            });

            const ws = new WebSocket(
              `ws://localhost:${server.address().port}`,
              { followRedirects: true, headers }
            );

            const firstRequest = ws._req;

            assert.strictEqual(
              firstRequest.getHeader('Authorization'),
              headers.authorization
            );
            assert.strictEqual(
              firstRequest.getHeader('Cookie'),
              headers.cookie
            );
            assert.strictEqual(firstRequest.getHeader('Host'), headers.host);

            ws.on('redirect', (url, req) => {
              assert.strictEqual(ws._redirects, 1);
              assert.strictEqual(url, `ws://localhost:${port}/`);
              assert.notStrictEqual(firstRequest, req);
              assert.strictEqual(
                req.getHeader('Authorization'),
                headers.authorization
              );
              assert.strictEqual(req.getHeader('Cookie'), headers.cookie);
              assert.strictEqual(req.getHeader('Host'), headers.host);

              ws.on('close', (code) => {
                assert.strictEqual(code, 1005);
                wss.close(done);
              });
            });
          });

          wss.on('connection', (ws, req) => {
            assert.strictEqual(
              req.headers.authorization,
              headers.authorization
            );
            assert.strictEqual(req.headers.cookie, headers.cookie);
            assert.strictEqual(req.headers.host, headers.host);
            ws.close();
          });
        });
      });
    });

    describe("In a listener of the 'redirect' event", () => {
      it('allows to abort the request without swallowing errors', (done) => {
        server.once('upgrade', (req, socket) => {
          socket.end('HTTP/1.1 302 Found\r\nLocation: /foo\r\n\r\n');
        });

        const port = server.address().port;
        const ws = new WebSocket(`ws://localhost:${port}`, {
          followRedirects: true
        });

        ws.on('redirect', (url, req) => {
          assert.strictEqual(ws._redirects, 1);
          assert.strictEqual(url, `ws://localhost:${port}/foo`);

          req.on('socket', () => {
            req.abort();
          });

          ws.on('error', (err) => {
            assert.ok(err instanceof Error);
            assert.strictEqual(err.message, 'socket hang up');

            ws.on('close', (code) => {
              assert.strictEqual(code, 1006);
              done();
            });
          });
        });
      });

      it('allows to remove headers', (done) => {
        const wss = new WebSocket.Server({ port: 0 }, () => {
          const port = wss.address().port;

          server.once('upgrade', (req, socket) => {
            socket.end(
              'HTTP/1.1 302 Found\r\n' +
                `Location: ws://localhost:${port}/\r\n\r\n`
            );
          });

          const headers = {
            authorization: 'Basic Zm9vOmJhcg==',
            cookie: 'foo=bar'
          };

          const ws = new WebSocket(`ws://localhost:${server.address().port}`, {
            followRedirects: true,
            headers
          });

          ws.on('redirect', (url, req) => {
            assert.strictEqual(ws._redirects, 1);
            assert.strictEqual(url, `ws://localhost:${port}/`);
            assert.strictEqual(
              req.getHeader('Authorization'),
              headers.authorization
            );
            assert.strictEqual(req.getHeader('Cookie'), headers.cookie);

            req.removeHeader('authorization');
            req.removeHeader('cookie');

            ws.on('close', (code) => {
              assert.strictEqual(code, 1005);
              wss.close(done);
            });
          });
        });

        wss.on('connection', (ws, req) => {
          assert.strictEqual(req.headers.authorization, undefined);
          assert.strictEqual(req.headers.cookie, undefined);
          ws.close();
        });
      });
    });
  });

  describe('Connection with query string', () => {
    it('connects when pathname is not null', (done) => {
      const wss = new WebSocket.Server({ port: 0 }, () => {
        const port = wss.address().port;
        const ws = new WebSocket(`ws://localhost:${port}/?token=qwerty`);

        ws.on('open', () => {
          wss.close(done);
        });
      });

      wss.on('connection', (ws) => {
        ws.close();
      });
    });

    it('connects when pathname is null', (done) => {
      const wss = new WebSocket.Server({ port: 0 }, () => {
        const port = wss.address().port;
        const ws = new WebSocket(`ws://localhost:${port}?token=qwerty`);

        ws.on('open', () => {
          wss.close(done);
        });
      });

      wss.on('connection', (ws) => {
        ws.close();
      });
    });
  });

  describe('#pause', () => {
    it('does nothing if `readyState` is `CONNECTING` or `CLOSED`', (done) => {
      const wss = new WebSocket.Server({ port: 0 }, () => {
        const ws = new WebSocket(`ws://localhost:${wss.address().port}`);

        assert.strictEqual(ws.readyState, WebSocket.CONNECTING);
        assert.ok(!ws.isPaused);

        ws.pause();
        assert.ok(!ws.isPaused);

        ws.on('open', () => {
          ws.on('close', () => {
            assert.strictEqual(ws.readyState, WebSocket.CLOSED);

            ws.pause();
            assert.ok(!ws.isPaused);

            wss.close(done);
          });

          ws.close();
        });
      });
    });

    it('pauses the socket', (done) => {
      const wss = new WebSocket.Server({ port: 0 }, () => {
        const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
      });

      wss.on('connection', (ws) => {
        assert.ok(!ws.isPaused);
        assert.ok(!ws._socket.isPaused());

        ws.pause();
        assert.ok(ws.isPaused);
        assert.ok(ws._socket.isPaused());

        ws.terminate();
        wss.close(done);
      });
    });
  });

  describe('#ping', () => {
    it('throws an error if `readyState` is `CONNECTING`', () => {
      const ws = new WebSocket('ws://localhost', {
        lookup() {}
      });

      assert.throws(
        () => ws.ping(),
        /^Error: WebSocket is not open: readyState 0 \(CONNECTING\)$/
      );

      assert.throws(
        () => ws.ping(NOOP),
        /^Error: WebSocket is not open: readyState 0 \(CONNECTING\)$/
      );
    });

    it('increases `bufferedAmount` if `readyState` is 2 or 3', (done) => {
      const ws = new WebSocket('ws://localhost', {
        lookup() {}
      });

      ws.on('error', (err) => {
        assert.ok(err instanceof Error);
        assert.strictEqual(
          err.message,
          'WebSocket was closed before the connection was established'
        );

        assert.strictEqual(ws.readyState, WebSocket.CLOSING);
        assert.strictEqual(ws.bufferedAmount, 0);

        ws.ping('hi');
        assert.strictEqual(ws.bufferedAmount, 2);

        ws.ping();
        assert.strictEqual(ws.bufferedAmount, 2);

        ws.on('close', () => {
          assert.strictEqual(ws.readyState, WebSocket.CLOSED);

          ws.ping('hi');
          assert.strictEqual(ws.bufferedAmount, 4);

          ws.ping();
          assert.strictEqual(ws.bufferedAmount, 4);

          done();
        });
      });

      ws.close();
    });

    it('calls the callback w/ an error if `readyState` is 2 or 3', (done) => {
      const wss = new WebSocket.Server({ port: 0 }, () => {
        const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
      });

      wss.on('connection', (ws) => {
        ws.close();

        assert.strictEqual(ws.bufferedAmount, 0);

        ws.ping('hi', (err) => {
          assert.ok(err instanceof Error);
          assert.strictEqual(
            err.message,
            'WebSocket is not open: readyState 2 (CLOSING)'
          );
          assert.strictEqual(ws.bufferedAmount, 2);

          ws.on('close', () => {
            ws.ping((err) => {
              assert.ok(err instanceof Error);
              assert.strictEqual(
                err.message,
                'WebSocket is not open: readyState 3 (CLOSED)'
              );
              assert.strictEqual(ws.bufferedAmount, 2);

              wss.close(done);
            });
          });
        });
      });
    });

    it('can send a ping with no data', (done) => {
      const wss = new WebSocket.Server({ port: 0 }, () => {
        const ws = new WebSocket(`ws://localhost:${wss.address().port}`);

        ws.on('open', () => {
          ws.ping(() => {
            ws.ping();
            ws.close();
          });
        });
      });

      wss.on('connection', (ws) => {
        let pings = 0;
        ws.on('ping', (data) => {
          assert.ok(Buffer.isBuffer(data));
          assert.strictEqual(data.length, 0);
          if (++pings === 2) wss.close(done);
        });
      });
    });

    it('can send a ping with data', (done) => {
      const wss = new WebSocket.Server({ port: 0 }, () => {
        const ws = new WebSocket(`ws://localhost:${wss.address().port}`);

        ws.on('open', () => {
          ws.ping('hi', () => {
            ws.ping('hi'true);
            ws.close();
          });
        });
      });

      wss.on('connection', (ws) => {
        let pings = 0;
        ws.on('ping', (message) => {
          assert.strictEqual(message.toString(), 'hi');
          if (++pings === 2) wss.close(done);
        });
      });
    });

    it('can send numbers as ping payload', (done) => {
      const wss = new WebSocket.Server({ port: 0 }, () => {
        const ws = new WebSocket(`ws://localhost:${wss.address().port}`);

        ws.on('open', () => {
          ws.ping(0);
          ws.close();
        });
      });

      wss.on('connection', (ws) => {
        ws.on('ping', (message) => {
          assert.strictEqual(message.toString(), '0');
          wss.close(done);
        });
      });
    });

    it('throws an error if the data size is greater than 125 bytes', (done) => {
      const wss = new WebSocket.Server({ port: 0 }, () => {
        const ws = new WebSocket(`ws://localhost:${wss.address().port}`);

        ws.on('open', () => {
          assert.throws(
            () => ws.ping(Buffer.alloc(126)),
            /^RangeError: The data size must not be greater than 125 bytes$/
          );

--> --------------------

--> maximum size reached

--> --------------------

97%


¤ Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.0.51Bemerkung:  (vorverarbeitet)  ¤

*Bot Zugriff






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Diese beiden folgenden Angebotsgruppen bietet das Unternehmen

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.