mirror of
https://github.com/denoland/deno.git
synced 2025-01-09 07:39:15 -05:00
fix(std): Use Deno.errors where possible. (#4356)
This commit is contained in:
parent
aab1acaed1
commit
0f6acf2753
13 changed files with 71 additions and 86 deletions
|
@ -1,7 +1,5 @@
|
||||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
import { UnexpectedEOFError } from "../io/bufio.ts";
|
|
||||||
|
|
||||||
type RawBaseTypes = "int8" | "int16" | "int32" | "uint8" | "uint16" | "uint32";
|
type RawBaseTypes = "int8" | "int16" | "int32" | "uint8" | "uint16" | "uint32";
|
||||||
type RawNumberTypes = RawBaseTypes | "float32" | "float64";
|
type RawNumberTypes = RawBaseTypes | "float32" | "float64";
|
||||||
type RawBigTypes = RawBaseTypes | "int64" | "uint64";
|
type RawBigTypes = RawBaseTypes | "int64" | "uint64";
|
||||||
|
@ -46,14 +44,14 @@ export function sizeof(dataType: RawTypes): number {
|
||||||
|
|
||||||
/** Reads `n` bytes from `r`.
|
/** Reads `n` bytes from `r`.
|
||||||
*
|
*
|
||||||
* Returns it in a `Uint8Array`, or throws `UnexpectedEOFError` if `n` bytes cannot be read. */
|
* Returns it in a `Uint8Array`, or throws `Deno.errors.UnexpectedEof` if `n` bytes cannot be read. */
|
||||||
export async function getNBytes(
|
export async function getNBytes(
|
||||||
r: Deno.Reader,
|
r: Deno.Reader,
|
||||||
n: number
|
n: number
|
||||||
): Promise<Uint8Array> {
|
): Promise<Uint8Array> {
|
||||||
const scratch = new Uint8Array(n);
|
const scratch = new Uint8Array(n);
|
||||||
const nRead = await r.read(scratch);
|
const nRead = await r.read(scratch);
|
||||||
if (nRead === Deno.EOF || nRead < n) throw new UnexpectedEOFError();
|
if (nRead === Deno.EOF || nRead < n) throw new Deno.errors.UnexpectedEof();
|
||||||
return scratch;
|
return scratch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +197,7 @@ export function putVarbig(
|
||||||
|
|
||||||
/** Reads a number from `r`, comsuming `sizeof(o.dataType)` bytes. Data-type defaults to `int32`.
|
/** Reads a number from `r`, comsuming `sizeof(o.dataType)` bytes. Data-type defaults to `int32`.
|
||||||
*
|
*
|
||||||
* Returns it as `number`, or throws `UnexpectedEOFError` if not enough bytes can be read. */
|
* Returns it as `number`, or throws `Deno.errors.UnexpectedEof` if not enough bytes can be read. */
|
||||||
export async function readVarnum(
|
export async function readVarnum(
|
||||||
r: Deno.Reader,
|
r: Deno.Reader,
|
||||||
o: VarnumOptions = {}
|
o: VarnumOptions = {}
|
||||||
|
@ -211,7 +209,7 @@ export async function readVarnum(
|
||||||
|
|
||||||
/** Reads an integer from `r`, comsuming `sizeof(o.dataType)` bytes. Data-type defaults to `int64`.
|
/** Reads an integer from `r`, comsuming `sizeof(o.dataType)` bytes. Data-type defaults to `int64`.
|
||||||
*
|
*
|
||||||
* Returns it as `bigint`, or throws `UnexpectedEOFError` if not enough bytes can be read. */
|
* Returns it as `bigint`, or throws `Deno.errors.UnexpectedEof` if not enough bytes can be read. */
|
||||||
export async function readVarbig(
|
export async function readVarbig(
|
||||||
r: Deno.Reader,
|
r: Deno.Reader,
|
||||||
o: VarbigOptions = {}
|
o: VarbigOptions = {}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
import { assertEquals, assertThrowsAsync } from "../testing/asserts.ts";
|
import { assertEquals, assertThrowsAsync } from "../testing/asserts.ts";
|
||||||
import { UnexpectedEOFError } from "../io/bufio.ts";
|
|
||||||
import {
|
import {
|
||||||
getNBytes,
|
getNBytes,
|
||||||
putVarbig,
|
putVarbig,
|
||||||
|
@ -27,7 +26,7 @@ Deno.test(async function testGetNBytesThrows(): Promise<void> {
|
||||||
const buff = new Deno.Buffer(data.buffer);
|
const buff = new Deno.Buffer(data.buffer);
|
||||||
assertThrowsAsync(async () => {
|
assertThrowsAsync(async () => {
|
||||||
await getNBytes(buff, 8);
|
await getNBytes(buff, 8);
|
||||||
}, UnexpectedEOFError);
|
}, Deno.errors.UnexpectedEof);
|
||||||
});
|
});
|
||||||
|
|
||||||
Deno.test(async function testPutVarbig(): Promise<void> {
|
Deno.test(async function testPutVarbig(): Promise<void> {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { BufReader, UnexpectedEOFError, BufWriter } from "../io/bufio.ts";
|
import { BufReader, BufWriter } from "../io/bufio.ts";
|
||||||
import { TextProtoReader } from "../textproto/mod.ts";
|
import { TextProtoReader } from "../textproto/mod.ts";
|
||||||
import { assert } from "../testing/asserts.ts";
|
import { assert } from "../testing/asserts.ts";
|
||||||
import { encoder } from "../strings/mod.ts";
|
import { encoder } from "../strings/mod.ts";
|
||||||
|
@ -57,13 +57,13 @@ export function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
|
||||||
chunks.shift();
|
chunks.shift();
|
||||||
// Consume \r\n;
|
// Consume \r\n;
|
||||||
if ((await tp.readLine()) === Deno.EOF) {
|
if ((await tp.readLine()) === Deno.EOF) {
|
||||||
throw new UnexpectedEOFError();
|
throw new Deno.errors.UnexpectedEof();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return readLength;
|
return readLength;
|
||||||
}
|
}
|
||||||
const line = await tp.readLine();
|
const line = await tp.readLine();
|
||||||
if (line === Deno.EOF) throw new UnexpectedEOFError();
|
if (line === Deno.EOF) throw new Deno.errors.UnexpectedEof();
|
||||||
// TODO: handle chunk extension
|
// TODO: handle chunk extension
|
||||||
const [chunkSizeString] = line.split(";");
|
const [chunkSizeString] = line.split(";");
|
||||||
const chunkSize = parseInt(chunkSizeString, 16);
|
const chunkSize = parseInt(chunkSizeString, 16);
|
||||||
|
@ -74,12 +74,12 @@ export function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
|
||||||
if (chunkSize > buf.byteLength) {
|
if (chunkSize > buf.byteLength) {
|
||||||
let eof = await r.readFull(buf);
|
let eof = await r.readFull(buf);
|
||||||
if (eof === Deno.EOF) {
|
if (eof === Deno.EOF) {
|
||||||
throw new UnexpectedEOFError();
|
throw new Deno.errors.UnexpectedEof();
|
||||||
}
|
}
|
||||||
const restChunk = new Uint8Array(chunkSize - buf.byteLength);
|
const restChunk = new Uint8Array(chunkSize - buf.byteLength);
|
||||||
eof = await r.readFull(restChunk);
|
eof = await r.readFull(restChunk);
|
||||||
if (eof === Deno.EOF) {
|
if (eof === Deno.EOF) {
|
||||||
throw new UnexpectedEOFError();
|
throw new Deno.errors.UnexpectedEof();
|
||||||
} else {
|
} else {
|
||||||
chunks.push({
|
chunks.push({
|
||||||
offset: 0,
|
offset: 0,
|
||||||
|
@ -91,11 +91,11 @@ export function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
|
||||||
const bufToFill = buf.subarray(0, chunkSize);
|
const bufToFill = buf.subarray(0, chunkSize);
|
||||||
const eof = await r.readFull(bufToFill);
|
const eof = await r.readFull(bufToFill);
|
||||||
if (eof === Deno.EOF) {
|
if (eof === Deno.EOF) {
|
||||||
throw new UnexpectedEOFError();
|
throw new Deno.errors.UnexpectedEof();
|
||||||
}
|
}
|
||||||
// Consume \r\n
|
// Consume \r\n
|
||||||
if ((await tp.readLine()) === Deno.EOF) {
|
if ((await tp.readLine()) === Deno.EOF) {
|
||||||
throw new UnexpectedEOFError();
|
throw new Deno.errors.UnexpectedEof();
|
||||||
}
|
}
|
||||||
return chunkSize;
|
return chunkSize;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ export function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
|
||||||
assert(chunkSize === 0);
|
assert(chunkSize === 0);
|
||||||
// Consume \r\n
|
// Consume \r\n
|
||||||
if ((await r.readLine()) === Deno.EOF) {
|
if ((await r.readLine()) === Deno.EOF) {
|
||||||
throw new UnexpectedEOFError();
|
throw new Deno.errors.UnexpectedEof();
|
||||||
}
|
}
|
||||||
await readTrailers(h, r);
|
await readTrailers(h, r);
|
||||||
finished = true;
|
finished = true;
|
||||||
|
@ -348,7 +348,7 @@ export async function readRequest(
|
||||||
const firstLine = await tp.readLine(); // e.g. GET /index.html HTTP/1.0
|
const firstLine = await tp.readLine(); // e.g. GET /index.html HTTP/1.0
|
||||||
if (firstLine === Deno.EOF) return Deno.EOF;
|
if (firstLine === Deno.EOF) return Deno.EOF;
|
||||||
const headers = await tp.readMIMEHeader();
|
const headers = await tp.readMIMEHeader();
|
||||||
if (headers === Deno.EOF) throw new UnexpectedEOFError();
|
if (headers === Deno.EOF) throw new Deno.errors.UnexpectedEof();
|
||||||
|
|
||||||
const req = new ServerRequest();
|
const req = new ServerRequest();
|
||||||
req.conn = conn;
|
req.conn = conn;
|
||||||
|
|
|
@ -15,7 +15,7 @@ import {
|
||||||
writeResponse
|
writeResponse
|
||||||
} from "./io.ts";
|
} from "./io.ts";
|
||||||
import { encode, decode } from "../strings/mod.ts";
|
import { encode, decode } from "../strings/mod.ts";
|
||||||
import { BufReader, UnexpectedEOFError, ReadLineResult } from "../io/bufio.ts";
|
import { BufReader, ReadLineResult } from "../io/bufio.ts";
|
||||||
import { chunkedBodyReader } from "./io.ts";
|
import { chunkedBodyReader } from "./io.ts";
|
||||||
import { ServerRequest, Response } from "./server.ts";
|
import { ServerRequest, Response } from "./server.ts";
|
||||||
import { StringReader } from "../io/readers.ts";
|
import { StringReader } from "../io/readers.ts";
|
||||||
|
@ -369,7 +369,7 @@ test(async function testReadRequestError(): Promise<void> {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
in: "GET / HTTP/1.1\r\nheader:foo\r\n",
|
in: "GET / HTTP/1.1\r\nheader:foo\r\n",
|
||||||
err: UnexpectedEOFError
|
err: Deno.errors.UnexpectedEof
|
||||||
},
|
},
|
||||||
{ in: "", err: Deno.EOF },
|
{ in: "", err: Deno.EOF },
|
||||||
{
|
{
|
||||||
|
@ -437,7 +437,7 @@ test(async function testReadRequestError(): Promise<void> {
|
||||||
} else if (typeof test.err === "string") {
|
} else if (typeof test.err === "string") {
|
||||||
assertEquals(err.message, test.err);
|
assertEquals(err.message, test.err);
|
||||||
} else if (test.err) {
|
} else if (test.err) {
|
||||||
assert(err instanceof (test.err as typeof UnexpectedEOFError));
|
assert(err instanceof (test.err as typeof Deno.errors.UnexpectedEof));
|
||||||
} else {
|
} else {
|
||||||
assert(req instanceof ServerRequest);
|
assert(req instanceof ServerRequest);
|
||||||
assert(test.headers);
|
assert(test.headers);
|
||||||
|
|
|
@ -21,11 +21,11 @@ export class BufferFullError extends Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UnexpectedEOFError extends Error {
|
export class PartialReadError extends Deno.errors.UnexpectedEof {
|
||||||
name = "UnexpectedEOFError";
|
name = "PartialReadError";
|
||||||
partial?: Uint8Array;
|
partial?: Uint8Array;
|
||||||
constructor() {
|
constructor() {
|
||||||
super("Unexpected EOF");
|
super("Encountered UnexpectedEof, data only partially read");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ export class BufReader implements Reader {
|
||||||
if (bytesRead === 0) {
|
if (bytesRead === 0) {
|
||||||
return Deno.EOF;
|
return Deno.EOF;
|
||||||
} else {
|
} else {
|
||||||
throw new UnexpectedEOFError();
|
throw new PartialReadError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bytesRead += rr;
|
bytesRead += rr;
|
||||||
|
|
|
@ -15,7 +15,7 @@ import {
|
||||||
BufReader,
|
BufReader,
|
||||||
BufWriter,
|
BufWriter,
|
||||||
BufferFullError,
|
BufferFullError,
|
||||||
UnexpectedEOFError,
|
PartialReadError,
|
||||||
readStringDelim,
|
readStringDelim,
|
||||||
readLines
|
readLines
|
||||||
} from "./bufio.ts";
|
} from "./bufio.ts";
|
||||||
|
@ -369,9 +369,9 @@ Deno.test(async function bufReaderReadFull(): Promise<void> {
|
||||||
const buf = new Uint8Array(6);
|
const buf = new Uint8Array(6);
|
||||||
try {
|
try {
|
||||||
await bufr.readFull(buf);
|
await bufr.readFull(buf);
|
||||||
fail("readFull() should throw");
|
fail("readFull() should throw PartialReadError");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
assert(err instanceof UnexpectedEOFError);
|
assert(err instanceof PartialReadError);
|
||||||
assert(err.partial instanceof Uint8Array);
|
assert(err.partial instanceof Uint8Array);
|
||||||
assertEquals(err.partial.length, 5);
|
assertEquals(err.partial.length, 5);
|
||||||
assertEquals(dec.decode(buf.subarray(0, 5)), "World");
|
assertEquals(dec.decode(buf.subarray(0, 5)), "World");
|
||||||
|
|
|
@ -36,14 +36,7 @@ export class HalfReader implements Reader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ErrTimeout extends Error {
|
/** TimeoutReader returns `Deno.errors.TimedOut` on the second read
|
||||||
constructor() {
|
|
||||||
super("timeout");
|
|
||||||
this.name = "ErrTimeout";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** TimeoutReader returns ErrTimeout on the second read
|
|
||||||
* with no data. Subsequent calls to read succeed.
|
* with no data. Subsequent calls to read succeed.
|
||||||
*/
|
*/
|
||||||
export class TimeoutReader implements Reader {
|
export class TimeoutReader implements Reader {
|
||||||
|
@ -53,7 +46,7 @@ export class TimeoutReader implements Reader {
|
||||||
async read(p: Uint8Array): Promise<number | Deno.EOF> {
|
async read(p: Uint8Array): Promise<number | Deno.EOF> {
|
||||||
this.count++;
|
this.count++;
|
||||||
if (this.count === 2) {
|
if (this.count === 2) {
|
||||||
throw new ErrTimeout();
|
throw new Deno.errors.TimedOut();
|
||||||
}
|
}
|
||||||
return this.r.read(p);
|
return this.r.read(p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||||
import { BufReader, UnexpectedEOFError } from "./bufio.ts";
|
import { BufReader } from "./bufio.ts";
|
||||||
type Reader = Deno.Reader;
|
type Reader = Deno.Reader;
|
||||||
type Writer = Deno.Writer;
|
type Writer = Deno.Writer;
|
||||||
import { assert } from "../testing/asserts.ts";
|
import { assert } from "../testing/asserts.ts";
|
||||||
|
@ -37,7 +37,7 @@ export async function readShort(buf: BufReader): Promise<number | Deno.EOF> {
|
||||||
const high = await buf.readByte();
|
const high = await buf.readByte();
|
||||||
if (high === Deno.EOF) return Deno.EOF;
|
if (high === Deno.EOF) return Deno.EOF;
|
||||||
const low = await buf.readByte();
|
const low = await buf.readByte();
|
||||||
if (low === Deno.EOF) throw new UnexpectedEOFError();
|
if (low === Deno.EOF) throw new Deno.errors.UnexpectedEof();
|
||||||
return (high << 8) | low;
|
return (high << 8) | low;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ export async function readInt(buf: BufReader): Promise<number | Deno.EOF> {
|
||||||
const high = await readShort(buf);
|
const high = await readShort(buf);
|
||||||
if (high === Deno.EOF) return Deno.EOF;
|
if (high === Deno.EOF) return Deno.EOF;
|
||||||
const low = await readShort(buf);
|
const low = await readShort(buf);
|
||||||
if (low === Deno.EOF) throw new UnexpectedEOFError();
|
if (low === Deno.EOF) throw new Deno.errors.UnexpectedEof();
|
||||||
return (high << 16) | low;
|
return (high << 16) | low;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ export async function readLong(buf: BufReader): Promise<number | Deno.EOF> {
|
||||||
const high = await readInt(buf);
|
const high = await readInt(buf);
|
||||||
if (high === Deno.EOF) return Deno.EOF;
|
if (high === Deno.EOF) return Deno.EOF;
|
||||||
const low = await readInt(buf);
|
const low = await readInt(buf);
|
||||||
if (low === Deno.EOF) throw new UnexpectedEOFError();
|
if (low === Deno.EOF) throw new Deno.errors.UnexpectedEof();
|
||||||
const big = (BigInt(high) << 32n) | BigInt(low);
|
const big = (BigInt(high) << 32n) | BigInt(low);
|
||||||
// We probably should provide a similar API that returns BigInt values.
|
// We probably should provide a similar API that returns BigInt values.
|
||||||
if (big > MAX_SAFE_INTEGER) {
|
if (big > MAX_SAFE_INTEGER) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { copyN } from "../io/ioutil.ts";
|
||||||
import { MultiReader } from "../io/readers.ts";
|
import { MultiReader } from "../io/readers.ts";
|
||||||
import { extname } from "../path/mod.ts";
|
import { extname } from "../path/mod.ts";
|
||||||
import { tempFile } from "../io/util.ts";
|
import { tempFile } from "../io/util.ts";
|
||||||
import { BufReader, BufWriter, UnexpectedEOFError } from "../io/bufio.ts";
|
import { BufReader, BufWriter } from "../io/bufio.ts";
|
||||||
import { encoder } from "../strings/mod.ts";
|
import { encoder } from "../strings/mod.ts";
|
||||||
import { assertStrictEq, assert } from "../testing/asserts.ts";
|
import { assertStrictEq, assert } from "../testing/asserts.ts";
|
||||||
import { TextProtoReader } from "../textproto/mod.ts";
|
import { TextProtoReader } from "../textproto/mod.ts";
|
||||||
|
@ -166,7 +166,7 @@ class PartReader implements Reader, Closer {
|
||||||
peekLength = max(peekLength, br.buffered());
|
peekLength = max(peekLength, br.buffered());
|
||||||
const peekBuf = await br.peek(peekLength);
|
const peekBuf = await br.peek(peekLength);
|
||||||
if (peekBuf === Deno.EOF) {
|
if (peekBuf === Deno.EOF) {
|
||||||
throw new UnexpectedEOFError();
|
throw new Deno.errors.UnexpectedEof();
|
||||||
}
|
}
|
||||||
const eof = peekBuf.length < peekLength;
|
const eof = peekBuf.length < peekLength;
|
||||||
this.n = scanUntilBoundary(
|
this.n = scanUntilBoundary(
|
||||||
|
@ -352,14 +352,14 @@ export class MultipartReader {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const line = await this.bufReader.readSlice("\n".charCodeAt(0));
|
const line = await this.bufReader.readSlice("\n".charCodeAt(0));
|
||||||
if (line === Deno.EOF) {
|
if (line === Deno.EOF) {
|
||||||
throw new UnexpectedEOFError();
|
throw new Deno.errors.UnexpectedEof();
|
||||||
}
|
}
|
||||||
if (this.isBoundaryDelimiterLine(line)) {
|
if (this.isBoundaryDelimiterLine(line)) {
|
||||||
this.partsRead++;
|
this.partsRead++;
|
||||||
const r = new TextProtoReader(this.bufReader);
|
const r = new TextProtoReader(this.bufReader);
|
||||||
const headers = await r.readMIMEHeader();
|
const headers = await r.readMIMEHeader();
|
||||||
if (headers === Deno.EOF) {
|
if (headers === Deno.EOF) {
|
||||||
throw new UnexpectedEOFError();
|
throw new Deno.errors.UnexpectedEof();
|
||||||
}
|
}
|
||||||
const np = new PartReader(this, headers);
|
const np = new PartReader(this, headers);
|
||||||
this.currentPart = np;
|
this.currentPart = np;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
import { BufReader, UnexpectedEOFError } from "../io/bufio.ts";
|
import { BufReader } from "../io/bufio.ts";
|
||||||
import { charCode } from "../io/util.ts";
|
import { charCode } from "../io/util.ts";
|
||||||
|
|
||||||
const asciiDecoder = new TextDecoder();
|
const asciiDecoder = new TextDecoder();
|
||||||
|
@ -15,13 +15,6 @@ function str(buf: Uint8Array | null | undefined): string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ProtocolError extends Error {
|
|
||||||
constructor(msg: string) {
|
|
||||||
super(msg);
|
|
||||||
this.name = "ProtocolError";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function append(a: Uint8Array, b: Uint8Array): Uint8Array {
|
export function append(a: Uint8Array, b: Uint8Array): Uint8Array {
|
||||||
if (a == null) {
|
if (a == null) {
|
||||||
return b;
|
return b;
|
||||||
|
@ -79,16 +72,16 @@ export class TextProtoReader {
|
||||||
|
|
||||||
buf = await this.r.peek(1);
|
buf = await this.r.peek(1);
|
||||||
if (buf === Deno.EOF) {
|
if (buf === Deno.EOF) {
|
||||||
throw new UnexpectedEOFError();
|
throw new Deno.errors.UnexpectedEof();
|
||||||
} else if (buf[0] == charCode(" ") || buf[0] == charCode("\t")) {
|
} else if (buf[0] == charCode(" ") || buf[0] == charCode("\t")) {
|
||||||
throw new ProtocolError(
|
throw new Deno.errors.InvalidData(
|
||||||
`malformed MIME header initial line: ${str(line)}`
|
`malformed MIME header initial line: ${str(line)}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const kv = await this.readLineSlice(); // readContinuedLineSlice
|
const kv = await this.readLineSlice(); // readContinuedLineSlice
|
||||||
if (kv === Deno.EOF) throw new UnexpectedEOFError();
|
if (kv === Deno.EOF) throw new Deno.errors.UnexpectedEof();
|
||||||
if (kv.byteLength === 0) return m;
|
if (kv.byteLength === 0) return m;
|
||||||
|
|
||||||
// Key ends at first colon; should not have trailing spaces
|
// Key ends at first colon; should not have trailing spaces
|
||||||
|
@ -96,7 +89,9 @@ export class TextProtoReader {
|
||||||
// them if present.
|
// them if present.
|
||||||
let i = kv.indexOf(charCode(":"));
|
let i = kv.indexOf(charCode(":"));
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
throw new ProtocolError(`malformed MIME header line: ${str(kv)}`);
|
throw new Deno.errors.InvalidData(
|
||||||
|
`malformed MIME header line: ${str(kv)}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let endKey = i;
|
let endKey = i;
|
||||||
while (endKey > 0 && kv[endKey - 1] == charCode(" ")) {
|
while (endKey > 0 && kv[endKey - 1] == charCode(" ")) {
|
||||||
|
@ -108,7 +103,7 @@ export class TextProtoReader {
|
||||||
|
|
||||||
// As per RFC 7230 field-name is a token,
|
// As per RFC 7230 field-name is a token,
|
||||||
// tokens consist of one or more chars.
|
// tokens consist of one or more chars.
|
||||||
// We could return a ProtocolError here,
|
// We could throw `Deno.errors.InvalidData` here,
|
||||||
// but better to be liberal in what we
|
// but better to be liberal in what we
|
||||||
// accept, so if we get an empty key, skip it.
|
// accept, so if we get an empty key, skip it.
|
||||||
if (key == "") {
|
if (key == "") {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
import { BufReader } from "../io/bufio.ts";
|
import { BufReader } from "../io/bufio.ts";
|
||||||
import { TextProtoReader, ProtocolError } from "./mod.ts";
|
import { TextProtoReader } from "./mod.ts";
|
||||||
import { stringsReader } from "../io/util.ts";
|
import { stringsReader } from "../io/util.ts";
|
||||||
import {
|
import {
|
||||||
assert,
|
assert,
|
||||||
|
@ -134,7 +134,7 @@ test({
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
err = e;
|
err = e;
|
||||||
}
|
}
|
||||||
assert(err instanceof ProtocolError);
|
assert(err instanceof Deno.errors.InvalidData);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ test({
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
err = e;
|
err = e;
|
||||||
}
|
}
|
||||||
assert(err instanceof ProtocolError);
|
assert(err instanceof Deno.errors.InvalidData);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import { decode, encode } from "../strings/mod.ts";
|
import { decode, encode } from "../strings/mod.ts";
|
||||||
import { hasOwnProperty } from "../util/has_own_property.ts";
|
import { hasOwnProperty } from "../util/has_own_property.ts";
|
||||||
import { BufReader, BufWriter, UnexpectedEOFError } from "../io/bufio.ts";
|
import { BufReader, BufWriter } from "../io/bufio.ts";
|
||||||
import { readLong, readShort, sliceLongToBytes } from "../io/ioutil.ts";
|
import { readLong, readShort, sliceLongToBytes } from "../io/ioutil.ts";
|
||||||
import { Sha1 } from "./sha1.ts";
|
import { Sha1 } from "./sha1.ts";
|
||||||
import { writeResponse } from "../http/io.ts";
|
import { writeResponse } from "../http/io.ts";
|
||||||
|
@ -71,12 +71,6 @@ export function append(a: Uint8Array, b: Uint8Array): Uint8Array {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SocketClosedError extends Error {
|
|
||||||
constructor(msg = "Socket has already been closed") {
|
|
||||||
super(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WebSocketFrame {
|
export interface WebSocketFrame {
|
||||||
isLastFrame: boolean;
|
isLastFrame: boolean;
|
||||||
opcode: OpCode;
|
opcode: OpCode;
|
||||||
|
@ -91,20 +85,20 @@ export interface WebSocket {
|
||||||
receive(): AsyncIterableIterator<WebSocketEvent>;
|
receive(): AsyncIterableIterator<WebSocketEvent>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws SocketClosedError
|
* @throws `Deno.errors.ConnectionReset`
|
||||||
*/
|
*/
|
||||||
send(data: WebSocketMessage): Promise<void>;
|
send(data: WebSocketMessage): Promise<void>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param data
|
* @param data
|
||||||
* @throws SocketClosedError
|
* @throws `Deno.errors.ConnectionReset`
|
||||||
*/
|
*/
|
||||||
ping(data?: WebSocketMessage): Promise<void>;
|
ping(data?: WebSocketMessage): Promise<void>;
|
||||||
|
|
||||||
/** Close connection after sending close frame to peer.
|
/** Close connection after sending close frame to peer.
|
||||||
* This is canonical way of disconnection but it may hang because of peer's response delay.
|
* This is canonical way of disconnection but it may hang because of peer's response delay.
|
||||||
* Default close code is 1000 (Normal Closure)
|
* Default close code is 1000 (Normal Closure)
|
||||||
* @throws SocketClosedError
|
* @throws `Deno.errors.ConnectionReset`
|
||||||
*/
|
*/
|
||||||
close(): Promise<void>;
|
close(): Promise<void>;
|
||||||
close(code: number): Promise<void>;
|
close(code: number): Promise<void>;
|
||||||
|
@ -164,8 +158,8 @@ export async function writeFrame(
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Read websocket frame from given BufReader
|
/** Read websocket frame from given BufReader
|
||||||
* @throws UnexpectedEOFError When peer closed connection without close frame
|
* @throws `Deno.errors.UnexpectedEof` When peer closed connection without close frame
|
||||||
* @throws Error Frame is invalid
|
* @throws `Error` Frame is invalid
|
||||||
*/
|
*/
|
||||||
export async function readFrame(buf: BufReader): Promise<WebSocketFrame> {
|
export async function readFrame(buf: BufReader): Promise<WebSocketFrame> {
|
||||||
let b = assertNotEOF(await buf.readByte());
|
let b = assertNotEOF(await buf.readByte());
|
||||||
|
@ -318,7 +312,7 @@ class WebSocketImpl implements WebSocket {
|
||||||
|
|
||||||
private enqueue(frame: WebSocketFrame): Promise<void> {
|
private enqueue(frame: WebSocketFrame): Promise<void> {
|
||||||
if (this._isClosed) {
|
if (this._isClosed) {
|
||||||
throw new SocketClosedError();
|
throw new Deno.errors.ConnectionReset("Socket has already been closed");
|
||||||
}
|
}
|
||||||
const d = deferred<void>();
|
const d = deferred<void>();
|
||||||
this.sendQueue.push({ d, frame });
|
this.sendQueue.push({ d, frame });
|
||||||
|
@ -397,7 +391,11 @@ class WebSocketImpl implements WebSocket {
|
||||||
this._isClosed = true;
|
this._isClosed = true;
|
||||||
const rest = this.sendQueue;
|
const rest = this.sendQueue;
|
||||||
this.sendQueue = [];
|
this.sendQueue = [];
|
||||||
rest.forEach(e => e.d.reject(new SocketClosedError()));
|
rest.forEach(e =>
|
||||||
|
e.d.reject(
|
||||||
|
new Deno.errors.ConnectionReset("Socket has already been closed")
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -495,7 +493,7 @@ export async function handshake(
|
||||||
const tpReader = new TextProtoReader(bufReader);
|
const tpReader = new TextProtoReader(bufReader);
|
||||||
const statusLine = await tpReader.readLine();
|
const statusLine = await tpReader.readLine();
|
||||||
if (statusLine === Deno.EOF) {
|
if (statusLine === Deno.EOF) {
|
||||||
throw new UnexpectedEOFError();
|
throw new Deno.errors.UnexpectedEof();
|
||||||
}
|
}
|
||||||
const m = statusLine.match(/^(?<version>\S+) (?<statusCode>\S+) /);
|
const m = statusLine.match(/^(?<version>\S+) (?<statusCode>\S+) /);
|
||||||
if (!m) {
|
if (!m) {
|
||||||
|
@ -513,7 +511,7 @@ export async function handshake(
|
||||||
|
|
||||||
const responseHeaders = await tpReader.readMIMEHeader();
|
const responseHeaders = await tpReader.readMIMEHeader();
|
||||||
if (responseHeaders === Deno.EOF) {
|
if (responseHeaders === Deno.EOF) {
|
||||||
throw new UnexpectedEOFError();
|
throw new Deno.errors.UnexpectedEof();
|
||||||
}
|
}
|
||||||
|
|
||||||
const expectedSecAccept = createSecAccept(key);
|
const expectedSecAccept = createSecAccept(key);
|
||||||
|
|
|
@ -14,8 +14,7 @@ import {
|
||||||
readFrame,
|
readFrame,
|
||||||
unmask,
|
unmask,
|
||||||
writeFrame,
|
writeFrame,
|
||||||
createWebSocket,
|
createWebSocket
|
||||||
SocketClosedError
|
|
||||||
} from "./mod.ts";
|
} from "./mod.ts";
|
||||||
import { encode, decode } from "../strings/mod.ts";
|
import { encode, decode } from "../strings/mod.ts";
|
||||||
import Writer = Deno.Writer;
|
import Writer = Deno.Writer;
|
||||||
|
@ -331,7 +330,7 @@ test("[ws] createSecKeyHasCorrectLength", () => {
|
||||||
assertEquals(atob(secKey).length, 16);
|
assertEquals(atob(secKey).length, 16);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("[ws] WebSocket should throw SocketClosedError when peer closed connection without close frame", async () => {
|
test("[ws] WebSocket should throw `Deno.errors.ConnectionReset` when peer closed connection without close frame", async () => {
|
||||||
const buf = new Buffer();
|
const buf = new Buffer();
|
||||||
const eofReader: Deno.Reader = {
|
const eofReader: Deno.Reader = {
|
||||||
async read(_: Uint8Array): Promise<number | Deno.EOF> {
|
async read(_: Uint8Array): Promise<number | Deno.EOF> {
|
||||||
|
@ -341,12 +340,15 @@ test("[ws] WebSocket should throw SocketClosedError when peer closed connection
|
||||||
const conn = dummyConn(eofReader, buf);
|
const conn = dummyConn(eofReader, buf);
|
||||||
const sock = createWebSocket({ conn });
|
const sock = createWebSocket({ conn });
|
||||||
sock.closeForce();
|
sock.closeForce();
|
||||||
await assertThrowsAsync(() => sock.send("hello"), SocketClosedError);
|
await assertThrowsAsync(
|
||||||
await assertThrowsAsync(() => sock.ping(), SocketClosedError);
|
() => sock.send("hello"),
|
||||||
await assertThrowsAsync(() => sock.close(0), SocketClosedError);
|
Deno.errors.ConnectionReset
|
||||||
|
);
|
||||||
|
await assertThrowsAsync(() => sock.ping(), Deno.errors.ConnectionReset);
|
||||||
|
await assertThrowsAsync(() => sock.close(0), Deno.errors.ConnectionReset);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("[ws] WebSocket shouldn't throw UnexpectedEOFError on recive()", async () => {
|
test("[ws] WebSocket shouldn't throw `Deno.errors.UnexpectedEof` on recive()", async () => {
|
||||||
const buf = new Buffer();
|
const buf = new Buffer();
|
||||||
const eofReader: Deno.Reader = {
|
const eofReader: Deno.Reader = {
|
||||||
async read(_: Uint8Array): Promise<number | Deno.EOF> {
|
async read(_: Uint8Array): Promise<number | Deno.EOF> {
|
||||||
|
@ -382,8 +384,8 @@ test("[ws] WebSocket should reject sending promise when connection reset forcely
|
||||||
sock.closeForce();
|
sock.closeForce();
|
||||||
assertEquals(sock.isClosed, true);
|
assertEquals(sock.isClosed, true);
|
||||||
const [a, b, c] = await p;
|
const [a, b, c] = await p;
|
||||||
assert(a instanceof SocketClosedError);
|
assert(a instanceof Deno.errors.ConnectionReset);
|
||||||
assert(b instanceof SocketClosedError);
|
assert(b instanceof Deno.errors.ConnectionReset);
|
||||||
assert(c instanceof SocketClosedError);
|
assert(c instanceof Deno.errors.ConnectionReset);
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue