mirror of
https://github.com/denoland/deno.git
synced 2025-08-04 19:08:15 +00:00
fix(ext/node): work correctly with wrapper Response objects, use correct rawHeaders
structure (#29056)
Fixes https://github.com/denoland/deno/issues/28022 Basically drizzle-kit studio uses hono with the node-server adapter. That creates wrapper objects for responses that forward property getters to the underlying response (the one we provided). However, in deno.serve we were assuming that the response was actually the same response we initially gave and crashed when it wasn't. instead, just call the property getters if we can't find the inner response. The raw headers bug is that we were exposing the `rawHeaders` field on `Incoming` as a `Headers` object, instead it's supposed to be a flat array of the header keys + values. I.e. `["Content-Type:", "application/json", "Host:", "http://localhost"]`
This commit is contained in:
parent
c22d17824b
commit
05574665b2
6 changed files with 253 additions and 8 deletions
|
@ -58,6 +58,7 @@ import {
|
|||
ResponsePrototype,
|
||||
toInnerResponse,
|
||||
} from "ext:deno_fetch/23_response.js";
|
||||
import { headerListFromHeaders } from "ext:deno_fetch/20_headers.js";
|
||||
import {
|
||||
abortRequest,
|
||||
fromInnerRequest,
|
||||
|
@ -500,8 +501,15 @@ function fastSyncResponseOrStream(
|
|||
return;
|
||||
}
|
||||
|
||||
const stream = respBody.streamOrStatic;
|
||||
const body = stream.body;
|
||||
let stream;
|
||||
let body;
|
||||
if (respBody.streamOrStatic) {
|
||||
stream = respBody.streamOrStatic;
|
||||
body = stream.body;
|
||||
} else {
|
||||
stream = respBody;
|
||||
body = respBody;
|
||||
}
|
||||
if (body !== undefined) {
|
||||
// We ensure the response has not been consumed yet in the caller of this
|
||||
// function.
|
||||
|
@ -632,8 +640,19 @@ function mapToCallback(context, callback, onError) {
|
|||
return;
|
||||
}
|
||||
|
||||
const status = inner.status;
|
||||
const headers = inner.headerList;
|
||||
let status;
|
||||
let headers;
|
||||
let body;
|
||||
if (inner) {
|
||||
status = inner.status;
|
||||
headers = inner.headerList;
|
||||
body = inner.body;
|
||||
} else {
|
||||
status = response.status;
|
||||
headers = headerListFromHeaders(response.headers);
|
||||
body = response.body;
|
||||
}
|
||||
|
||||
if (headers && headers.length > 0) {
|
||||
if (headers.length == 1) {
|
||||
op_http_set_response_header(req, headers[0][0], headers[0][1]);
|
||||
|
@ -642,7 +661,7 @@ function mapToCallback(context, callback, onError) {
|
|||
}
|
||||
}
|
||||
|
||||
fastSyncResponseOrStream(req, inner.body, status, innerRequest);
|
||||
fastSyncResponseOrStream(req, body, status, innerRequest);
|
||||
};
|
||||
|
||||
if (TRACING_ENABLED) {
|
||||
|
|
|
@ -1780,6 +1780,8 @@ Object.defineProperty(ServerResponse.prototype, "connection", {
|
|||
),
|
||||
});
|
||||
|
||||
const kRawHeaders = Symbol("rawHeaders");
|
||||
|
||||
// TODO(@AaronO): optimize
|
||||
export class IncomingMessageForServer extends NodeReadable {
|
||||
#headers: Record<string, string>;
|
||||
|
@ -1819,7 +1821,7 @@ export class IncomingMessageForServer extends NodeReadable {
|
|||
this.method = "";
|
||||
this.socket = socket;
|
||||
this.upgrade = null;
|
||||
this.rawHeaders = [];
|
||||
this[kRawHeaders] = [];
|
||||
socket?.on("error", (e) => {
|
||||
if (this.listenerCount("error") > 0) {
|
||||
this.emit("error", e);
|
||||
|
@ -1842,7 +1844,7 @@ export class IncomingMessageForServer extends NodeReadable {
|
|||
get headers() {
|
||||
if (!this.#headers) {
|
||||
this.#headers = {};
|
||||
const entries = headersEntries(this.rawHeaders);
|
||||
const entries = headersEntries(this[kRawHeaders]);
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
const entry = entries[i];
|
||||
this.#headers[entry[0]] = entry[1];
|
||||
|
@ -1855,6 +1857,16 @@ export class IncomingMessageForServer extends NodeReadable {
|
|||
this.#headers = val;
|
||||
}
|
||||
|
||||
get rawHeaders() {
|
||||
const entries = headersEntries(this[kRawHeaders]);
|
||||
const out = new Array(entries.length * 2);
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
out[i * 2] = entries[i][0];
|
||||
out[i * 2 + 1] = entries[i][1];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// connection is deprecated, but still tested in unit test.
|
||||
get connection() {
|
||||
return this.socket;
|
||||
|
@ -1959,7 +1971,7 @@ export class ServerImpl extends EventEmitter {
|
|||
req.upgrade =
|
||||
request.headers.get("connection")?.toLowerCase().includes("upgrade") &&
|
||||
request.headers.get("upgrade");
|
||||
req.rawHeaders = request.headers;
|
||||
req[kRawHeaders] = request.headers;
|
||||
|
||||
if (req.upgrade && this.listenerCount("upgrade") > 0) {
|
||||
const { conn, response } = upgradeHttpRaw(request);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue