aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Colin McDonnell <colinmcd94@gmail.com> 2023-03-03 14:24:12 -0800
committerGravatar GitHub <noreply@github.com> 2023-03-03 14:24:12 -0800
commit0f8f484e21e3ebafaf62370421f6296eaca262fe (patch)
tree8f5adeacb07ab24a20b7e8c764631e19244ec551
parent7e5dddd2fa3d940ebfff0ba2f24d1789f41212ee (diff)
downloadbun-0f8f484e21e3ebafaf62370421f6296eaca262fe.tar.gz
bun-0f8f484e21e3ebafaf62370421f6296eaca262fe.tar.zst
bun-0f8f484e21e3ebafaf62370421f6296eaca262fe.zip
Improve types for `node:http` (#2284)
* Document node:http * Fix test * Fix default * Fix default
-rw-r--r--packages/bun-types/globals.d.ts8
-rw-r--r--packages/bun-types/http.d.ts935
-rw-r--r--packages/bun-types/net.d.ts418
-rw-r--r--packages/bun-types/stream.d.ts41
-rw-r--r--packages/bun-types/tests/http.test-d.ts27
-rw-r--r--src/bun.js/http.exports.js4
-rw-r--r--test/bun.js/node-http.test.ts20
7 files changed, 1204 insertions, 249 deletions
diff --git a/packages/bun-types/globals.d.ts b/packages/bun-types/globals.d.ts
index 72c8495dc..e44bcf43d 100644
--- a/packages/bun-types/globals.d.ts
+++ b/packages/bun-types/globals.d.ts
@@ -1316,17 +1316,17 @@ declare var performance: {
* Cancel a repeating timer by its timer ID.
* @param id timer id
*/
-declare function clearInterval(id?: number): void;
+declare function clearInterval(id?: number | Timer): void;
/**
* Cancel a delayed function call by its timer ID.
* @param id timer id
*/
-declare function clearTimeout(id?: number): void;
+declare function clearTimeout(id?: number | Timer): void;
/**
* Cancel an immediate function call by its immediate ID.
* @param id immediate id
*/
-declare function clearImmediate(id?: number): void;
+declare function clearImmediate(id?: number | Timer): void;
// declare function createImageBitmap(image: ImageBitmapSource, options?: ImageBitmapOptions): Promise<ImageBitmap>;
// declare function createImageBitmap(image: ImageBitmapSource, sx: number, sy: number, sw: number, sh: number, options?: ImageBitmapOptions): Promise<ImageBitmap>;
/**
@@ -1981,6 +1981,8 @@ interface AbortSignal extends EventTarget {
declare var AbortSignal: {
prototype: AbortSignal;
new (): AbortSignal;
+ abort(reason?: any): AbortSignal;
+ timeout(milliseconds: number): AbortSignal;
};
// type AlgorithmIdentifier = Algorithm | string;
diff --git a/packages/bun-types/http.d.ts b/packages/bun-types/http.d.ts
index a282b621d..30571b4b6 100644
--- a/packages/bun-types/http.d.ts
+++ b/packages/bun-types/http.d.ts
@@ -41,6 +41,9 @@
*/
declare module "http" {
import * as stream from "node:stream";
+
+ import { Socket, TcpSocketConnectOpts, Server as NetServer } from "node:net";
+
// incoming headers will never contain number
interface IncomingHttpHeaders extends Dict<string | string[]> {
accept?: string | undefined;
@@ -111,26 +114,757 @@ declare module "http" {
type OutgoingHttpHeader = number | string | string[];
interface OutgoingHttpHeaders extends Dict<OutgoingHttpHeader> {}
interface ClientRequestArgs {
- signal?: AbortSignal | undefined;
- protocol?: string | null | undefined;
+ agent?: Agent | boolean | undefined;
+ auth?: string | null | undefined;
+ // createConnection?:
+ // | ((
+ // options: ClientRequestArgs,
+ // oncreate: (err: Error, socket: Socket) => void,
+ // ) => Socket)
+ // | undefined;
+ defaultPort?: number | string | undefined;
+ family?: number | undefined;
+ headers?: OutgoingHttpHeaders | undefined;
+ // hints?: LookupOptions["hints"];
host?: string | null | undefined;
hostname?: string | null | undefined;
- family?: number | undefined;
- port?: number | string | null | undefined;
- defaultPort?: number | string | undefined;
+ // insecureHTTPParser?: boolean | undefined;
localAddress?: string | undefined;
- socketPath?: string | undefined;
+ // localPort?: number | undefined;
+ // lookup?: LookupFunction | undefined;
/**
* @default 8192
*/
maxHeaderSize?: number | undefined;
method?: string | undefined;
path?: string | null | undefined;
- headers?: OutgoingHttpHeaders | undefined;
- auth?: string | null | undefined;
- timeout?: number | undefined;
+ port?: number | string | null | undefined;
+ protocol?: string | null | undefined;
setHost?: boolean | undefined;
+ signal?: AbortSignal | undefined;
+ socketPath?: string | undefined;
+ timeout?: number | undefined;
+ // uniqueHeaders?: Array<string | string[]> | undefined;
+ }
+
+ interface ServerOptions<
+ Request extends typeof IncomingMessage = typeof IncomingMessage,
+ Response extends typeof ServerResponse = typeof ServerResponse,
+ > {
+ /**
+ * Specifies the `IncomingMessage` class to be used. Useful for extending the original `IncomingMessage`.
+ */
+ IncomingMessage?: Request | undefined;
+ /**
+ * Specifies the `ServerResponse` class to be used. Useful for extending the original `ServerResponse`.
+ */
+ ServerResponse?: Response | undefined;
+ /**
+ * Sets the timeout value in milliseconds for receiving the entire request from the client.
+ * @see Server.requestTimeout for more information.
+ * @default 300000
+ * @since v18.0.0
+ */
+ requestTimeout?: number | undefined;
+ /**
+ * The number of milliseconds of inactivity a server needs to wait for additional incoming data,
+ * after it has finished writing the last response, before a socket will be destroyed.
+ * @see Server.keepAliveTimeout for more information.
+ * @default 5000
+ * @since v18.0.0
+ */
+ keepAliveTimeout?: number | undefined;
+ /**
+ * Sets the interval value in milliseconds to check for request and headers timeout in incomplete requests.
+ * @default 30000
+ */
+ connectionsCheckingInterval?: number | undefined;
+ /**
+ * Use an insecure HTTP parser that accepts invalid HTTP headers when `true`.
+ * Using the insecure parser should be avoided.
+ * See --insecure-http-parser for more information.
+ * @default false
+ */
+ insecureHTTPParser?: boolean | undefined;
+ /**
+ * Optionally overrides the value of
+ * `--max-http-header-size` for requests received by this server, i.e.
+ * the maximum length of request headers in bytes.
+ * @default 16384
+ * @since v13.3.0
+ */
+ maxHeaderSize?: number | undefined;
+ /**
+ * If set to `true`, it disables the use of Nagle's algorithm immediately after a new incoming connection is received.
+ * @default true
+ * @since v16.5.0
+ */
+ noDelay?: boolean | undefined;
+ /**
+ * If set to `true`, it enables keep-alive functionality on the socket immediately after a new incoming connection is received,
+ * similarly on what is done in `socket.setKeepAlive([enable][, initialDelay])`.
+ * @default false
+ * @since v16.5.0
+ */
+ keepAlive?: boolean | undefined;
+ /**
+ * If set to a positive number, it sets the initial delay before the first keepalive probe is sent on an idle socket.
+ * @default 0
+ * @since v16.5.0
+ */
+ keepAliveInitialDelay?: number | undefined;
+ /**
+ * A list of response headers that should be sent only once.
+ * If the header's value is an array, the items will be joined using `; `.
+ */
+ uniqueHeaders?: Array<string | string[]> | undefined;
}
+ type RequestListener<
+ Request extends typeof IncomingMessage = typeof IncomingMessage,
+ Response extends typeof ServerResponse = typeof ServerResponse,
+ > = (
+ req: InstanceType<Request>,
+ res: InstanceType<Response> & { req: InstanceType<Request> },
+ ) => void;
+ /**
+ * @since v0.1.17
+ */
+ var Server: Server;
+ interface Server<
+ Request extends typeof IncomingMessage = typeof IncomingMessage,
+ Response extends typeof ServerResponse = typeof ServerResponse,
+ > extends NetServer {
+ prototype: Server<Request, Response>;
+
+ new <Req extends typeof IncomingMessage, Res extends typeof ServerResponse>(
+ requestListener?: RequestListener<Req, Res>,
+ ): Server<Req, Res>;
+ new <Req extends typeof IncomingMessage, Res extends typeof ServerResponse>(
+ options: ServerOptions<Req, Res>,
+ requestListener?: RequestListener<Req, Res>,
+ ): Server<Req, Res>;
+ /**
+ * Sets the timeout value for sockets, and emits a `'timeout'` event on
+ * the Server object, passing the socket as an argument, if a timeout
+ * occurs.
+ *
+ * If there is a `'timeout'` event listener on the Server object, then it
+ * will be called with the timed-out socket as an argument.
+ *
+ * By default, the Server does not timeout sockets. However, if a callback
+ * is assigned to the Server's `'timeout'` event, timeouts must be handled
+ * explicitly.
+ * @since v0.9.12
+ * @param [msecs=0 (no timeout)]
+ */
+ // setTimeout(msecs?: number, callback?: () => void): this;
+ // setTimeout(callback: () => void): this;
+ /**
+ * Limits maximum incoming headers count. If set to 0, no limit will be applied.
+ * @since v0.7.0
+ */
+ // maxHeadersCount: number | null;
+ /**
+ * The maximum number of requests socket can handle
+ * before closing keep alive connection.
+ *
+ * A value of `0` will disable the limit.
+ *
+ * When the limit is reached it will set the `Connection` header value to `close`,
+ * but will not actually close the connection, subsequent requests sent
+ * after the limit is reached will get `503 Service Unavailable` as a response.
+ * @since v16.10.0
+ */
+ // maxRequestsPerSocket: number | null;
+ /**
+ * The number of milliseconds of inactivity before a socket is presumed
+ * to have timed out.
+ *
+ * A value of `0` will disable the timeout behavior on incoming connections.
+ *
+ * The socket timeout logic is set up on connection, so changing this
+ * value only affects new connections to the server, not any existing connections.
+ * @since v0.9.12
+ */
+ // timeout: number;
+ /**
+ * Limit the amount of time the parser will wait to receive the complete HTTP
+ * headers.
+ *
+ * If the timeout expires, the server responds with status 408 without
+ * forwarding the request to the request listener and then closes the connection.
+ *
+ * It must be set to a non-zero value (e.g. 120 seconds) to protect against
+ * potential Denial-of-Service attacks in case the server is deployed without a
+ * reverse proxy in front.
+ * @since v11.3.0, v10.14.0
+ */
+ // headersTimeout: number;
+ /**
+ * The number of milliseconds of inactivity a server needs to wait for additional
+ * incoming data, after it has finished writing the last response, before a socket
+ * will be destroyed. If the server receives new data before the keep-alive
+ * timeout has fired, it will reset the regular inactivity timeout, i.e.,`server.timeout`.
+ *
+ * A value of `0` will disable the keep-alive timeout behavior on incoming
+ * connections.
+ * A value of `0` makes the http server behave similarly to Node.js versions prior
+ * to 8.0.0, which did not have a keep-alive timeout.
+ *
+ * The socket timeout logic is set up on connection, so changing this value only
+ * affects new connections to the server, not any existing connections.
+ * @since v8.0.0
+ */
+ // keepAliveTimeout: number;
+ /**
+ * Sets the timeout value in milliseconds for receiving the entire request from
+ * the client.
+ *
+ * If the timeout expires, the server responds with status 408 without
+ * forwarding the request to the request listener and then closes the connection.
+ *
+ * It must be set to a non-zero value (e.g. 120 seconds) to protect against
+ * potential Denial-of-Service attacks in case the server is deployed without a
+ * reverse proxy in front.
+ * @since v14.11.0
+ */
+ // requestTimeout: number;
+ /**
+ * Closes all connections connected to this server.
+ * @since v18.2.0
+ */
+ // closeAllConnections(): void;
+ /**
+ * Closes all connections connected to this server which are not sending a request or waiting for a response.
+ * @since v18.2.0
+ */
+ // closeIdleConnections(): void;
+ addListener(event: string, listener: (...args: any[]) => void): this;
+ addListener(event: "close", listener: () => void): this;
+ addListener(event: "connection", listener: (socket: Socket) => void): this;
+ addListener(event: "error", listener: (err: Error) => void): this;
+ addListener(event: "listening", listener: () => void): this;
+ addListener(
+ event: "checkContinue",
+ listener: RequestListener<Request, Response>,
+ ): this;
+ addListener(
+ event: "checkExpectation",
+ listener: RequestListener<Request, Response>,
+ ): this;
+ addListener(
+ event: "clientError",
+ listener: (err: Error, socket: stream.Duplex) => void,
+ ): this;
+ addListener(
+ event: "connect",
+ listener: (
+ req: InstanceType<Request>,
+ socket: stream.Duplex,
+ head: Buffer,
+ ) => void,
+ ): this;
+ addListener(
+ event: "request",
+ listener: RequestListener<Request, Response>,
+ ): this;
+ addListener(
+ event: "upgrade",
+ listener: (
+ req: InstanceType<Request>,
+ socket: stream.Duplex,
+ head: Buffer,
+ ) => void,
+ ): this;
+ emit(event: string, ...args: any[]): boolean;
+ emit(event: "close"): boolean;
+ emit(event: "connection", socket: Socket): boolean;
+ emit(event: "error", err: Error): boolean;
+ emit(event: "listening"): boolean;
+ emit(
+ event: "checkContinue",
+ req: InstanceType<Request>,
+ res: InstanceType<Response> & { req: InstanceType<Request> },
+ ): boolean;
+ emit(
+ event: "checkExpectation",
+ req: InstanceType<Request>,
+ res: InstanceType<Response> & { req: InstanceType<Request> },
+ ): boolean;
+ emit(event: "clientError", err: Error, socket: stream.Duplex): boolean;
+ emit(
+ event: "connect",
+ req: InstanceType<Request>,
+ socket: stream.Duplex,
+ head: Buffer,
+ ): boolean;
+ emit(
+ event: "request",
+ req: InstanceType<Request>,
+ res: InstanceType<Response> & { req: InstanceType<Request> },
+ ): boolean;
+ emit(
+ event: "upgrade",
+ req: InstanceType<Request>,
+ socket: stream.Duplex,
+ head: Buffer,
+ ): boolean;
+ on(event: string, listener: (...args: any[]) => void): this;
+ on(event: "close", listener: () => void): this;
+ on(event: "connection", listener: (socket: Socket) => void): this;
+ on(event: "error", listener: (err: Error) => void): this;
+ on(event: "listening", listener: () => void): this;
+ on(
+ event: "checkContinue",
+ listener: RequestListener<Request, Response>,
+ ): this;
+ on(
+ event: "checkExpectation",
+ listener: RequestListener<Request, Response>,
+ ): this;
+ on(
+ event: "clientError",
+ listener: (err: Error, socket: stream.Duplex) => void,
+ ): this;
+ on(
+ event: "connect",
+ listener: (
+ req: InstanceType<Request>,
+ socket: stream.Duplex,
+ head: Buffer,
+ ) => void,
+ ): this;
+ on(event: "request", listener: RequestListener<Request, Response>): this;
+ on(
+ event: "upgrade",
+ listener: (
+ req: InstanceType<Request>,
+ socket: stream.Duplex,
+ head: Buffer,
+ ) => void,
+ ): this;
+ once(event: string, listener: (...args: any[]) => void): this;
+ once(event: "close", listener: () => void): this;
+ once(event: "connection", listener: (socket: Socket) => void): this;
+ once(event: "error", listener: (err: Error) => void): this;
+ once(event: "listening", listener: () => void): this;
+ once(
+ event: "checkContinue",
+ listener: RequestListener<Request, Response>,
+ ): this;
+ once(
+ event: "checkExpectation",
+ listener: RequestListener<Request, Response>,
+ ): this;
+ once(
+ event: "clientError",
+ listener: (err: Error, socket: stream.Duplex) => void,
+ ): this;
+ once(
+ event: "connect",
+ listener: (
+ req: InstanceType<Request>,
+ socket: stream.Duplex,
+ head: Buffer,
+ ) => void,
+ ): this;
+ once(event: "request", listener: RequestListener<Request, Response>): this;
+ once(
+ event: "upgrade",
+ listener: (
+ req: InstanceType<Request>,
+ socket: stream.Duplex,
+ head: Buffer,
+ ) => void,
+ ): this;
+ // prependListener(event: string, listener: (...args: any[]) => void): this;
+ // prependListener(event: "close", listener: () => void): this;
+ // prependListener(
+ // event: "connection",
+ // listener: (socket: Socket) => void,
+ // ): this;
+ // prependListener(event: "error", listener: (err: Error) => void): this;
+ // prependListener(event: "listening", listener: () => void): this;
+ // prependListener(
+ // event: "checkContinue",
+ // listener: RequestListener<Request, Response>,
+ // ): this;
+ // prependListener(
+ // event: "checkExpectation",
+ // listener: RequestListener<Request, Response>,
+ // ): this;
+ // prependListener(
+ // event: "clientError",
+ // listener: (err: Error, socket: stream.Duplex) => void,
+ // ): this;
+ // prependListener(
+ // event: "connect",
+ // listener: (
+ // req: InstanceType<Request>,
+ // socket: stream.Duplex,
+ // head: Buffer,
+ // ) => void,
+ // ): this;
+ // prependListener(
+ // event: "request",
+ // listener: RequestListener<Request, Response>,
+ // ): this;
+ // prependListener(
+ // event: "upgrade",
+ // listener: (
+ // req: InstanceType<Request>,
+ // socket: stream.Duplex,
+ // head: Buffer,
+ // ) => void,
+ // ): this;
+ // prependOnceListener(
+ // event: string,
+ // listener: (...args: any[]) => void,
+ // ): this;
+ // prependOnceListener(event: "close", listener: () => void): this;
+ // prependOnceListener(
+ // event: "connection",
+ // listener: (socket: Socket) => void,
+ // ): this;
+ // prependOnceListener(event: "error", listener: (err: Error) => void): this;
+ // prependOnceListener(event: "listening", listener: () => void): this;
+ // prependOnceListener(
+ // event: "checkContinue",
+ // listener: RequestListener<Request, Response>,
+ // ): this;
+ // prependOnceListener(
+ // event: "checkExpectation",
+ // listener: RequestListener<Request, Response>,
+ // ): this;
+ // prependOnceListener(
+ // event: "clientError",
+ // listener: (err: Error, socket: stream.Duplex) => void,
+ // ): this;
+ // prependOnceListener(
+ // event: "connect",
+ // listener: (
+ // req: InstanceType<Request>,
+ // socket: stream.Duplex,
+ // head: Buffer,
+ // ) => void,
+ // ): this;
+ // prependOnceListener(
+ // event: "request",
+ // listener: RequestListener<Request, Response>,
+ // ): this;
+ // prependOnceListener(
+ // event: "upgrade",
+ // listener: (
+ // req: InstanceType<Request>,
+ // socket: stream.Duplex,
+ // head: Buffer,
+ // ) => void,
+ // ): this;
+ }
+ /**
+ * This class serves as the parent class of {@link ClientRequest} and {@link ServerResponse}. It is an abstract of outgoing message from
+ * the perspective of the participants of HTTP transaction.
+ * @since v0.1.17
+ */
+ class OutgoingMessage<
+ Request extends IncomingMessage = IncomingMessage,
+ > extends stream.Writable {
+ readonly req: Request;
+ chunkedEncoding: boolean;
+ shouldKeepAlive: boolean;
+ useChunkedEncodingByDefault: boolean;
+ sendDate: boolean;
+ /**
+ * @deprecated Use `writableEnded` instead.
+ */
+ finished: boolean;
+ /**
+ * Read-only. `true` if the headers were sent, otherwise `false`.
+ * @since v0.9.3
+ */
+ readonly headersSent: boolean;
+ /**
+ * Aliases of `outgoingMessage.socket`
+ * @since v0.3.0
+ * @deprecated Since v15.12.0,v14.17.1 - Use `socket` instead.
+ */
+ readonly connection: Socket | null;
+ /**
+ * Reference to the underlying socket. Usually, users will not want to access
+ * this property.
+ *
+ * After calling `outgoingMessage.end()`, this property will be nulled.
+ * @since v0.3.0
+ */
+ readonly socket: Socket | null;
+ constructor();
+ /**
+ * Once a socket is associated with the message and is connected,`socket.setTimeout()` will be called with `msecs` as the first parameter.
+ * @since v0.9.12
+ * @param callback Optional function to be called when a timeout occurs. Same as binding to the `timeout` event.
+ */
+ setTimeout(msecs: number, callback?: () => void): this;
+ /**
+ * Sets a single header value for the header object.
+ * @since v0.4.0
+ * @param name Header name
+ * @param value Header value
+ */
+ setHeader(
+ name: string,
+ value: number | string | ReadonlyArray<string>,
+ ): this;
+ /**
+ * Gets the value of HTTP header with the given name. If such a name doesn't
+ * exist in message, it will be `undefined`.
+ * @since v0.4.0
+ * @param name Name of header
+ */
+ getHeader(name: string): number | string | string[] | undefined;
+ /**
+ * Returns a shallow copy of the current outgoing headers. Since a shallow
+ * copy is used, array values may be mutated without additional calls to
+ * various header-related HTTP module methods. The keys of the returned
+ * object are the header names and the values are the respective header
+ * values. All header names are lowercase.
+ *
+ * The object returned by the `outgoingMessage.getHeaders()` method does
+ * not prototypically inherit from the JavaScript Object. This means that
+ * typical Object methods such as `obj.toString()`, `obj.hasOwnProperty()`,
+ * and others are not defined and will not work.
+ *
+ * ```js
+ * outgoingMessage.setHeader('Foo', 'bar');
+ * outgoingMessage.setHeader('Set-Cookie', ['foo=bar', 'bar=baz']);
+ *
+ * const headers = outgoingMessage.getHeaders();
+ * // headers === { foo: 'bar', 'set-cookie': ['foo=bar', 'bar=baz'] }
+ * ```
+ * @since v7.7.0
+ */
+ getHeaders(): OutgoingHttpHeaders;
+ /**
+ * Returns an array of names of headers of the outgoing outgoingMessage. All
+ * names are lowercase.
+ * @since v7.7.0
+ */
+ getHeaderNames(): string[];
+ /**
+ * Returns `true` if the header identified by `name` is currently set in the
+ * outgoing headers. The header name is case-insensitive.
+ *
+ * ```js
+ * const hasContentType = outgoingMessage.hasHeader('content-type');
+ * ```
+ * @since v7.7.0
+ */
+ hasHeader(name: string): boolean;
+ /**
+ * Removes a header that is queued for implicit sending.
+ *
+ * ```js
+ * outgoingMessage.removeHeader('Content-Encoding');
+ * ```
+ * @since v0.4.0
+ * @param name Header name
+ */
+ removeHeader(name: string): void;
+ /**
+ * Adds HTTP trailers (headers but at the end of the message) to the message.
+ *
+ * Trailers are **only** be emitted if the message is chunked encoded. If not,
+ * the trailer will be silently discarded.
+ *
+ * HTTP requires the `Trailer` header to be sent to emit trailers,
+ * with a list of header fields in its value, e.g.
+ *
+ * ```js
+ * message.writeHead(200, { 'Content-Type': 'text/plain',
+ * 'Trailer': 'Content-MD5' });
+ * message.write(fileData);
+ * message.addTrailers({ 'Content-MD5': '7895bf4b8828b55ceaf47747b4bca667' });
+ * message.end();
+ * ```
+ *
+ * Attempting to set a header field name or value that contains invalid characters
+ * will result in a `TypeError` being thrown.
+ * @since v0.3.0
+ */
+ addTrailers(
+ headers: OutgoingHttpHeaders | ReadonlyArray<[string, string]>,
+ ): void;
+ /**
+ * Compulsorily flushes the message headers
+ *
+ * For efficiency reason, Node.js normally buffers the message headers
+ * until `outgoingMessage.end()` is called or the first chunk of message data
+ * is written. It then tries to pack the headers and data into a single TCP
+ * packet.
+ *
+ * It is usually desired (it saves a TCP round-trip), but not when the first
+ * data is not sent until possibly much later. `outgoingMessage.flushHeaders()`bypasses the optimization and kickstarts the request.
+ * @since v1.6.0
+ */
+ flushHeaders(): void;
+ }
+ /**
+ * This object is created internally by an HTTP server, not by the user. It is
+ * passed as the second parameter to the `'request'` event.
+ * @since v0.1.17
+ */
+ class ServerResponse<
+ Request extends IncomingMessage = IncomingMessage,
+ > extends OutgoingMessage<Request> {
+ /**
+ * When using implicit headers (not calling `response.writeHead()` explicitly),
+ * this property controls the status code that will be sent to the client when
+ * the headers get flushed.
+ *
+ * ```js
+ * response.statusCode = 404;
+ * ```
+ *
+ * After response header was sent to the client, this property indicates the
+ * status code which was sent out.
+ * @since v0.4.0
+ */
+ statusCode: number;
+ /**
+ * When using implicit headers (not calling `response.writeHead()` explicitly),
+ * this property controls the status message that will be sent to the client when
+ * the headers get flushed. If this is left as `undefined` then the standard
+ * message for the status code will be used.
+ *
+ * ```js
+ * response.statusMessage = 'Not found';
+ * ```
+ *
+ * After response header was sent to the client, this property indicates the
+ * status message which was sent out.
+ * @since v0.11.8
+ */
+ statusMessage: string;
+ constructor(req: Request);
+ assignSocket(socket: Socket): void;
+ detachSocket(socket: Socket): void;
+ /**
+ * Sends an HTTP/1.1 100 Continue message to the client, indicating that
+ * the request body should be sent. See the `'checkContinue'` event on`Server`.
+ * @since v0.3.0
+ */
+ writeContinue(callback?: () => void): void;
+ /**
+ * Sends an HTTP/1.1 103 Early Hints message to the client with a Link header,
+ * indicating that the user agent can preload/preconnect the linked resources.
+ * The `hints` is an object containing the values of headers to be sent with
+ * early hints message. The optional `callback` argument will be called when
+ * the response message has been written.
+ *
+ * Example:
+ *
+ * ```js
+ * const earlyHintsLink = '</styles.css>; rel=preload; as=style';
+ * response.writeEarlyHints({
+ * 'link': earlyHintsLink,
+ * });
+ *
+ * const earlyHintsLinks = [
+ * '</styles.css>; rel=preload; as=style',
+ * '</scripts.js>; rel=preload; as=script',
+ * ];
+ * response.writeEarlyHints({
+ * 'link': earlyHintsLinks,
+ * 'x-trace-id': 'id for diagnostics'
+ * });
+ *
+ * const earlyHintsCallback = () => console.log('early hints message sent');
+ * response.writeEarlyHints({
+ * 'link': earlyHintsLinks
+ * }, earlyHintsCallback);
+ * ```
+ *
+ * @since v18.11.0
+ * @param hints An object containing the values of headers
+ * @param callback Will be called when the response message has been written
+ */
+ writeEarlyHints(
+ hints: Record<string, string | string[]>,
+ callback?: () => void,
+ ): void;
+ /**
+ * Sends a response header to the request. The status code is a 3-digit HTTP
+ * status code, like `404`. The last argument, `headers`, are the response headers.
+ * Optionally one can give a human-readable `statusMessage` as the second
+ * argument.
+ *
+ * `headers` may be an `Array` where the keys and values are in the same list.
+ * It is _not_ a list of tuples. So, the even-numbered offsets are key values,
+ * and the odd-numbered offsets are the associated values. The array is in the same
+ * format as `request.rawHeaders`.
+ *
+ * Returns a reference to the `ServerResponse`, so that calls can be chained.
+ *
+ * ```js
+ * const body = 'hello world';
+ * response
+ * .writeHead(200, {
+ * 'Content-Length': Buffer.byteLength(body),
+ * 'Content-Type': 'text/plain'
+ * })
+ * .end(body);
+ * ```
+ *
+ * This method must only be called once on a message and it must
+ * be called before `response.end()` is called.
+ *
+ * If `response.write()` or `response.end()` are called before calling
+ * this, the implicit/mutable headers will be calculated and call this function.
+ *
+ * When headers have been set with `response.setHeader()`, they will be merged
+ * with any headers passed to `response.writeHead()`, with the headers passed
+ * to `response.writeHead()` given precedence.
+ *
+ * If this method is called and `response.setHeader()` has not been called,
+ * it will directly write the supplied header values onto the network channel
+ * without caching internally, and the `response.getHeader()` on the header
+ * will not yield the expected result. If progressive population of headers is
+ * desired with potential future retrieval and modification, use `response.setHeader()` instead.
+ *
+ * ```js
+ * // Returns content-type = text/plain
+ * const server = http.createServer((req, res) => {
+ * res.setHeader('Content-Type', 'text/html');
+ * res.setHeader('X-Foo', 'bar');
+ * res.writeHead(200, { 'Content-Type': 'text/plain' });
+ * res.end('ok');
+ * });
+ * ```
+ *
+ * `Content-Length` is given in bytes, not characters. Use `Buffer.byteLength()` to determine the length of the body in bytes. Node.js
+ * does not check whether `Content-Length` and the length of the body which has
+ * been transmitted are equal or not.
+ *
+ * Attempting to set a header field name or value that contains invalid characters
+ * will result in a `TypeError` being thrown.
+ * @since v0.1.30
+ */
+ writeHead(
+ statusCode: number,
+ statusMessage?: string,
+ headers?: OutgoingHttpHeaders | OutgoingHttpHeader[],
+ ): this;
+ writeHead(
+ statusCode: number,
+ headers?: OutgoingHttpHeaders | OutgoingHttpHeader[],
+ ): this;
+ /**
+ * Sends an HTTP/1.1 102 Processing message to the client, indicating that
+ * the request body should be sent.
+ * @since v10.0.0
+ */
+ writeProcessing(): void;
+ }
+
interface InformationEvent {
statusCode: number;
statusMessage: string;
@@ -167,7 +901,7 @@ declare module "http" {
* Node.js does not check whether Content-Length and the length of the
* body which has been transmitted are equal or not.
*/
- class ClientRequest {
+ class ClientRequest extends OutgoingMessage {
/**
* The `request.aborted` property will be `true` if the request has
* been aborted.
@@ -231,11 +965,11 @@ declare module "http" {
* retriableRequest();
* ```
*/
- reusedSocket: boolean;
+ // reusedSocket: boolean;
/**
* Limits maximum response headers count. If set to 0, no limit will be applied.
*/
- maxHeadersCount: number;
+ // maxHeadersCount: number;
constructor(
url: string | URL | ClientRequestArgs,
cb?: (res: IncomingMessage) => void,
@@ -253,7 +987,7 @@ declare module "http" {
* in the response to be dropped and the socket to be destroyed.
* @deprecated Since v14.1.0,v13.14.0 - Use `destroy` instead.
*/
- abort(): void;
+ // abort(): void;
/**
* Once a socket is assigned to this request and is connected `socket.setTimeout()` will be called.
* @param timeout Milliseconds before a request times out.
@@ -299,7 +1033,7 @@ declare module "http" {
/**
* Once a socket is assigned to this request and is connected `socket.setNoDelay()` will be called.
*/
- setNoDelay(noDelay?: boolean): void;
+ // setNoDelay(noDelay?: boolean): void;
/**
* Once a socket is assigned to this request and is connected `socket.setKeepAlive()` will be called.
*/
@@ -316,7 +1050,7 @@ declare module "http" {
* // headerNames === ['Foo', 'Set-Cookie']
* ```
*/
- getRawHeaderNames(): string[];
+ // getRawHeaderNames(): string[];
/**
* @deprecated
*/
@@ -595,7 +1329,7 @@ declare module "http" {
* }
* ```
*/
- url?: string | undefined;
+ url: string | undefined;
/**
* **Only valid for response obtained from {@link ClientRequest}.**
*
@@ -614,11 +1348,177 @@ declare module "http" {
*/
destroy(error?: Error): this;
}
+
+ interface AgentOptions extends Partial<TcpSocketConnectOpts> {
+ /**
+ * Keep sockets around in a pool to be used by other requests in the future. Default = false
+ */
+ keepAlive?: boolean | undefined;
+ /**
+ * When using HTTP KeepAlive, how often to send TCP KeepAlive packets over sockets being kept alive. Default = 1000.
+ * Only relevant if keepAlive is set to true.
+ */
+ keepAliveMsecs?: number | undefined;
+ /**
+ * Maximum number of sockets to allow per host. Default for Node 0.10 is 5, default for Node 0.12 is Infinity
+ */
+ maxSockets?: number | undefined;
+ /**
+ * Maximum number of sockets allowed for all hosts in total. Each request will use a new socket until the maximum is reached. Default: Infinity.
+ */
+ maxTotalSockets?: number | undefined;
+ /**
+ * Maximum number of sockets to leave open in a free state. Only relevant if keepAlive is set to true. Default = 256.
+ */
+ maxFreeSockets?: number | undefined;
+ /**
+ * Socket timeout in milliseconds. This will set the timeout after the socket is connected.
+ */
+ // timeout?: number | undefined;
+ /**
+ * Scheduling strategy to apply when picking the next free socket to use.
+ * @default `lifo`
+ */
+ scheduling?: "fifo" | "lifo" | undefined;
+ }
+ /**
+ * An `Agent` is responsible for managing connection persistence
+ * and reuse for HTTP clients. It maintains a queue of pending requests
+ * for a given host and port, reusing a single socket connection for each
+ * until the queue is empty, at which time the socket is either destroyed
+ * or put into a pool where it is kept to be used again for requests to the
+ * same host and port. Whether it is destroyed or pooled depends on the`keepAlive` `option`.
+ *
+ * Pooled connections have TCP Keep-Alive enabled for them, but servers may
+ * still close idle connections, in which case they will be removed from the
+ * pool and a new connection will be made when a new HTTP request is made for
+ * that host and port. Servers may also refuse to allow multiple requests
+ * over the same connection, in which case the connection will have to be
+ * remade for every request and cannot be pooled. The `Agent` will still make
+ * the requests to that server, but each one will occur over a new connection.
+ *
+ * When a connection is closed by the client or the server, it is removed
+ * from the pool. Any unused sockets in the pool will be unrefed so as not
+ * to keep the Node.js process running when there are no outstanding requests.
+ * (see `socket.unref()`).
+ *
+ * It is good practice, to `destroy()` an `Agent` instance when it is no
+ * longer in use, because unused sockets consume OS resources.
+ *
+ * Sockets are removed from an agent when the socket emits either
+ * a `'close'` event or an `'agentRemove'` event. When intending to keep one
+ * HTTP request open for a long time without keeping it in the agent, something
+ * like the following may be done:
+ *
+ * ```js
+ * http.get(options, (res) => {
+ * // Do stuff
+ * }).on('socket', (socket) => {
+ * socket.emit('agentRemove');
+ * });
+ * ```
+ *
+ * An agent may also be used for an individual request. By providing`{agent: false}` as an option to the `http.get()` or `http.request()`functions, a one-time use `Agent` with default options
+ * will be used
+ * for the client connection.
+ *
+ * `agent:false`:
+ *
+ * ```js
+ * http.get({
+ * hostname: 'localhost',
+ * port: 80,
+ * path: '/',
+ * agent: false // Create a new agent just for this one request
+ * }, (res) => {
+ * // Do stuff with response
+ * });
+ * ```
+ * @since v0.3.4
+ */
+ class Agent {
+ /**
+ * By default set to 256\. For agents with `keepAlive` enabled, this
+ * sets the maximum number of sockets that will be left open in the free
+ * state.
+ * @since v0.11.7
+ */
+ maxFreeSockets: number;
+ /**
+ * By default set to `Infinity`. Determines how many concurrent sockets the agent
+ * can have open per origin. Origin is the returned value of `agent.getName()`.
+ * @since v0.3.6
+ */
+ maxSockets: number;
+ /**
+ * By default set to `Infinity`. Determines how many concurrent sockets the agent
+ * can have open. Unlike `maxSockets`, this parameter applies across all origins.
+ * @since v14.5.0, v12.19.0
+ */
+ maxTotalSockets: number;
+ /**
+ * An object which contains arrays of sockets currently awaiting use by
+ * the agent when `keepAlive` is enabled. Do not modify.
+ *
+ * Sockets in the `freeSockets` list will be automatically destroyed and
+ * removed from the array on `'timeout'`.
+ * @since v0.11.4
+ */
+ readonly freeSockets: ReadOnlyDict<Socket[]>;
+ /**
+ * An object which contains arrays of sockets currently in use by the
+ * agent. Do not modify.
+ * @since v0.3.6
+ */
+ readonly sockets: ReadOnlyDict<Socket[]>;
+ /**
+ * An object which contains queues of requests that have not yet been assigned to
+ * sockets. Do not modify.
+ * @since v0.5.9
+ */
+ readonly requests: ReadOnlyDict<IncomingMessage[]>;
+ constructor(opts?: AgentOptions);
+ /**
+ * Destroy any sockets that are currently in use by the agent.
+ *
+ * It is usually not necessary to do this. However, if using an
+ * agent with `keepAlive` enabled, then it is best to explicitly shut down
+ * the agent when it is no longer needed. Otherwise,
+ * sockets might stay open for quite a long time before the server
+ * terminates them.
+ * @since v0.11.4
+ */
+ destroy(): void;
+ keepSocketAlive(socket: Socket): boolean;
+ }
+
const METHODS: string[];
const STATUS_CODES: {
[errorCode: number]: string | undefined;
[errorCode: string]: string | undefined;
};
+
+ /**
+ * Returns a new instance of {@link Server}.
+ *
+ * The `requestListener` is a function which is automatically
+ * added to the `'request'` event.
+ * @since v0.1.13
+ */
+ function createServer<
+ Request extends typeof IncomingMessage = typeof IncomingMessage,
+ Response extends typeof ServerResponse = typeof ServerResponse,
+ >(
+ requestListener?: RequestListener<Request, Response>,
+ ): Server<Request, Response>;
+ function createServer<
+ Request extends typeof IncomingMessage = typeof IncomingMessage,
+ Response extends typeof ServerResponse = typeof ServerResponse,
+ >(
+ options: ServerOptions<Request, Response>,
+ requestListener?: RequestListener<Request, Response>,
+ ): Server<Request, Response>;
+
// although RequestOptions are passed as ClientRequestArgs to ClientRequest directly,
// create interface RequestOptions would make the naming more clear to developers
interface RequestOptions extends ClientRequestArgs {}
@@ -884,6 +1784,9 @@ declare module "http" {
options: RequestOptions,
callback?: (res: IncomingMessage) => void,
): ClientRequest;
+
+ let globalAgent: Agent;
+
/**
* Read-only property specifying the maximum allowed size of HTTP headers in bytes.
* Defaults to 16KB. Configurable using the `--max-http-header-size` CLI option.
diff --git a/packages/bun-types/net.d.ts b/packages/bun-types/net.d.ts
index 8459fe685..4817d98f8 100644
--- a/packages/bun-types/net.d.ts
+++ b/packages/bun-types/net.d.ts
@@ -14,10 +14,7 @@
*/
declare module "net" {
import * as stream from "node:stream";
- import {
- Abortable,
- // EventEmitter
- } from "node:events";
+ import { Abortable, EventEmitter } from "node:events";
import * as dns from "node:dns";
type LookupFunction = (
hostname: string,
@@ -530,212 +527,213 @@ declare module "net" {
* This class is used to create a TCP or `IPC` server.
* @since v0.1.90
*/
- // class Server extends EventEmitter {
- // constructor(connectionListener?: (socket: Socket) => void);
- // constructor(
- // options?: ServerOpts,
- // connectionListener?: (socket: Socket) => void,
- // );
- // /**
- // * Start a server listening for connections. A `net.Server` can be a TCP or
- // * an `IPC` server depending on what it listens to.
- // *
- // * Possible signatures:
- // *
- // * * `server.listen(handle[, backlog][, callback])`
- // * * `server.listen(options[, callback])`
- // * * `server.listen(path[, backlog][, callback])` for `IPC` servers
- // * * `server.listen([port[, host[, backlog]]][, callback])` for TCP servers
- // *
- // * This function is asynchronous. When the server starts listening, the `'listening'` event will be emitted. The last parameter `callback`will be added as a listener for the `'listening'`
- // * event.
- // *
- // * All `listen()` methods can take a `backlog` parameter to specify the maximum
- // * length of the queue of pending connections. The actual length will be determined
- // * by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn`on Linux. The default value of this parameter is 511 (not 512).
- // *
- // * All {@link Socket} are set to `SO_REUSEADDR` (see [`socket(7)`](https://man7.org/linux/man-pages/man7/socket.7.html) for
- // * details).
- // *
- // * The `server.listen()` method can be called again if and only if there was an
- // * error during the first `server.listen()` call or `server.close()` has been
- // * called. Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown.
- // *
- // * One of the most common errors raised when listening is `EADDRINUSE`.
- // * This happens when another server is already listening on the requested`port`/`path`/`handle`. One way to handle this would be to retry
- // * after a certain amount of time:
- // *
- // * ```js
- // * server.on('error', (e) => {
- // * if (e.code === 'EADDRINUSE') {
- // * console.log('Address in use, retrying...');
- // * setTimeout(() => {
- // * server.close();
- // * server.listen(PORT, HOST);
- // * }, 1000);
- // * }
- // * });
- // * ```
- // */
- // listen(
- // port?: number,
- // hostname?: string,
- // backlog?: number,
- // listeningListener?: () => void,
- // ): this;
- // listen(
- // port?: number,
- // hostname?: string,
- // listeningListener?: () => void,
- // ): this;
- // listen(
- // port?: number,
- // backlog?: number,
- // listeningListener?: () => void,
- // ): this;
- // listen(port?: number, listeningListener?: () => void): this;
- // listen(
- // path: string,
- // backlog?: number,
- // listeningListener?: () => void,
- // ): this;
- // listen(path: string, listeningListener?: () => void): this;
- // listen(options: ListenOptions, listeningListener?: () => void): this;
- // listen(handle: any, backlog?: number, listeningListener?: () => void): this;
- // listen(handle: any, listeningListener?: () => void): this;
- // /**
- // * Stops the server from accepting new connections and keeps existing
- // * connections. This function is asynchronous, the server is finally closed
- // * when all connections are ended and the server emits a `'close'` event.
- // * The optional `callback` will be called once the `'close'` event occurs. Unlike
- // * that event, it will be called with an `Error` as its only argument if the server
- // * was not open when it was closed.
- // * @since v0.1.90
- // * @param callback Called when the server is closed.
- // */
- // close(callback?: (err?: Error) => void): this;
- // /**
- // * Returns the bound `address`, the address `family` name, and `port` of the server
- // * as reported by the operating system if listening on an IP socket
- // * (useful to find which port was assigned when getting an OS-assigned address):`{ port: 12346, family: 'IPv4', address: '127.0.0.1' }`.
- // *
- // * For a server listening on a pipe or Unix domain socket, the name is returned
- // * as a string.
- // *
- // * ```js
- // * const server = net.createServer((socket) => {
- // * socket.end('goodbye\n');
- // * }).on('error', (err) => {
- // * // Handle errors here.
- // * throw err;
- // * });
- // *
- // * // Grab an arbitrary unused port.
- // * server.listen(() => {
- // * console.log('opened server on', server.address());
- // * });
- // * ```
- // *
- // * `server.address()` returns `null` before the `'listening'` event has been
- // * emitted or after calling `server.close()`.
- // * @since v0.1.90
- // */
- // address(): AddressInfo | string | null;
- // /**
- // * Asynchronously get the number of concurrent connections on the server. Works
- // * when sockets were sent to forks.
- // *
- // * Callback should take two arguments `err` and `count`.
- // * @since v0.9.7
- // */
- // getConnections(cb: (error: Error | null, count: number) => void): void;
- // /**
- // * Opposite of `unref()`, calling `ref()` on a previously `unref`ed server will _not_ let the program exit if it's the only server left (the default behavior).
- // * If the server is `ref`ed calling `ref()` again will have no effect.
- // * @since v0.9.1
- // */
- // ref(): this;
- // /**
- // * Calling `unref()` on a server will allow the program to exit if this is the only
- // * active server in the event system. If the server is already `unref`ed calling`unref()` again will have no effect.
- // * @since v0.9.1
- // */
- // unref(): this;
- // /**
- // * Set this property to reject connections when the server's connection count gets
- // * high.
- // *
- // * It is not recommended to use this option once a socket has been sent to a child
- // * with `child_process.fork()`.
- // * @since v0.2.0
- // */
- // maxConnections: number;
- // connections: number;
- // /**
- // * Indicates whether or not the server is listening for connections.
- // * @since v5.7.0
- // */
- // listening: boolean;
- // /**
- // * events.EventEmitter
- // * 1. close
- // * 2. connection
- // * 3. error
- // * 4. listening
- // * 5. drop
- // */
- // addListener(event: string, listener: (...args: any[]) => void): this;
- // addListener(event: "close", listener: () => void): this;
- // addListener(event: "connection", listener: (socket: Socket) => void): this;
- // addListener(event: "error", listener: (err: Error) => void): this;
- // addListener(event: "listening", listener: () => void): this;
- // addListener(event: "drop", listener: (data?: DropArgument) => void): this;
- // emit(event: string | symbol, ...args: any[]): boolean;
- // emit(event: "close"): boolean;
- // emit(event: "connection", socket: Socket): boolean;
- // emit(event: "error", err: Error): boolean;
- // emit(event: "listening"): boolean;
- // emit(event: "drop", data?: DropArgument): boolean;
- // on(event: string, listener: (...args: any[]) => void): this;
- // on(event: "close", listener: () => void): this;
- // on(event: "connection", listener: (socket: Socket) => void): this;
- // on(event: "error", listener: (err: Error) => void): this;
- // on(event: "listening", listener: () => void): this;
- // on(event: "drop", listener: (data?: DropArgument) => void): this;
- // once(event: string, listener: (...args: any[]) => void): this;
- // once(event: "close", listener: () => void): this;
- // once(event: "connection", listener: (socket: Socket) => void): this;
- // once(event: "error", listener: (err: Error) => void): this;
- // once(event: "listening", listener: () => void): this;
- // once(event: "drop", listener: (data?: DropArgument) => void): this;
- // prependListener(event: string, listener: (...args: any[]) => void): this;
- // prependListener(event: "close", listener: () => void): this;
- // prependListener(
- // event: "connection",
- // listener: (socket: Socket) => void,
- // ): this;
- // prependListener(event: "error", listener: (err: Error) => void): this;
- // prependListener(event: "listening", listener: () => void): this;
- // prependListener(
- // event: "drop",
- // listener: (data?: DropArgument) => void,
- // ): this;
- // prependOnceListener(
- // event: string,
- // listener: (...args: any[]) => void,
- // ): this;
- // prependOnceListener(event: "close", listener: () => void): this;
- // prependOnceListener(
- // event: "connection",
- // listener: (socket: Socket) => void,
- // ): this;
- // prependOnceListener(event: "error", listener: (err: Error) => void): this;
- // prependOnceListener(event: "listening", listener: () => void): this;
- // prependOnceListener(
- // event: "drop",
- // listener: (data?: DropArgument) => void,
- // ): this;
- // }
+ // change back to class once implemented
+ interface Server extends EventEmitter {
+ // constructor(connectionListener?: (socket: Socket) => void);
+ // constructor(
+ // options?: ServerOpts,
+ // connectionListener?: (socket: Socket) => void,
+ // );
+ /**
+ * Start a server listening for connections. A `net.Server` can be a TCP or
+ * an `IPC` server depending on what it listens to.
+ *
+ * Possible signatures:
+ *
+ * * `server.listen(handle[, backlog][, callback])`
+ * * `server.listen(options[, callback])`
+ * * `server.listen(path[, backlog][, callback])` for `IPC` servers
+ * * `server.listen([port[, host[, backlog]]][, callback])` for TCP servers
+ *
+ * This function is asynchronous. When the server starts listening, the `'listening'` event will be emitted. The last parameter `callback`will be added as a listener for the `'listening'`
+ * event.
+ *
+ * All `listen()` methods can take a `backlog` parameter to specify the maximum
+ * length of the queue of pending connections. The actual length will be determined
+ * by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn`on Linux. The default value of this parameter is 511 (not 512).
+ *
+ * All {@link Socket} are set to `SO_REUSEADDR` (see [`socket(7)`](https://man7.org/linux/man-pages/man7/socket.7.html) for
+ * details).
+ *
+ * The `server.listen()` method can be called again if and only if there was an
+ * error during the first `server.listen()` call or `server.close()` has been
+ * called. Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown.
+ *
+ * One of the most common errors raised when listening is `EADDRINUSE`.
+ * This happens when another server is already listening on the requested`port`/`path`/`handle`. One way to handle this would be to retry
+ * after a certain amount of time:
+ *
+ * ```js
+ * server.on('error', (e) => {
+ * if (e.code === 'EADDRINUSE') {
+ * console.log('Address in use, retrying...');
+ * setTimeout(() => {
+ * server.close();
+ * server.listen(PORT, HOST);
+ * }, 1000);
+ * }
+ * });
+ * ```
+ */
+ listen(
+ port?: number,
+ hostname?: string,
+ backlog?: number,
+ listeningListener?: () => void,
+ ): this;
+ listen(
+ port?: number,
+ hostname?: string,
+ listeningListener?: () => void,
+ ): this;
+ listen(
+ port?: number,
+ backlog?: number,
+ listeningListener?: () => void,
+ ): this;
+ listen(port?: number, listeningListener?: () => void): this;
+ listen(
+ path: string,
+ backlog?: number,
+ listeningListener?: () => void,
+ ): this;
+ listen(path: string, listeningListener?: () => void): this;
+ listen(options: ListenOptions, listeningListener?: () => void): this;
+ listen(handle: any, backlog?: number, listeningListener?: () => void): this;
+ listen(handle: any, listeningListener?: () => void): this;
+ /**
+ * Stops the server from accepting new connections and keeps existing
+ * connections. This function is asynchronous, the server is finally closed
+ * when all connections are ended and the server emits a `'close'` event.
+ * The optional `callback` will be called once the `'close'` event occurs. Unlike
+ * that event, it will be called with an `Error` as its only argument if the server
+ * was not open when it was closed.
+ * @since v0.1.90
+ * @param callback Called when the server is closed.
+ */
+ close(callback?: (err?: Error) => void): this;
+ /**
+ * Returns the bound `address`, the address `family` name, and `port` of the server
+ * as reported by the operating system if listening on an IP socket
+ * (useful to find which port was assigned when getting an OS-assigned address):`{ port: 12346, family: 'IPv4', address: '127.0.0.1' }`.
+ *
+ * For a server listening on a pipe or Unix domain socket, the name is returned
+ * as a string.
+ *
+ * ```js
+ * const server = net.createServer((socket) => {
+ * socket.end('goodbye\n');
+ * }).on('error', (err) => {
+ * // Handle errors here.
+ * throw err;
+ * });
+ *
+ * // Grab an arbitrary unused port.
+ * server.listen(() => {
+ * console.log('opened server on', server.address());
+ * });
+ * ```
+ *
+ * `server.address()` returns `null` before the `'listening'` event has been
+ * emitted or after calling `server.close()`.
+ * @since v0.1.90
+ */
+ address(): AddressInfo | string | null;
+ /**
+ * Asynchronously get the number of concurrent connections on the server. Works
+ * when sockets were sent to forks.
+ *
+ * Callback should take two arguments `err` and `count`.
+ * @since v0.9.7
+ */
+ // getConnections(cb: (error: Error | null, count: number) => void): void;
+ /**
+ * Opposite of `unref()`, calling `ref()` on a previously `unref`ed server will _not_ let the program exit if it's the only server left (the default behavior).
+ * If the server is `ref`ed calling `ref()` again will have no effect.
+ * @since v0.9.1
+ */
+ // ref(): this;
+ /**
+ * Calling `unref()` on a server will allow the program to exit if this is the only
+ * active server in the event system. If the server is already `unref`ed calling`unref()` again will have no effect.
+ * @since v0.9.1
+ */
+ // unref(): this;
+ /**
+ * Set this property to reject connections when the server's connection count gets
+ * high.
+ *
+ * It is not recommended to use this option once a socket has been sent to a child
+ * with `child_process.fork()`.
+ * @since v0.2.0
+ */
+ // maxConnections: number;
+ // connections: number;
+ /**
+ * Indicates whether or not the server is listening for connections.
+ * @since v5.7.0
+ */
+ // listening: boolean;
+ /**
+ * events.EventEmitter
+ * 1. close
+ * 2. connection
+ * 3. error
+ * 4. listening
+ * 5. drop
+ */
+ addListener(event: string, listener: (...args: any[]) => void): this;
+ addListener(event: "close", listener: () => void): this;
+ addListener(event: "connection", listener: (socket: Socket) => void): this;
+ addListener(event: "error", listener: (err: Error) => void): this;
+ addListener(event: "listening", listener: () => void): this;
+ addListener(event: "drop", listener: (data?: DropArgument) => void): this;
+ emit(event: string | symbol, ...args: any[]): boolean;
+ emit(event: "close"): boolean;
+ emit(event: "connection", socket: Socket): boolean;
+ emit(event: "error", err: Error): boolean;
+ emit(event: "listening"): boolean;
+ emit(event: "drop", data?: DropArgument): boolean;
+ on(event: string, listener: (...args: any[]) => void): this;
+ on(event: "close", listener: () => void): this;
+ on(event: "connection", listener: (socket: Socket) => void): this;
+ on(event: "error", listener: (err: Error) => void): this;
+ on(event: "listening", listener: () => void): this;
+ on(event: "drop", listener: (data?: DropArgument) => void): this;
+ once(event: string, listener: (...args: any[]) => void): this;
+ once(event: "close", listener: () => void): this;
+ once(event: "connection", listener: (socket: Socket) => void): this;
+ once(event: "error", listener: (err: Error) => void): this;
+ once(event: "listening", listener: () => void): this;
+ once(event: "drop", listener: (data?: DropArgument) => void): this;
+ prependListener(event: string, listener: (...args: any[]) => void): this;
+ prependListener(event: "close", listener: () => void): this;
+ prependListener(
+ event: "connection",
+ listener: (socket: Socket) => void,
+ ): this;
+ prependListener(event: "error", listener: (err: Error) => void): this;
+ prependListener(event: "listening", listener: () => void): this;
+ prependListener(
+ event: "drop",
+ listener: (data?: DropArgument) => void,
+ ): this;
+ prependOnceListener(
+ event: string,
+ listener: (...args: any[]) => void,
+ ): this;
+ prependOnceListener(event: "close", listener: () => void): this;
+ prependOnceListener(
+ event: "connection",
+ listener: (socket: Socket) => void,
+ ): this;
+ prependOnceListener(event: "error", listener: (err: Error) => void): this;
+ prependOnceListener(event: "listening", listener: () => void): this;
+ prependOnceListener(
+ event: "drop",
+ listener: (data?: DropArgument) => void,
+ ): this;
+ }
type IPVersion = "ipv4" | "ipv6";
/**
* The `BlockList` object can be used with some network APIs to specify rules for
diff --git a/packages/bun-types/stream.d.ts b/packages/bun-types/stream.d.ts
index 5962692a0..8934146fa 100644
--- a/packages/bun-types/stream.d.ts
+++ b/packages/bun-types/stream.d.ts
@@ -555,24 +555,29 @@ declare module "stream" {
*/
destroyed: boolean;
constructor(opts?: WritableOptions);
- _write(
- chunk: any,
- encoding: BufferEncoding,
- callback: (error?: Error | null) => void,
- ): void;
- _writev?(
- chunks: Array<{
- chunk: any;
- encoding: BufferEncoding;
- }>,
- callback: (error?: Error | null) => void,
- ): void;
- _construct?(callback: (error?: Error | null) => void): void;
- _destroy(
- error: Error | null,
- callback: (error?: Error | null) => void,
- ): void;
- _final(callback: (error?: Error | null) => void): void;
+
+ /**
+ * Hide internal methods from the public API.
+ */
+ // _write(
+ // chunk: any,
+ // encoding: BufferEncoding,
+ // callback: (error?: Error | null) => void,
+ // ): void;
+ // _writev?(
+ // chunks: Array<{
+ // chunk: any;
+ // encoding: BufferEncoding;
+ // }>,
+ // callback: (error?: Error | null) => void,
+ // ): void;
+ // _construct?(callback: (error?: Error | null) => void): void;
+ // _destroy(
+ // error: Error | null,
+ // callback: (error?: Error | null) => void,
+ // ): void;
+ // _final(callback: (error?: Error | null) => void): void;
+
/**
* The `writable.write()` method writes some data to the stream, and calls the
* supplied `callback` once the data has been fully handled. If an error
diff --git a/packages/bun-types/tests/http.test-d.ts b/packages/bun-types/tests/http.test-d.ts
new file mode 100644
index 000000000..d9754ac0c
--- /dev/null
+++ b/packages/bun-types/tests/http.test-d.ts
@@ -0,0 +1,27 @@
+import * as http from "http";
+
+const server = new http.Server({});
+server.address;
+server.close();
+server.eventNames;
+server.getMaxListeners();
+server.listeners;
+server.on;
+server.once;
+server.prependListener;
+server.prependOnceListener;
+server.rawListeners;
+server.removeAllListeners;
+server.removeListener;
+server.setMaxListeners;
+server;
+const agent = new http.Agent({});
+
+http.globalAgent;
+http.maxHeaderSize;
+console.log(Object.getOwnPropertyNames(agent));
+
+const req = http.request({ host: "localhost", port: 3000, method: "GET" });
+req.abort;
+req.end();
+export {};
diff --git a/src/bun.js/http.exports.js b/src/bun.js/http.exports.js
index 579991424..29421b836 100644
--- a/src/bun.js/http.exports.js
+++ b/src/bun.js/http.exports.js
@@ -920,6 +920,10 @@ export class ClientRequest extends OutgoingMessage {
return this.#port;
}
+ get method() {
+ return this.#method;
+ }
+
get host() {
return this.#host;
}
diff --git a/test/bun.js/node-http.test.ts b/test/bun.js/node-http.test.ts
index 6ba619c3e..e0964edb0 100644
--- a/test/bun.js/node-http.test.ts
+++ b/test/bun.js/node-http.test.ts
@@ -83,10 +83,10 @@ describe("node:http", () => {
describe("request", () => {
let server;
let serverPort;
- let timer = null;
+ let timer: Timer | null = null;
beforeAll(() => {
server = createServer((req, res) => {
- const reqUrl = new URL(req.url, `http://${req.headers.host}`);
+ const reqUrl = new URL(req.url!, `http://${req.headers.host}`);
if (reqUrl.pathname) {
if (reqUrl.pathname === "/redirect") {
// Temporary redirect
@@ -148,6 +148,20 @@ describe("node:http", () => {
if (timer) clearTimeout(timer);
});
+ it("check for expected fields", done => {
+ const req = request({ host: "localhost", port: serverPort, method: "GET" }, res => {
+ res.on("end", () => {
+ done();
+ });
+ res.on("error", err => done(err));
+ });
+ expect(req.path).toEqual("/");
+ expect(req.method).toEqual("GET");
+ expect(req.host).toEqual("localhost");
+ expect(req.protocol).toEqual("http:");
+ req.end();
+ });
+
it("should make a standard GET request when passed string as first arg", done => {
const req = request(`http://localhost:${serverPort}`, res => {
let data = "";
@@ -510,7 +524,9 @@ describe("node:http", () => {
it("should noop keepSocketAlive", () => {
const agent = new Agent({ keepAlive: true });
+ // @ts-ignore
expect(agent.keepAlive).toBe(true);
+
agent.keepSocketAlive(dummyReq.socket);
});