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:
parent
0eb91c5591
commit
9075daa2e3
3 changed files with 41 additions and 43 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 = {
|
||||
|
|
Loading…
Add table
Reference in a new issue