Skip to content

Commit e60efad

Browse files
authored
Clarify and fix use of @internal Request response headers (#59)
2 parents d47b291 + 3621325 commit e60efad

File tree

4 files changed

+28
-19
lines changed

4 files changed

+28
-19
lines changed

src/Request.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,9 @@ export class Request<A> {
261261
}
262262

263263
/**
264-
* Response headers that the Response to this request should include.
264+
* Set in advance response headers that the Response to this request should include. Do not use if a Response
265+
* context is available (use {@link Response#headers} instead). Responses cannot see these headers and may overwrite
266+
* them if there is a collision.
265267
* @internal
266268
*/
267269
public _responseHeaders = new Headers();

src/response/BufferResponse.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,23 @@ export abstract class BufferResponse<A> extends Response<A> {
99
/**
1010
* Fetch the buffer to send in the response body.
1111
*/
12-
protected abstract readBuffer(): Uint8Array | Promise<Uint8Array>;
12+
protected abstract readonly buffer: Uint8Array;
1313

14-
protected override async send(res: http.ServerResponse, req?: Request<A>): Promise<void> {
15-
const buffer = await this.readBuffer();
14+
public override allHeaders(res: http.ServerResponse, req?: Request<A>) {
15+
const headers = super.allHeaders(res, req);
1616
if (req !== undefined) {
17-
if (res.chunkedEncoding)
18-
req._responseHeaders.set("transfer-encoding", "chunked");
19-
else
20-
req._responseHeaders.set("content-length", buffer.byteLength.toString());
17+
if (res.chunkedEncoding) {
18+
if (!headers.has("transfer-encoding"))
19+
headers.set("transfer-encoding", "chunked");
20+
}
21+
else if (!headers.has("content-length"))
22+
headers.set("content-length", this.buffer.byteLength.toString());
2123
}
24+
return headers;
25+
}
26+
27+
protected override async send(res: http.ServerResponse, req?: Request<A>): Promise<void> {
2228
this.writeHead(res, req);
23-
res.end(buffer);
29+
res.end(this.buffer);
2430
}
2531
}

src/response/Response.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ export abstract class Response<A> {
6767
}
6868

6969
/**
70-
* Set the HTTP response status code and headers.
70+
* Set and send the HTTP response status code and headers. No more headers can be sent after this.
71+
* @final
7172
*/
7273
protected writeHead(res: http.ServerResponse, req?: Request<A>) {
7374
const headers = this.allHeaders(res, req);

src/response/TextResponse.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1+
import http from "node:http";
2+
import {Request} from "../Request.js";
13
import {BufferResponse} from "./BufferResponse.js";
24

35
/**
46
* An HTTP response with a plain text body.
57
*/
68
export class TextResponse<A> extends BufferResponse<A> {
7-
/**
8-
* The plain text body of the response.
9-
*/
10-
protected readonly text: string;
9+
protected override readonly buffer: Uint8Array;
1110
private readonly encoder = new TextEncoder();
1211

1312
/**
@@ -18,12 +17,13 @@ export class TextResponse<A> extends BufferResponse<A> {
1817
*/
1918
public constructor(text: string, statusCode = 200, headers?: HeadersInit) {
2019
super(statusCode, headers);
21-
this.text = text;
22-
if (!this.headers.has("content-type"))
23-
this.headers.set("content-type", "text/plain");
20+
this.buffer = this.encoder.encode(text);
2421
}
2522

26-
public override readBuffer() {
27-
return this.encoder.encode(this.text);
23+
public override allHeaders(res: http.ServerResponse, req?: Request<A>): Headers {
24+
const headers = super.allHeaders(res, req);
25+
if (!headers.has("content-type"))
26+
headers.set("content-type", "text/plain");
27+
return headers;
2828
}
2929
}

0 commit comments

Comments
 (0)