diff --git a/cli/tests/unit/http_test.ts b/cli/tests/unit/http_test.ts index a27fcbc23e..39bc82fb0e 100644 --- a/cli/tests/unit/http_test.ts +++ b/cli/tests/unit/http_test.ts @@ -854,6 +854,32 @@ Deno.test({ permissions: { net: true } }, async function httpServerPanic() { listener.close(); }); +Deno.test( + { permissions: { net: true, write: true, read: true } }, + async function httpServerCorrectSizeResponse() { + const tmpFile = await Deno.makeTempFile(); + const file = await Deno.open(tmpFile, { write: true, read: true }); + await file.write(new Uint8Array(70 * 1024).fill(1)); // 70kb sent in 64kb + 6kb chunks + file.close(); + const promise = (async () => { + const listener = Deno.listen({ port: 4503 }); + const conn = await listener.accept(); + const httpConn = Deno.serveHttp(conn); + const ev = await httpConn.nextRequest(); + const { respondWith } = ev!; + const f = await Deno.open(tmpFile, { read: true }); + await respondWith(new Response(f.readable, { status: 200 })); + httpConn.close(); + listener.close(); + f.close(); + })(); + const resp = await fetch("http://127.0.0.1:4503/"); + const body = await resp.arrayBuffer(); + assertEquals(body.byteLength, 70 * 1024); + await promise; + }, +); + Deno.test( { permissions: { net: true, write: true, read: true } }, async function httpServerClosedStream() { diff --git a/ext/http/01_http.js b/ext/http/01_http.js index 152241522c..5c9deb5a34 100644 --- a/ext/http/01_http.js +++ b/ext/http/01_http.js @@ -318,13 +318,13 @@ throw error; } } + } - try { - await core.opAsync("op_http_shutdown", streamRid); - } catch (error) { - await reader.cancel(error); - throw error; - } + try { + await core.opAsync("op_http_shutdown", streamRid); + } catch (error) { + await reader.cancel(error); + throw error; } } diff --git a/ext/http/lib.rs b/ext/http/lib.rs index b4a2f0c452..28689654e6 100644 --- a/ext/http/lib.rs +++ b/ext/http/lib.rs @@ -729,7 +729,9 @@ async fn op_http_write_resource( } } HttpResponseWriter::BodyUncompressed(body) => { - if let Err(err) = body.send_data(Bytes::from(buf.to_temp())).await { + let mut buf = buf.to_temp(); + buf.truncate(nread); + if let Err(err) = body.send_data(Bytes::from(buf)).await { assert!(err.is_closed()); // Pull up the failure associated with the transport connection instead. http_stream.conn.closed().await?; @@ -740,19 +742,6 @@ async fn op_http_write_resource( _ => unreachable!(), }; } - - let wr = take(&mut *wr); - if let HttpResponseWriter::Body(mut body_writer) = wr { - match body_writer.shutdown().await { - Ok(_) => {} - Err(err) => { - assert_eq!(err.kind(), std::io::ErrorKind::BrokenPipe); - // Don't return "broken pipe", that's an implementation detail. - // Pull up the failure associated with the transport connection instead. - http_stream.conn.closed().await?; - } - } - } Ok(()) }