mirror of
https://github.com/denoland/deno.git
synced 2024-12-26 09:10:40 -05:00
fix(ext/flash): use utf8 length as Content-Length (#15793)
This commit is contained in:
parent
7f4b043f32
commit
d57f9d560d
4 changed files with 68 additions and 3 deletions
|
@ -495,6 +495,43 @@ Deno.test(
|
|||
},
|
||||
);
|
||||
|
||||
Deno.test(
|
||||
{ permissions: { net: true } },
|
||||
async function httpServerCorrectLengthForUnicodeString() {
|
||||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
|
||||
const server = Deno.serve({
|
||||
handler: () => new Response("韓國".repeat(10)),
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
onError: createOnErrorCb(ac),
|
||||
});
|
||||
|
||||
await listeningPromise;
|
||||
const conn = await Deno.connect({ port: 4503 });
|
||||
const encoder = new TextEncoder();
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
const body =
|
||||
`GET / HTTP/1.1\r\nHost: example.domain\r\nConnection: close\r\n\r\n`;
|
||||
const writeResult = await conn.write(encoder.encode(body));
|
||||
assertEquals(body.length, writeResult);
|
||||
|
||||
const buf = new Uint8Array(1024);
|
||||
const readResult = await conn.read(buf);
|
||||
assert(readResult);
|
||||
const msg = decoder.decode(buf.subarray(0, readResult));
|
||||
|
||||
conn.close();
|
||||
|
||||
ac.abort();
|
||||
await server;
|
||||
assert(msg.includes("Content-Length: 60"));
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test({ permissions: { net: true } }, async function httpServerWebSocket() {
|
||||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
|
|
|
@ -323,6 +323,7 @@
|
|||
opNames: () => ops.op_op_names(),
|
||||
eventLoopHasMoreWork: () => ops.op_event_loop_has_more_work(),
|
||||
setPromiseRejectCallback: (fn) => ops.op_set_promise_reject_callback(fn),
|
||||
byteLength: (str) => ops.op_str_byte_length(str),
|
||||
});
|
||||
|
||||
ObjectAssign(globalThis.__bootstrap, { core });
|
||||
|
|
|
@ -39,6 +39,7 @@ pub(crate) fn init_builtins() -> Extension {
|
|||
op_metrics::decl(),
|
||||
op_format_file_name::decl(),
|
||||
op_is_proxy::decl(),
|
||||
op_str_byte_length::decl(),
|
||||
])
|
||||
.ops(crate::ops_builtin_v8::init_builtins_v8())
|
||||
.build()
|
||||
|
@ -195,3 +196,15 @@ fn op_format_file_name(file_name: String) -> String {
|
|||
fn op_is_proxy(value: serde_v8::Value) -> bool {
|
||||
value.v8_value.is_proxy()
|
||||
}
|
||||
|
||||
#[op(v8)]
|
||||
fn op_str_byte_length(
|
||||
scope: &mut v8::HandleScope,
|
||||
value: serde_v8::Value,
|
||||
) -> u32 {
|
||||
if let Ok(string) = v8::Local::<v8::String>::try_from(value.v8_value) {
|
||||
string.utf8_length(scope) as u32
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,7 +122,14 @@
|
|||
// CRLF
|
||||
// [ message-body ]
|
||||
//
|
||||
function http1Response(method, status, headerList, body, earlyEnd = false) {
|
||||
function http1Response(
|
||||
method,
|
||||
status,
|
||||
headerList,
|
||||
body,
|
||||
bodyLen,
|
||||
earlyEnd = false,
|
||||
) {
|
||||
// HTTP uses a "<major>.<minor>" numbering scheme
|
||||
// HTTP-version = HTTP-name "/" DIGIT "." DIGIT
|
||||
// HTTP-name = %x48.54.54.50 ; "HTTP", case-sensitive
|
||||
|
@ -155,7 +162,7 @@
|
|||
|
||||
// null body status is validated by inititalizeAResponse in ext/fetch
|
||||
if (body !== null && body !== undefined) {
|
||||
str += `Content-Length: ${body.length}\r\n\r\n`;
|
||||
str += `Content-Length: ${bodyLen}\r\n\r\n`;
|
||||
} else {
|
||||
str += "Transfer-Encoding: chunked\r\n\r\n";
|
||||
return str;
|
||||
|
@ -192,6 +199,7 @@
|
|||
server,
|
||||
requestId,
|
||||
response,
|
||||
responseLen,
|
||||
end,
|
||||
respondFast,
|
||||
) {
|
||||
|
@ -215,7 +223,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
if (nwritten < response.length) {
|
||||
if (nwritten < responseLen) {
|
||||
core.opAsync(
|
||||
"op_flash_respond_async",
|
||||
server,
|
||||
|
@ -421,16 +429,19 @@
|
|||
|
||||
const ws = resp[_ws];
|
||||
if (isStreamingResponseBody === false) {
|
||||
const length = respBody.byteLength || core.byteLength(respBody);
|
||||
const responseStr = http1Response(
|
||||
method,
|
||||
innerResp.status ?? 200,
|
||||
innerResp.headerList,
|
||||
respBody,
|
||||
length,
|
||||
);
|
||||
writeFixedResponse(
|
||||
serverId,
|
||||
i,
|
||||
responseStr,
|
||||
length,
|
||||
!ws, // Don't close socket if there is a deferred websocket upgrade.
|
||||
respondFast,
|
||||
);
|
||||
|
@ -460,6 +471,7 @@
|
|||
method,
|
||||
innerResp.status ?? 200,
|
||||
innerResp.headerList,
|
||||
0, // Content-Length will be set by the op.
|
||||
null,
|
||||
true,
|
||||
),
|
||||
|
@ -483,8 +495,10 @@
|
|||
method,
|
||||
innerResp.status ?? 200,
|
||||
innerResp.headerList,
|
||||
respBody.byteLength,
|
||||
null,
|
||||
),
|
||||
respBody.byteLength,
|
||||
false,
|
||||
respondFast,
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue