Skip to content
Effect 4.0 is here. One ecosystem. Zero dependencies.

NodeHttpServer unstable

Node.js implementation of the Effect HttpServer.

This module adapts a supplied Node http.Server or node:http2 server into Effect's platform-independent HTTP server service. It starts the server with Node listen options, converts request events into HttpServerRequest values, writes HttpServerResponse bodies through Node's ServerResponse, and handles upgrade events by exposing the upgraded socket through HttpServerRequest.upgrade. It also exports request and upgrade handler constructors plus layers for the server alone, HTTP support services, the combined server, configurable options, and tests.

HTTP/2

Pass Http2.createServer() for cleartext HTTP/2 (h2c), or Http2.createSecureServer({ key, cert, allowHTTP1: true }) to negotiate HTTP/2 over TLS and fall back to HTTP/1.1 for clients that do not support it. The protocol is detected per request, so the application sees the same HttpServerRequest either way:

  • pseudo-headers are removed from headers, and host is taken from :authority
  • originalUrl and HttpServerRequest.toURL use the :scheme the client sent, which a client can set as freely as x-forwarded-proto
  • connection-specific response headers that HTTP/2 forbids, such as connection, keep-alive and transfer-encoding, are dropped silently
  • a response that fails after its headers were sent resets the stream with INTERNAL_ERROR, so clients do not mistake a truncated body for a complete one

WebSockets and other upgrades only work over HTTP/1.1, which needs allowHTTP1 on a TLS server. Trailers are only available through the Node objects from NodeHttpServerRequest. Tune HTTP/2 limits, such as maxSessionMemory and settings.maxConcurrentStreams, through the Node server options.

9 exports Since v4.0.0 Source

Constructors

make

unstable
Since v4.0.0

Creates a scoped HttpServer from a Node http.Server or node:http2 server, starts listening with the supplied options, registers request and upgrade handling, and closes the server during scope finalization with optional graceful-shutdown control.

Signature

declare const make: (...args: [evaluate: LazyArg<Server<typeof IncomingMessage, typeof ServerResponse> | Http2Server<typeof IncomingMessage, typeof ServerResponse, typeof Http2ServerRequest, typeof Http2ServerResponse> | Http2SecureServer<typeof IncomingMessage, typeof ServerResponse, typeof Http2ServerRequest, typeof Http2ServerResponse>>, options: Options]) => Effect<{
readonly address: SocketAddress;
readonly serve: {
<E, R>(effect: Effect<HttpServerResponse, E, R>): Effect<void, never, Scope | Exclude<R, HttpServerRequest>>;
<E, R, App extends Effect<HttpServerResponse, any, any>>(effect: Effect<HttpServerResponse, E, R>, middleware: Applied<App, E, R>): Effect<void, never, Scope | Exclude<R, HttpServerRequest>>;
};
}, ServeError, Scope>

Handlers

makeHandler

unstable
Since v4.0.0

Creates a Node request event handler for an Effect HTTP application, injecting a HttpServerRequest and interrupting the request fiber if the client closes the response before it finishes. It accepts both HTTP/1.1 and HTTP/2 compatibility requests.

Signature

declare function makeHandler<R, E, App extends Effect<HttpServerResponse, any, any> = Effect<HttpServerResponse, E, R>>(httpEffect: Effect<HttpServerResponse, E, R>, options: {
readonly middleware?: Applied<App, E, R>;
readonly scope: Scope;
}): Effect<(nodeRequest: IncomingMessage | Http2ServerRequest, nodeResponse: ServerResponse<IncomingMessage> | Http2ServerResponse<Http2ServerRequest>) => void, never, Exclude<Services<App>, Scope | HttpServerRequest>>
Since v4.0.0

Creates a Node upgrade event handler for an Effect HTTP application, exposing the upgraded connection as the request's upgrade effect and interrupting the request fiber when the socket closes early.

Details

Upgrade: websocket requests complete the WebSocket handshake. Any other protocol answers 101 Switching Protocols with the requested protocol and exposes the raw connection, with bytes the client sent after the request head first on the reader. Either response is sent when the socket's reader is acquired. A handler that never asks for upgrade answers with its response as usual.

Signature

declare function makeUpgradeHandler<R, E, App extends Effect<HttpServerResponse, any, any> = Effect<HttpServerResponse, E, R>>(lazyWss: Effect<WebSocketServer>, httpEffect: Effect<HttpServerResponse, E, R>, options: {
readonly middleware?: Applied<App, E, R>;
readonly scope: Scope;
}): Effect<(nodeRequest: IncomingMessage, socket: Duplex, head: Buffer) => void, never, Exclude<Services<App>, Scope | HttpServerRequest>>

Layers

layer

unstable
Since v4.0.0

Provides a Node HttpServer together with the Node HTTP platform, ETag, and core platform services required to serve requests.

Signature

declare function layer(evaluate: LazyArg<Server<typeof IncomingMessage, typeof ServerResponse> | Http2Server<typeof IncomingMessage, typeof ServerResponse, typeof Http2ServerRequest, typeof Http2ServerResponse> | Http2SecureServer<typeof IncomingMessage, typeof ServerResponse, typeof Http2ServerRequest, typeof Http2ServerResponse>>, options: Options): Layer<HttpPlatform | Generator | NodeServices | HttpServer, ServeError>

layerConfig

unstable
Since v4.0.0

Provides a Node HttpServer together with the Node HTTP platform, ETag, and core Node platform services, reading the listen and shutdown options from a Config value.

Signature

declare function layerConfig(evaluate: LazyArg<Server<typeof IncomingMessage, typeof ServerResponse> | Http2Server<typeof IncomingMessage, typeof ServerResponse, typeof Http2ServerRequest, typeof Http2ServerResponse> | Http2SecureServer<typeof IncomingMessage, typeof ServerResponse, typeof Http2ServerRequest, typeof Http2ServerResponse>>, options: {
readonly backlog?: Config<number | undefined>;
readonly disablePreemptiveShutdown?: Config<boolean | undefined>;
readonly exclusive?: Config<boolean | undefined>;
readonly gracefulShutdownTimeout?: Config<Input | undefined>;
readonly handle?: Config<BoundSocket | undefined>;
readonly host?: Config<string | undefined>;
readonly ipv6Only?: Config<boolean | undefined>;
readonly path?: Config<string | undefined>;
readonly port?: Config<number | undefined>;
readonly readableAll?: Config<boolean | undefined>;
readonly reusePort?: Config<boolean | undefined>;
readonly signal?: {
readonly aborted: Config<boolean>;
addEventListener: Config<{
<K extends "abort">(type: K, listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
}>;
dispatchEvent: Config<(event: Event) => boolean>;
readonly onabort: Config<(this: AbortSignal, ev: Event) => any | null>;
readonly reason: Config<any>;
removeEventListener: Config<{
<K extends "abort">(type: K, listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}>;
throwIfAborted: Config<() => void>;
} | Config<AbortSignal | undefined>;
readonly websocket?: Config<Omit<ServerOptions, "port" | "host" | "noServer" | "server" | "path"> | undefined>;
readonly writableAll?: Config<boolean | undefined>;
} | Config<Options>): Layer<HttpPlatform | Generator | NodeServices | HttpServer, ConfigError | ServeError>
Since v4.0.0

Provides the Node HTTP support services used by NodeHttpServer, including the HTTP platform, ETag generator, and core Node platform services.

Signature

declare const layerHttpServices: Layer.Layer<NodeServices.NodeServices | HttpPlatform.HttpPlatform | Etag.Generator>

layerServer

unstable
Since v4.0.0

Provides an HttpServer by creating and managing a scoped Node http.Server or node:http2 server with the supplied listen and shutdown options.

Signature

declare const layerServer: (evaluate: LazyArg<Http.Server | Http2.Http2Server | Http2.Http2SecureServer>, options: Options) => Layer.Layer<HttpServer.HttpServer, ServeError>

Options

Options

interface unstable
Since v4.0.0

Options accepted by the Node HttpServer constructors and layers.

Signature

interface Options extends ListenOptions {
readonly disablePreemptiveShutdown?: boolean;
readonly gracefulShutdownTimeout?: Input;
readonly websocket?: Omit<ServerOptions, "port" | "host" | "noServer" | "server" | "path">;
}

Testing

layerTest

unstable
Since v4.0.0

Provides a test HTTP server listening on an ephemeral port together with a Fetch-backed HttpClient configured for server integration tests.

Signature

declare const layerTest: Layer.Layer<HttpServer.HttpServer | FileSystem.FileSystem | Path.Path | HttpPlatform.HttpPlatform | Etag.Generator | HttpClient, ServeError, never>