From 79d5f556ba22d6fa9426825234cc8c49d37caf2c Mon Sep 17 00:00:00 2001 From: Jun Kato Date: Sat, 11 May 2019 01:55:18 +0900 Subject: [PATCH] fix(http): Skip 0 chunks when writing body (#387) --- http/server.ts | 3 +- http/server_test.ts | 68 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/http/server.ts b/http/server.ts index 0892b26f7d..484ecf808d 100644 --- a/http/server.ts +++ b/http/server.ts @@ -1,5 +1,5 @@ // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. -const { listen, toAsyncIterator, copy } = Deno; +const { listen, copy, toAsyncIterator } = Deno; type Conn = Deno.Conn; type Reader = Deno.Reader; type Writer = Deno.Writer; @@ -79,6 +79,7 @@ async function writeChunkedBody(w: Writer, r: Reader): Promise { const encoder = new TextEncoder(); for await (const chunk of toAsyncIterator(r)) { + if (chunk.byteLength <= 0) continue; const start = encoder.encode(`${chunk.byteLength.toString(16)}\r\n`); const end = encoder.encode("\r\n"); await writer.write(start); diff --git a/http/server_test.ts b/http/server_test.ts index 36d704a4d6..82a368395e 100644 --- a/http/server_test.ts +++ b/http/server_test.ts @@ -6,10 +6,11 @@ // https://github.com/golang/go/blob/master/src/net/http/responsewrite_test.go const { Buffer } = Deno; -import { test } from "../testing/mod.ts"; +import { test, runIfMain } from "../testing/mod.ts"; import { assertEquals } from "../testing/asserts.ts"; -import { Response, ServerRequest } from "./server.ts"; +import { Response, ServerRequest, writeResponse } from "./server.ts"; import { BufReader, BufWriter } from "../io/bufio.ts"; +import { StringReader } from "../io/readers.ts"; interface ResponseTest { response: Response; @@ -261,3 +262,66 @@ test(async function requestBodyStreamWithTransferEncoding(): Promise { } } }); + +test(async function writeUint8ArrayResponse(): Promise { + const shortText = "Hello"; + + const body = new TextEncoder().encode(shortText); + const res: Response = { body }; + + const buf = new Deno.Buffer(); + await writeResponse(buf, res); + + const decoder = new TextDecoder("utf-8"); + const reader = new BufReader(buf); + + let line: Uint8Array; + line = (await reader.readLine())[0]; + assertEquals(decoder.decode(line), "HTTP/1.1 200 OK"); + + line = (await reader.readLine())[0]; + assertEquals(decoder.decode(line), `content-length: ${shortText.length}`); + + line = (await reader.readLine())[0]; + assertEquals(line.byteLength, 0); + + line = (await reader.readLine())[0]; + assertEquals(decoder.decode(line), shortText); + + line = (await reader.readLine())[0]; + assertEquals(line.byteLength, 0); +}); + +test(async function writeStringReaderResponse(): Promise { + const shortText = "Hello"; + + const body = new StringReader(shortText); + const res: Response = { body }; + + const buf = new Deno.Buffer(); + await writeResponse(buf, res); + + const decoder = new TextDecoder("utf-8"); + const reader = new BufReader(buf); + + let line: Uint8Array; + line = (await reader.readLine())[0]; + assertEquals(decoder.decode(line), "HTTP/1.1 200 OK"); + + line = (await reader.readLine())[0]; + assertEquals(decoder.decode(line), "transfer-encoding: chunked"); + + line = (await reader.readLine())[0]; + assertEquals(line.byteLength, 0); + + line = (await reader.readLine())[0]; + assertEquals(decoder.decode(line), shortText.length.toString()); + + line = (await reader.readLine())[0]; + assertEquals(decoder.decode(line), shortText); + + line = (await reader.readLine())[0]; + assertEquals(decoder.decode(line), "0"); +}); + +runIfMain(import.meta);