diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2022-01-02 14:04:40 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-02 14:04:40 +0100 |
commit | a721c34c19a07ece6677f4efc8aa0db881b310f0 (patch) | |
tree | 10ae7a30ca4a1e2d43d572acc98997109e1ce95c | |
parent | 6ab46b559c7668071c37decfc3fe304e4fb034cb (diff) |
chore: update std submodule to efa94f2 (#13260)
-rw-r--r-- | cli/tests/testdata/045_proxy_test.ts | 28 | ||||
-rw-r--r-- | cli/tests/unit/http_test.ts | 140 | ||||
m--------- | test_util/std | 0 |
3 files changed, 149 insertions, 19 deletions
diff --git a/cli/tests/testdata/045_proxy_test.ts b/cli/tests/testdata/045_proxy_test.ts index 1433b426a..e185b04f0 100644 --- a/cli/tests/testdata/045_proxy_test.ts +++ b/cli/tests/testdata/045_proxy_test.ts @@ -1,35 +1,31 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { - serve, - ServerRequest, -} from "../../../test_util/std/http/server_legacy.ts"; +import { Server } from "../../../test_util/std/http/server.ts"; import { assertEquals } from "../../../test_util/std/testing/asserts.ts"; -const addr = Deno.args[1] || "127.0.0.1:4555"; +const addr = Deno.args[1] || "localhost:4555"; async function proxyServer() { - const server = serve(addr); - + const [hostname, p] = addr.split(":"); + const port = parseInt(p ?? 4555); + const server = new Server({ hostname, port, handler }); console.log(`Proxy server listening on http://${addr}/`); - for await (const req of server) { - proxyRequest(req); - } + await server.listenAndServe(); } -async function proxyRequest(req: ServerRequest) { +async function handler(req: Request): Promise<Response> { console.log(`Proxy request to: ${req.url}`); - const proxyAuthorization = req.headers.get("proxy-authorization"); + const headers = new Headers(req.headers); + const proxyAuthorization = headers.get("proxy-authorization"); if (proxyAuthorization) { console.log(`proxy-authorization: ${proxyAuthorization}`); - req.headers.delete("proxy-authorization"); + headers.delete("proxy-authorization"); } const resp = await fetch(req.url, { method: req.method, - headers: req.headers, + headers: headers, }); - req.respond({ + return new Response(new Uint8Array(await resp.arrayBuffer()), { status: resp.status, - body: new Uint8Array(await resp.arrayBuffer()), headers: resp.headers, }); } diff --git a/cli/tests/unit/http_test.ts b/cli/tests/unit/http_test.ts index a52ea3cc7..4d1ad4ab6 100644 --- a/cli/tests/unit/http_test.ts +++ b/cli/tests/unit/http_test.ts @@ -1,7 +1,9 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { chunkedBodyReader } from "../../../test_util/std/http/_io.ts"; -import { BufReader, BufWriter } from "../../../test_util/std/io/bufio.ts"; -import { Buffer } from "../../../test_util/std/io/buffer.ts"; +import { + Buffer, + BufReader, + BufWriter, +} from "../../../test_util/std/io/buffer.ts"; import { TextProtoReader } from "../../../test_util/std/textproto/mod.ts"; import { assert, @@ -1139,3 +1141,135 @@ Deno.test( await promise; }, ); + +function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader { + // Based on https://tools.ietf.org/html/rfc2616#section-19.4.6 + const tp = new TextProtoReader(r); + let finished = false; + const chunks: Array<{ + offset: number; + data: Uint8Array; + }> = []; + async function read(buf: Uint8Array): Promise<number | null> { + if (finished) return null; + const [chunk] = chunks; + if (chunk) { + const chunkRemaining = chunk.data.byteLength - chunk.offset; + const readLength = Math.min(chunkRemaining, buf.byteLength); + for (let i = 0; i < readLength; i++) { + buf[i] = chunk.data[chunk.offset + i]; + } + chunk.offset += readLength; + if (chunk.offset === chunk.data.byteLength) { + chunks.shift(); + // Consume \r\n; + if ((await tp.readLine()) === null) { + throw new Deno.errors.UnexpectedEof(); + } + } + return readLength; + } + const line = await tp.readLine(); + if (line === null) throw new Deno.errors.UnexpectedEof(); + // TODO(bartlomieju): handle chunk extension + const [chunkSizeString] = line.split(";"); + const chunkSize = parseInt(chunkSizeString, 16); + if (Number.isNaN(chunkSize) || chunkSize < 0) { + throw new Deno.errors.InvalidData("Invalid chunk size"); + } + if (chunkSize > 0) { + if (chunkSize > buf.byteLength) { + let eof = await r.readFull(buf); + if (eof === null) { + throw new Deno.errors.UnexpectedEof(); + } + const restChunk = new Uint8Array(chunkSize - buf.byteLength); + eof = await r.readFull(restChunk); + if (eof === null) { + throw new Deno.errors.UnexpectedEof(); + } else { + chunks.push({ + offset: 0, + data: restChunk, + }); + } + return buf.byteLength; + } else { + const bufToFill = buf.subarray(0, chunkSize); + const eof = await r.readFull(bufToFill); + if (eof === null) { + throw new Deno.errors.UnexpectedEof(); + } + // Consume \r\n + if ((await tp.readLine()) === null) { + throw new Deno.errors.UnexpectedEof(); + } + return chunkSize; + } + } else { + assert(chunkSize === 0); + // Consume \r\n + if ((await r.readLine()) === null) { + throw new Deno.errors.UnexpectedEof(); + } + await readTrailers(h, r); + finished = true; + return null; + } + } + return { read }; +} + +async function readTrailers( + headers: Headers, + r: BufReader, +) { + const trailers = parseTrailer(headers.get("trailer")); + if (trailers == null) return; + const trailerNames = [...trailers.keys()]; + const tp = new TextProtoReader(r); + const result = await tp.readMIMEHeader(); + if (result == null) { + throw new Deno.errors.InvalidData("Missing trailer header."); + } + const undeclared = [...result.keys()].filter( + (k) => !trailerNames.includes(k), + ); + if (undeclared.length > 0) { + throw new Deno.errors.InvalidData( + `Undeclared trailers: ${Deno.inspect(undeclared)}.`, + ); + } + for (const [k, v] of result) { + headers.append(k, v); + } + const missingTrailers = trailerNames.filter((k) => !result.has(k)); + if (missingTrailers.length > 0) { + throw new Deno.errors.InvalidData( + `Missing trailers: ${Deno.inspect(missingTrailers)}.`, + ); + } + headers.delete("trailer"); +} + +function parseTrailer(field: string | null): Headers | undefined { + if (field == null) { + return undefined; + } + const trailerNames = field.split(",").map((v) => v.trim().toLowerCase()); + if (trailerNames.length === 0) { + throw new Deno.errors.InvalidData("Empty trailer header."); + } + const prohibited = trailerNames.filter((k) => isProhibitedForTrailer(k)); + if (prohibited.length > 0) { + throw new Deno.errors.InvalidData( + `Prohibited trailer names: ${Deno.inspect(prohibited)}.`, + ); + } + return new Headers(trailerNames.map((key) => [key, ""])); +} + +function isProhibitedForTrailer(key: string): boolean { + const s = new Set(["transfer-encoding", "content-length", "trailer"]); + return s.has(key.toLowerCase()); +} diff --git a/test_util/std b/test_util/std -Subproject e59b24543e670752701cd6b7d35ebb857d10021 +Subproject efa94f2ccc2df51f9437e14bc5e3455b013b99b |