0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 09:31:22 -05:00

[std/ws] provide default close code for ws.close() (#4172)

This commit is contained in:
Yusuke Sakurai 2020-02-29 01:17:00 +09:00 committed by GitHub
parent 0eb91c5591
commit 9075daa2e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 43 deletions

View file

@ -103,9 +103,12 @@ export interface WebSocket {
/** Close connection after sending close frame to peer.
* This is canonical way of disconnection but it may hang because of peer's response delay.
* Default close code is 1000 (Normal Closure)
* @throws SocketClosedError
*/
close(code: number, reason?: string): Promise<void>;
close(): Promise<void>;
close(code: number): Promise<void>;
close(code: number, reason: string): Promise<void>;
/** Close connection forcely without sending close frame to peer.
* This is basically undesirable way of disconnection. Use carefully. */
@ -355,7 +358,7 @@ class WebSocketImpl implements WebSocket {
return this._isClosed;
}
async close(code: number, reason?: string): Promise<void> {
async close(code = 1000, reason?: string): Promise<void> {
try {
const header = [code >>> 8, code & 0x00ff];
let payload: Uint8Array;

View file

@ -3,20 +3,20 @@ const { test } = Deno;
import { assertEquals } from "../testing/asserts.ts";
import { Sha1 } from "./sha1.ts";
test(function testSha1(): void {
test("[ws/sha] test1", () => {
const sha1 = new Sha1();
sha1.update("abcde");
assertEquals(sha1.toString(), "03de6c570bfe24bfc328ccd7ca46b76eadaf4334");
});
test(function testSha1WithArray(): void {
test("[ws/sha] testWithArray", () => {
const data = Uint8Array.of(0x61, 0x62, 0x63, 0x64, 0x65);
const sha1 = new Sha1();
sha1.update(data);
assertEquals(sha1.toString(), "03de6c570bfe24bfc328ccd7ca46b76eadaf4334");
});
test(function testSha1WithBuffer(): void {
test("[ws/sha] testSha1WithBuffer", () => {
const data = Uint8Array.of(0x61, 0x62, 0x63, 0x64, 0x65);
const sha1 = new Sha1();
sha1.update(data.buffer);

View file

@ -23,7 +23,7 @@ import Reader = Deno.Reader;
import Conn = Deno.Conn;
import Buffer = Deno.Buffer;
test(async function wsReadUnmaskedTextFrame(): Promise<void> {
test("[ws] read unmasked text frame", async () => {
// unmasked single text frame with payload "Hello"
const buf = new BufReader(
new Buffer(new Uint8Array([0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f]))
@ -35,7 +35,7 @@ test(async function wsReadUnmaskedTextFrame(): Promise<void> {
assertEquals(frame.isLastFrame, true);
});
test(async function wsReadMaskedTextFrame(): Promise<void> {
test("[ws] read masked text frame", async () => {
// a masked single text frame with payload "Hello"
const buf = new BufReader(
new Buffer(
@ -61,7 +61,7 @@ test(async function wsReadMaskedTextFrame(): Promise<void> {
assertEquals(frame.isLastFrame, true);
});
test(async function wsReadUnmaskedSplitTextFrames(): Promise<void> {
test("[ws] read unmasked split text frames", async () => {
const buf1 = new BufReader(
new Buffer(new Uint8Array([0x01, 0x03, 0x48, 0x65, 0x6c]))
);
@ -80,7 +80,7 @@ test(async function wsReadUnmaskedSplitTextFrames(): Promise<void> {
assertEquals(new Buffer(f2.payload).toString(), "lo");
});
test(async function wsReadUnmaskedPingPongFrame(): Promise<void> {
test("[ws] read unmasked ping / pong frame", async () => {
// unmasked ping with payload "Hello"
const buf = new BufReader(
new Buffer(new Uint8Array([0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f]))
@ -88,24 +88,9 @@ test(async function wsReadUnmaskedPingPongFrame(): Promise<void> {
const ping = await readFrame(buf);
assertEquals(ping.opcode, OpCode.Ping);
assertEquals(new Buffer(ping.payload).toString(), "Hello");
const buf2 = new BufReader(
new Buffer(
new Uint8Array([
0x8a,
0x85,
0x37,
0xfa,
0x21,
0x3d,
0x7f,
0x9f,
0x4d,
0x51,
0x58
])
)
);
// prettier-ignore
const pongFrame= [0x8a, 0x85, 0x37, 0xfa, 0x21, 0x3d, 0x7f, 0x9f, 0x4d, 0x51, 0x58]
const buf2 = new BufReader(new Buffer(new Uint8Array(pongFrame)));
const pong = await readFrame(buf2);
assertEquals(pong.opcode, OpCode.Pong);
assert(pong.mask !== undefined);
@ -113,7 +98,7 @@ test(async function wsReadUnmaskedPingPongFrame(): Promise<void> {
assertEquals(new Buffer(pong.payload).toString(), "Hello");
});
test(async function wsReadUnmaskedBigBinaryFrame(): Promise<void> {
test("[ws] read unmasked big binary frame", async () => {
const payloadLength = 0x100;
const a = [0x82, 0x7e, 0x01, 0x00];
for (let i = 0; i < payloadLength; i++) {
@ -127,7 +112,7 @@ test(async function wsReadUnmaskedBigBinaryFrame(): Promise<void> {
assertEquals(bin.payload.length, payloadLength);
});
test(async function wsReadUnmaskedBigBigBinaryFrame(): Promise<void> {
test("[ws] read unmasked bigger binary frame", async () => {
const payloadLength = 0x10000;
const a = [0x82, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00];
for (let i = 0; i < payloadLength; i++) {
@ -141,13 +126,13 @@ test(async function wsReadUnmaskedBigBigBinaryFrame(): Promise<void> {
assertEquals(bin.payload.length, payloadLength);
});
test(async function wsCreateSecAccept(): Promise<void> {
test("[ws] createSecAccept", async () => {
const nonce = "dGhlIHNhbXBsZSBub25jZQ==";
const d = createSecAccept(nonce);
assertEquals(d, "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=");
});
test(function wsAcceptable(): void {
test("[ws] acceptable", () => {
const ret = acceptable({
headers: new Headers({
upgrade: "websocket",
@ -173,7 +158,7 @@ test(function wsAcceptable(): void {
);
});
test(function wsAcceptableInvalid(): void {
test("[ws] acceptable should return false when headers invalid", () => {
assertEquals(
acceptable({
headers: new Headers({ "sec-websocket-key": "aaa" })
@ -200,7 +185,7 @@ test(function wsAcceptableInvalid(): void {
);
});
test("connectWebSocket should throw invalid scheme of url", async (): Promise<
test("[ws] connectWebSocket should throw invalid scheme of url", async (): Promise<
void
> => {
await assertThrowsAsync(
@ -210,7 +195,7 @@ test("connectWebSocket should throw invalid scheme of url", async (): Promise<
);
});
test(async function wsWriteReadMaskedFrame(): Promise<void> {
test("[ws] write and read masked frame", async () => {
const mask = new Uint8Array([0, 1, 2, 3]);
const msg = "hello";
const buf = new Buffer();
@ -232,9 +217,7 @@ test(async function wsWriteReadMaskedFrame(): Promise<void> {
assertEquals(frame.payload, encode(msg));
});
test("handshake should not send search when it's empty", async function wsHandshakeWithEmptySearch(): Promise<
void
> {
test("[ws] handshake should not send search when it's empty", async () => {
const writer = new Buffer();
const reader = new Buffer(encode("HTTP/1.1 400\r\n"));
@ -255,7 +238,7 @@ test("handshake should not send search when it's empty", async function wsHandsh
assertEquals(statusLine, "GET / HTTP/1.1");
});
test("handshake should send search correctly", async function wsHandshakeWithSearch(): Promise<
test("[ws] handshake should send search correctly", async function wsHandshakeWithSearch(): Promise<
void
> {
const writer = new Buffer();
@ -278,6 +261,18 @@ test("handshake should send search correctly", async function wsHandshakeWithSea
assertEquals(statusLine, "GET /?a=1 HTTP/1.1");
});
test("[ws] ws.close() should use 1000 as close code", async () => {
const buf = new Buffer();
const bufr = new BufReader(buf);
const conn = dummyConn(buf, buf);
const ws = createWebSocket({ conn });
await ws.close();
const frame = await readFrame(bufr);
assertEquals(frame.opcode, OpCode.Close);
const code = (frame.payload[0] << 8) | frame.payload[1];
assertEquals(code, 1000);
});
function dummyConn(r: Reader, w: Writer): Conn {
return {
rid: -1,
@ -302,7 +297,7 @@ function delayedWriter(ms: number, dest: Writer): Writer {
}
};
}
test("WebSocket.send(), WebSocket.ping() should be exclusive", async (): Promise<
test("[ws] WebSocket.send(), WebSocket.ping() should be exclusive", async (): Promise<
void
> => {
const buf = new Buffer();
@ -329,14 +324,14 @@ test("WebSocket.send(), WebSocket.ping() should be exclusive", async (): Promise
assertEquals(bytes.equal(third.payload, new Uint8Array([3])), true);
});
test(function createSecKeyHasCorrectLength(): void {
test("[ws] createSecKeyHasCorrectLength", () => {
// Note: relies on --seed=86 being passed to deno to reproduce failure in
// #4063.
const secKey = createSecKey();
assertEquals(atob(secKey).length, 16);
});
test("WebSocket should throw SocketClosedError when peer closed connection without close frame", async () => {
test("[ws] WebSocket should throw SocketClosedError when peer closed connection without close frame", async () => {
const buf = new Buffer();
const eofReader: Deno.Reader = {
async read(_: Uint8Array): Promise<number | Deno.EOF> {
@ -351,7 +346,7 @@ test("WebSocket should throw SocketClosedError when peer closed connection witho
await assertThrowsAsync(() => sock.close(0), SocketClosedError);
});
test("WebSocket shouldn't throw UnexpectedEOFError on recive()", async () => {
test("[ws] WebSocket shouldn't throw UnexpectedEOFError on recive()", async () => {
const buf = new Buffer();
const eofReader: Deno.Reader = {
async read(_: Uint8Array): Promise<number | Deno.EOF> {
@ -366,7 +361,7 @@ test("WebSocket shouldn't throw UnexpectedEOFError on recive()", async () => {
assertEquals(done, true);
});
test("WebSocket should reject sending promise when connection reset forcely", async () => {
test("[ws] WebSocket should reject sending promise when connection reset forcely", async () => {
const buf = new Buffer();
let timer: number | undefined;
const lazyWriter: Deno.Writer = {