summaryrefslogtreecommitdiff
path: root/http/server_test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'http/server_test.ts')
-rw-r--r--http/server_test.ts443
1 files changed, 166 insertions, 277 deletions
diff --git a/http/server_test.ts b/http/server_test.ts
index 4f22e4a06..099547d0c 100644
--- a/http/server_test.ts
+++ b/http/server_test.ts
@@ -5,27 +5,19 @@
// Ported from
// https://github.com/golang/go/blob/master/src/net/http/responsewrite_test.go
-import { Buffer, copy, Reader } from "deno";
-import { assert, assertEqual, runTests, test } from "../testing/mod.ts";
-import {
- createResponder,
- createServer,
- findLongestAndNearestMatch,
- readRequest,
- readResponse,
- ServerResponse,
- writeResponse
-} from "./server.ts";
-import { encode } from "../strings/strings.ts";
-import { StringReader } from "../io/readers.ts";
-import { StringWriter } from "../io/writers.ts";
-import { defer } from "../util/deferred.ts";
+import { Buffer } from "deno";
+import { assertEqual, test } from "../testing/mod.ts";
+import { Response, ServerRequest } from "./server.ts";
+import { BufReader, BufWriter } from "../io/bufio.ts";
interface ResponseTest {
- response: ServerResponse;
+ response: Response;
raw: string;
}
+const enc = new TextEncoder();
+const dec = new TextDecoder();
+
const responseTests: ResponseTest[] = [
// Default response
{
@@ -36,7 +28,7 @@ const responseTests: ResponseTest[] = [
{
response: {
status: 200,
- body: new Buffer(encode("abcdef"))
+ body: new Buffer(new TextEncoder().encode("abcdef"))
},
raw:
@@ -46,284 +38,181 @@ const responseTests: ResponseTest[] = [
}
];
-test(async function httpWriteResponse() {
- for (const { raw, response } of responseTests) {
+test(async function responseWrite() {
+ for (const testCase of responseTests) {
const buf = new Buffer();
- await writeResponse(buf, response);
- assertEqual(buf.toString(), raw);
- }
-});
+ const bufw = new BufWriter(buf);
+ const request = new ServerRequest();
+ request.w = bufw;
-test(async function httpReadRequest() {
- const body = "0123456789";
- const lines = [
- "GET /index.html?deno=land HTTP/1.1",
- "Host: deno.land",
- "Content-Type: text/plain",
- `Content-Length: ${body.length}`,
- "\r\n"
- ];
- let msg = lines.join("\r\n");
- msg += body;
- const req = await readRequest(new StringReader(`${msg}`));
- assert.equal(req.url, "/index.html?deno=land");
- assert.equal(req.method, "GET");
- assert.equal(req.proto, "HTTP/1.1");
- assert.equal(req.headers.get("host"), "deno.land");
- assert.equal(req.headers.get("content-type"), "text/plain");
- assert.equal(req.headers.get("content-length"), `${body.length}`);
- const w = new StringWriter();
- await copy(w, req.body);
- assert.equal(w.toString(), body);
+ await request.respond(testCase.response);
+ assertEqual(buf.toString(), testCase.raw);
+ }
});
-test(async function httpReadRequestChunkedBody() {
- const lines = [
- "GET /index.html?deno=land HTTP/1.1",
- "Host: deno.land",
- "Content-Type: text/plain",
- `Transfer-Encoding: chunked`,
- "\r\n"
- ];
- const hd = lines.join("\r\n");
- const buf = new Buffer();
- await buf.write(encode(hd));
- await buf.write(encode("4\r\ndeno\r\n"));
- await buf.write(encode("5\r\n.land\r\n"));
- await buf.write(encode("0\r\n\r\n"));
- const req = await readRequest(buf);
- assert.equal(req.url, "/index.html?deno=land");
- assert.equal(req.method, "GET");
- assert.equal(req.proto, "HTTP/1.1");
- assert.equal(req.headers.get("host"), "deno.land");
- assert.equal(req.headers.get("content-type"), "text/plain");
- assert.equal(req.headers.get("transfer-encoding"), `chunked`);
- const dest = new Buffer();
- await copy(dest, req.body);
- assert.equal(dest.toString(), "deno.land");
-});
+test(async function requestBodyWithContentLength() {
+ {
+ const req = new ServerRequest();
+ req.headers = new Headers();
+ req.headers.set("content-length", "5");
+ const buf = new Buffer(enc.encode("Hello"));
+ req.r = new BufReader(buf);
+ const body = dec.decode(await req.body());
+ assertEqual(body, "Hello");
+ }
-test(function httpMatchNearest() {
- assert.equal(
- findLongestAndNearestMatch("/foo", ["/foo", "/bar", "/f"]).index,
- 0
- );
- assert.equal(
- findLongestAndNearestMatch("/foo", ["/foo", "/foo/bar"]).index,
- 0
- );
- assert.equal(
- findLongestAndNearestMatch("/foo/bar", [
- "/",
- "/foo",
- "/hoo",
- "/hoo/foo/bar",
- "/foo/bar"
- ]).index,
- 4
- );
- assert.equal(
- findLongestAndNearestMatch("/foo/bar/foo", ["/foo", "/foo/bar", "/bar/foo"])
- .index,
- 1
- );
- assert.equal(
- findLongestAndNearestMatch("/foo", ["/", "/hoo", "/hoo/foo"]).index,
- 0
- );
- assert.equal(
- findLongestAndNearestMatch("/deno/land", [/d(.+?)o/, /d(.+?)d/]).index,
- 1
- );
- assert.equal(findLongestAndNearestMatch("/foo", ["/", "/a/foo"]).index, 0);
- assert.equal(
- findLongestAndNearestMatch("/foo", [/\/foo/, /\/bar\/foo/]).index,
- 0
- );
- assert.equal(
- findLongestAndNearestMatch("/foo", [/\/a\/foo/, /\/foo/]).index,
- 1
- );
+ // Larger than internal buf
+ {
+ const longText = "1234\n".repeat(1000);
+ const req = new ServerRequest();
+ req.headers = new Headers();
+ req.headers.set("Content-Length", "5000");
+ const buf = new Buffer(enc.encode(longText));
+ req.r = new BufReader(buf);
+ const body = dec.decode(await req.body());
+ assertEqual(body, longText);
+ }
});
-test(async function httpServer() {
- const server = createServer();
- server.handle("/index", async (req, res) => {
- await res.respond({
- status: 200,
- body: encode("ok")
- });
- });
- server.handle(new RegExp("/foo/(?<id>.+)"), async (req, res) => {
- const { id } = req.match.groups;
- await res.respond({
- status: 200,
- headers: new Headers({
- "content-type": "application/json"
- }),
- body: encode(JSON.stringify({ id }))
- });
- });
- server.handle("/no-response", async (req, res) => {});
- const cancel = defer<void>();
- try {
- server.listen("127.0.0.1:8080", cancel);
- {
- const res1 = await fetch("http://127.0.0.1:8080/index");
- const text = await res1.body.text();
- assert.equal(res1.status, 200);
- assert.equal(text, "ok");
- }
- {
- const res2 = await fetch("http://127.0.0.1:8080/foo/123");
- const json = await res2.body.json();
- assert.equal(res2.status, 200);
- assert.equal(res2.headers.get("content-type"), "application/json");
- assert.equal(json["id"], "123");
- }
- {
- const res = await fetch("http://127.0.0.1:8080/no-response");
- assert.equal(res.status, 500);
- const text = await res.body.text();
- assert.assert(!!text.match("Not Responded"));
- }
- {
- const res = await fetch("http://127.0.0.1:8080/not-found");
- const text = await res.body.text();
- assert.equal(res.status, 404);
- assert.assert(!!text.match("Not Found"));
+test(async function requestBodyWithTransferEncoding() {
+ {
+ const shortText = "Hello";
+ const req = new ServerRequest();
+ req.headers = new Headers();
+ req.headers.set("transfer-encoding", "chunked");
+ let chunksData = "";
+ let chunkOffset = 0;
+ const maxChunkSize = 70;
+ while (chunkOffset < shortText.length) {
+ const chunkSize = Math.min(maxChunkSize, shortText.length - chunkOffset);
+ chunksData += `${chunkSize.toString(16)}\r\n${shortText.substr(
+ chunkOffset,
+ chunkSize
+ )}\r\n`;
+ chunkOffset += chunkSize;
}
- } finally {
- cancel.resolve();
+ chunksData += "0\r\n\r\n";
+ const buf = new Buffer(enc.encode(chunksData));
+ req.r = new BufReader(buf);
+ const body = dec.decode(await req.body());
+ assertEqual(body, shortText);
}
-});
-test(async function httpServerResponder() {
- const w = new Buffer();
- const res = createResponder(w);
- assert.assert(!res.isResponded);
- await res.respond({
- status: 200,
- headers: new Headers({
- "content-type": "text/plain"
- }),
- body: encode("ok")
- });
- assert.assert(res.isResponded);
- const resp = await readResponse(w);
- assert.equal(resp.status, 200);
- assert.equal(resp.headers.get("content-type"), "text/plain");
- const sw = new StringWriter();
- await copy(sw, resp.body as Reader);
- assert.equal(sw.toString(), "ok");
-});
-
-test(async function httpServerResponderRespondJson() {
- const w = new Buffer();
- const res = createResponder(w);
- const json = {
- id: 1,
- deno: {
- is: "land"
+ // Larger than internal buf
+ {
+ const longText = "1234\n".repeat(1000);
+ const req = new ServerRequest();
+ req.headers = new Headers();
+ req.headers.set("transfer-encoding", "chunked");
+ let chunksData = "";
+ let chunkOffset = 0;
+ const maxChunkSize = 70;
+ while (chunkOffset < longText.length) {
+ const chunkSize = Math.min(maxChunkSize, longText.length - chunkOffset);
+ chunksData += `${chunkSize.toString(16)}\r\n${longText.substr(
+ chunkOffset,
+ chunkSize
+ )}\r\n`;
+ chunkOffset += chunkSize;
}
- };
- assert.assert(!res.isResponded);
- await res.respondJson(
- json,
- new Headers({
- deno: "land"
- })
- );
- assert.assert(res.isResponded);
- const resp = await readResponse(w);
- assert.equal(resp.status, 200);
- assert.equal(resp.headers.get("content-type"), "application/json");
- const sw = new StringWriter();
- await copy(sw, resp.body as Reader);
- const resJson = JSON.parse(sw.toString());
- assert.equal(resJson, json);
- assert.equal(resp.headers.get("deno"), "land");
+ chunksData += "0\r\n\r\n";
+ const buf = new Buffer(enc.encode(chunksData));
+ req.r = new BufReader(buf);
+ const body = dec.decode(await req.body());
+ assertEqual(body, longText);
+ }
});
-test(async function httpServerResponderRespondText() {
- const w = new Buffer();
- const res = createResponder(w);
- assert.assert(!res.isResponded);
- await res.respondText(
- "deno.land",
- new Headers({
- deno: "land"
- })
- );
- assert.assert(res.isResponded);
- const resp = await readResponse(w);
- assert.equal(resp.status, 200);
- assert.equal(resp.headers.get("content-type"), "text/plain");
- const sw = new StringWriter();
- await copy(sw, resp.body as Reader);
- assert.equal(sw.toString(), "deno.land");
- assert.equal(resp.headers.get("deno"), "land");
-});
+test(async function requestBodyStreamWithContentLength() {
+ {
+ const shortText = "Hello";
+ const req = new ServerRequest();
+ req.headers = new Headers();
+ req.headers.set("content-length", "" + shortText.length);
+ const buf = new Buffer(enc.encode(shortText));
+ req.r = new BufReader(buf);
+ const it = await req.bodyStream();
+ let offset = 0;
+ for await (const chunk of it) {
+ const s = dec.decode(chunk);
+ assertEqual(shortText.substr(offset, s.length), s);
+ offset += s.length;
+ }
+ }
-test(async function httpServerResponderShouldThrow() {
- const w = new Buffer();
+ // Larger than internal buf
{
- const res = createResponder(w);
- await res.respond({
- body: null
- });
- await assert.throwsAsync(
- async () => res.respond({ body: null }),
- Error,
- "responded"
- );
- await assert.throwsAsync(
- async () => res.respondJson({}),
- Error,
- "responded"
- );
- await assert.throwsAsync(
- async () => res.respondText(""),
- Error,
- "responded"
- );
+ const longText = "1234\n".repeat(1000);
+ const req = new ServerRequest();
+ req.headers = new Headers();
+ req.headers.set("Content-Length", "5000");
+ const buf = new Buffer(enc.encode(longText));
+ req.r = new BufReader(buf);
+ const it = await req.bodyStream();
+ let offset = 0;
+ for await (const chunk of it) {
+ const s = dec.decode(chunk);
+ assertEqual(longText.substr(offset, s.length), s);
+ offset += s.length;
+ }
}
+});
+
+test(async function requestBodyStreamWithTransferEncoding() {
{
- const res = createResponder(w);
- await res.respondText("");
- await assert.throwsAsync(
- async () => res.respond({ body: null }),
- Error,
- "responded"
- );
- await assert.throwsAsync(
- async () => res.respondJson({}),
- Error,
- "responded"
- );
- await assert.throwsAsync(
- async () => res.respondText(""),
- Error,
- "responded"
- );
+ const shortText = "Hello";
+ const req = new ServerRequest();
+ req.headers = new Headers();
+ req.headers.set("transfer-encoding", "chunked");
+ let chunksData = "";
+ let chunkOffset = 0;
+ const maxChunkSize = 70;
+ while (chunkOffset < shortText.length) {
+ const chunkSize = Math.min(maxChunkSize, shortText.length - chunkOffset);
+ chunksData += `${chunkSize.toString(16)}\r\n${shortText.substr(
+ chunkOffset,
+ chunkSize
+ )}\r\n`;
+ chunkOffset += chunkSize;
+ }
+ chunksData += "0\r\n\r\n";
+ const buf = new Buffer(enc.encode(chunksData));
+ req.r = new BufReader(buf);
+ const it = await req.bodyStream();
+ let offset = 0;
+ for await (const chunk of it) {
+ const s = dec.decode(chunk);
+ assertEqual(shortText.substr(offset, s.length), s);
+ offset += s.length;
+ }
}
+
+ // Larger than internal buf
{
- const res = createResponder(w);
- await res.respondJson({});
- await assert.throwsAsync(
- async () => res.respond({ body: null }),
- Error,
- "responded"
- );
- await assert.throwsAsync(
- async () => res.respondJson({}),
- Error,
- "responded"
- );
- await assert.throwsAsync(
- async () => res.respondText(""),
- Error,
- "responded"
- );
+ const longText = "1234\n".repeat(1000);
+ const req = new ServerRequest();
+ req.headers = new Headers();
+ req.headers.set("transfer-encoding", "chunked");
+ let chunksData = "";
+ let chunkOffset = 0;
+ const maxChunkSize = 70;
+ while (chunkOffset < longText.length) {
+ const chunkSize = Math.min(maxChunkSize, longText.length - chunkOffset);
+ chunksData += `${chunkSize.toString(16)}\r\n${longText.substr(
+ chunkOffset,
+ chunkSize
+ )}\r\n`;
+ chunkOffset += chunkSize;
+ }
+ chunksData += "0\r\n\r\n";
+ const buf = new Buffer(enc.encode(chunksData));
+ req.r = new BufReader(buf);
+ const it = await req.bodyStream();
+ let offset = 0;
+ for await (const chunk of it) {
+ const s = dec.decode(chunk);
+ assertEqual(longText.substr(offset, s.length), s);
+ offset += s.length;
+ }
}
});