summaryrefslogtreecommitdiff
path: root/http/server_test.ts
diff options
context:
space:
mode:
authorYusuke Sakurai <kerokerokerop@gmail.com>2019-02-16 01:03:57 +0900
committerRyan Dahl <ry@tinyclouds.org>2019-02-15 11:03:57 -0500
commit57f4e6a86448263c9f1c75934e829e048c76f572 (patch)
treeb4e46dcb4a43fec2694e289702fba2cd5e475c50 /http/server_test.ts
parent34ece9f2ede9c63af2678feb15ef5290a74c8d2f (diff)
Redesign of http server module (denoland/deno_std#188)
Original: https://github.com/denoland/deno_std/commit/8569f15207bdc12c2c8ca81e9d020955be54918b
Diffstat (limited to 'http/server_test.ts')
-rw-r--r--http/server_test.ts399
1 files changed, 233 insertions, 166 deletions
diff --git a/http/server_test.ts b/http/server_test.ts
index 099547d0c..f8aca487c 100644
--- a/http/server_test.ts
+++ b/http/server_test.ts
@@ -5,19 +5,26 @@
// Ported from
// https://github.com/golang/go/blob/master/src/net/http/responsewrite_test.go
-import { Buffer } from "deno";
-import { assertEqual, test } from "../testing/mod.ts";
-import { Response, ServerRequest } from "./server.ts";
-import { BufReader, BufWriter } from "../io/bufio.ts";
+import { Buffer, copy, Reader } from "deno";
+import { assert, assertEqual, test } from "../testing/mod.ts";
+import {
+ createResponder,
+ createServer,
+ 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";
interface ResponseTest {
- response: Response;
+ response: ServerResponse;
raw: string;
}
-const enc = new TextEncoder();
-const dec = new TextDecoder();
-
const responseTests: ResponseTest[] = [
// Default response
{
@@ -28,7 +35,7 @@ const responseTests: ResponseTest[] = [
{
response: {
status: 200,
- body: new Buffer(new TextEncoder().encode("abcdef"))
+ body: new Buffer(encode("abcdef"))
},
raw:
@@ -38,181 +45,241 @@ const responseTests: ResponseTest[] = [
}
];
-test(async function responseWrite() {
- for (const testCase of responseTests) {
+test(async function httpWriteResponse() {
+ for (const { raw, response } of responseTests) {
const buf = new Buffer();
- const bufw = new BufWriter(buf);
- const request = new ServerRequest();
- request.w = bufw;
-
- await request.respond(testCase.response);
- assertEqual(buf.toString(), testCase.raw);
+ await writeResponse(buf, response);
+ assertEqual(buf.toString(), raw);
}
});
-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(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);
+});
- // 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 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 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;
+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");
}
- 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);
- }
-
- // 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;
+ {
+ 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"));
}
- 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);
+ } finally {
+ cancel.resolve();
}
});
-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 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");
+});
- // 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 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 httpServerResponderRespondJson() {
+ const w = new Buffer();
+ const res = createResponder(w);
+ const json = {
+ id: 1,
+ deno: {
+ is: "land"
}
- }
+ };
+ 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");
+});
+
+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 requestBodyStreamWithTransferEncoding() {
+test(async function httpServerResponderShouldThrow() {
+ const w = new Buffer();
{
- 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;
- }
+ 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"
+ );
}
-
- // 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;
- }
- 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;
- }
+ 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 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"
+ );
}
});