mirror of
https://github.com/denoland/deno.git
synced 2025-01-03 12:58:54 -05:00
fix(runtime/http): Encode and decode headers as byte strings in the HTTP server (#11144)
This commit is contained in:
parent
7b9737b9f4
commit
5bf7da91f1
2 changed files with 53 additions and 6 deletions
|
@ -543,3 +543,46 @@ unitTest(
|
||||||
listener.close();
|
listener.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
unitTest({ perms: { net: true } }, async function httpRequestLatin1Headers() {
|
||||||
|
const promise = (async () => {
|
||||||
|
const listener = Deno.listen({ port: 4501 });
|
||||||
|
for await (const conn of listener) {
|
||||||
|
const httpConn = Deno.serveHttp(conn);
|
||||||
|
for await (const { request, respondWith } of httpConn) {
|
||||||
|
assertEquals(request.headers.get("X-Header-Test"), "á");
|
||||||
|
await respondWith(
|
||||||
|
new Response("", { headers: { "X-Header-Test": "Æ" } }),
|
||||||
|
);
|
||||||
|
httpConn.close();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
const clientConn = await Deno.connect({ port: 4501 });
|
||||||
|
const requestText =
|
||||||
|
"GET / HTTP/1.1\r\nHost: 127.0.0.1:4501\r\nX-Header-Test: á\r\n\r\n";
|
||||||
|
const requestBytes = new Uint8Array(requestText.length);
|
||||||
|
for (let i = 0; i < requestText.length; i++) {
|
||||||
|
requestBytes[i] = requestText.charCodeAt(i);
|
||||||
|
}
|
||||||
|
let written = 0;
|
||||||
|
while (written < requestBytes.byteLength) {
|
||||||
|
written += await clientConn.write(requestBytes.slice(written));
|
||||||
|
}
|
||||||
|
|
||||||
|
let responseText = "";
|
||||||
|
const buf = new Uint8Array(1024);
|
||||||
|
let read;
|
||||||
|
while ((read = await clientConn.read(buf)) !== null) {
|
||||||
|
for (let i = 0; i < read; i++) {
|
||||||
|
responseText += String.fromCharCode(buf[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clientConn.close();
|
||||||
|
|
||||||
|
assert(/\r\n[Xx]-[Hh]eader-[Tt]est: Æ\r\n/.test(responseText));
|
||||||
|
|
||||||
|
await promise;
|
||||||
|
});
|
||||||
|
|
|
@ -14,6 +14,7 @@ use deno_core::futures::StreamExt;
|
||||||
use deno_core::op_async;
|
use deno_core::op_async;
|
||||||
use deno_core::op_sync;
|
use deno_core::op_sync;
|
||||||
use deno_core::AsyncRefCell;
|
use deno_core::AsyncRefCell;
|
||||||
|
use deno_core::ByteString;
|
||||||
use deno_core::CancelHandle;
|
use deno_core::CancelHandle;
|
||||||
use deno_core::CancelTryFuture;
|
use deno_core::CancelTryFuture;
|
||||||
use deno_core::Extension;
|
use deno_core::Extension;
|
||||||
|
@ -140,9 +141,11 @@ struct NextRequestResponse(
|
||||||
// response_sender_rid:
|
// response_sender_rid:
|
||||||
ResourceId,
|
ResourceId,
|
||||||
// method:
|
// method:
|
||||||
|
// This is a String rather than a ByteString because reqwest will only return
|
||||||
|
// the method as a str which is guaranteed to be ASCII-only.
|
||||||
String,
|
String,
|
||||||
// headers:
|
// headers:
|
||||||
Vec<(String, String)>,
|
Vec<(ByteString, ByteString)>,
|
||||||
// url:
|
// url:
|
||||||
String,
|
String,
|
||||||
);
|
);
|
||||||
|
@ -199,9 +202,10 @@ async fn op_http_request_next(
|
||||||
|
|
||||||
let mut headers = Vec::with_capacity(req.headers().len());
|
let mut headers = Vec::with_capacity(req.headers().len());
|
||||||
for (name, value) in req.headers().iter() {
|
for (name, value) in req.headers().iter() {
|
||||||
let name = name.to_string();
|
let name: &[u8] = name.as_ref();
|
||||||
let value = value.to_str().unwrap_or("").to_string();
|
let value = value.as_bytes();
|
||||||
headers.push((name, value));
|
headers
|
||||||
|
.push((ByteString(name.to_owned()), ByteString(value.to_owned())));
|
||||||
}
|
}
|
||||||
|
|
||||||
let url = {
|
let url = {
|
||||||
|
@ -346,7 +350,7 @@ struct RespondArgs(
|
||||||
// status:
|
// status:
|
||||||
u16,
|
u16,
|
||||||
// headers:
|
// headers:
|
||||||
Vec<(String, String)>,
|
Vec<(ByteString, ByteString)>,
|
||||||
);
|
);
|
||||||
|
|
||||||
async fn op_http_response(
|
async fn op_http_response(
|
||||||
|
@ -375,7 +379,7 @@ async fn op_http_response(
|
||||||
|
|
||||||
builder.headers_mut().unwrap().reserve(headers.len());
|
builder.headers_mut().unwrap().reserve(headers.len());
|
||||||
for (key, value) in &headers {
|
for (key, value) in &headers {
|
||||||
builder = builder.header(key, value);
|
builder = builder.header(key.as_ref(), value.as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
let res;
|
let res;
|
||||||
|
|
Loading…
Reference in a new issue