diff options
Diffstat (limited to 'http/server_test.ts')
| -rw-r--r-- | http/server_test.ts | 443 |
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; + } } }); |
