Skip to content
Effect Days 2026 Get your ticket

HttpLayerRouter

42 exports Added in v1.0.0 Source

Configuration

RouterConfig

Added in v1.0.0 Source

Signature

declare class RouterConfig extends any {
constructor();
}

HttpApi

addHttpApi

Added in v1.0.0 Source

Signature

declare function addHttpApi<Id extends string, Groups extends Any, E, R>(api: HttpApi<Id, Groups, E, R>, options?: {
readonly openapiPath?: `/${string}`;
}): Layer<never, never, Generator | FileSystem | HttpPlatform | Path | HttpRouter | R | ToService<Id, Groups> | ErrorContext<Groups>>

Example

import * as NodeHttpServer from "@effect/platform-node/NodeHttpServer"
import * as NodeRuntime from "@effect/platform-node/NodeRuntime"
import * as HttpApi from "@effect/platform/HttpApi"
import * as HttpApiBuilder from "@effect/platform/HttpApiBuilder"
import * as HttpApiEndpoint from "@effect/platform/HttpApiEndpoint"
import * as HttpApiGroup from "@effect/platform/HttpApiGroup"
import * as HttpApiScalar from "@effect/platform/HttpApiScalar"
import * as HttpLayerRouter from "@effect/platform/HttpLayerRouter"
import * as HttpMiddleware from "@effect/platform/HttpMiddleware"
import * as Effect from "effect/Effect"
import * as Layer from "effect/Layer"
import { createServer } from "http"
// First, we define our HttpApi
class MyApi extends HttpApi.make("api").add(
HttpApiGroup.make("users").add(
HttpApiEndpoint.get("me", "/me")
).prefix("/users")
) {}
// Implement the handlers for the API
const UsersApiLayer = HttpApiBuilder.group(MyApi, "users", (handers) => handers.handle("me", () => Effect.void))
// Use `HttpLayerRouter.addHttpApi` to register the API with the router
const HttpApiRoutes = HttpLayerRouter.addHttpApi(MyApi, {
openapiPath: "/docs/openapi.json"
}).pipe(
// Provide the api handlers layer
Layer.provide(UsersApiLayer)
)
// Create a /docs route for the API documentation
const DocsRoute = HttpApiScalar.layerHttpLayerRouter({
api: MyApi,
path: "/docs"
})
const CorsMiddleware = HttpLayerRouter.middleware(HttpMiddleware.cors())
// You can also use HttpLayerRouter.cors() to create a CORS middleware
// Finally, we merge all routes and serve them using the Node HTTP server
const AllRoutes = Layer.mergeAll(
HttpApiRoutes,
DocsRoute
).pipe(
Layer.provide(CorsMiddleware.layer)
)
HttpLayerRouter.serve(AllRoutes).pipe(
Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })),
Layer.launch,
NodeRuntime.runMain
)

HttpRouter

add

Added in v1.0.0 Source

Create a layer that adds a single route to the HTTP router.

Signature

declare function add<E, R>(method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "*", path: PathInput, handler: Effect<HttpServerResponse, E, R> | (request: HttpServerRequest) => Effect<HttpServerResponse, E, R>, options?: {
readonly uninterruptible?: boolean;
}): Layer<never, never, HttpRouter | From<"Requires", Exclude<R, Provided>> | From<"Error", E>>

Example

import * as HttpLayerRouter from "@effect/platform/HttpLayerRouter"
import * as HttpServerResponse from "@effect/platform/HttpServerResponse"
const Route = HttpLayerRouter.add("GET", "/hello", HttpServerResponse.text("Hello, World!"))

addAll

Added in v1.0.0 Source

Create a layer that adds multiple routes to the HTTP router.

Signature

declare function addAll<Routes extends readonly Array<Route<any, any>>, EX = never, RX = never>(routes: Routes | Effect<Routes, EX, RX>, options?: {
readonly prefix?: string;
}): Layer<never, EX, HttpRouter | Exclude<RX, Scope> | From<"Requires", Exclude<Context<Routes[number]>, Provided>> | From<"Error", Error<Routes[number]>>>

Example

import * as HttpLayerRouter from "@effect/platform/HttpLayerRouter"
import * as HttpServerResponse from "@effect/platform/HttpServerResponse"
const Routes = HttpLayerRouter.addAll([
HttpLayerRouter.route("GET", "/hello", HttpServerResponse.text("Hello, World!"))
])

HttpRouter

Added in v1.0.0 Source

Signature

declare const HttpRouter: Tag<HttpRouter, HttpRouter>

HttpRouter interface

Added in v1.0.0 Source

Signature

interface HttpRouter {
readonly [TypeId]: typeof TypeId;
readonly add: <E, R>(method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "*", path: PathInput, handler: Effect<HttpServerResponse, E, R> | (request: HttpServerRequest) => Effect<HttpServerResponse, E, R>, options?: {
readonly uninterruptible?: boolean;
}) => Effect<void, never, From<"Requires", Exclude<R, Provided>> | From<"Error", E>>;
readonly addAll: <Routes extends readonly Array<Route<any, any>>>(routes: Routes) => Effect<void, never, From<"Requires", Exclude<Context<Routes[number]>, Provided>> | From<"Error", Error<Routes[number]>>>;
readonly addGlobalMiddleware: <E, R>(middleware: (effect: Effect<HttpServerResponse, unhandled>) => Effect<HttpServerResponse, E, R> & unhandled extends E ? unknown : "You cannot handle any errors") => Effect<void, never, From<"GlobalRequires", Exclude<R, GlobalProvided>> | From<"GlobalError", Exclude<E, unhandled>>>;
readonly asHttpEffect: () => Effect<HttpServerResponse, unknown, Scope | HttpServerRequest>;
readonly prefixed: (prefix: string) => HttpRouter;
}

layer

Added in v1.0.0 Source

Signature

declare const layer: Layer.Layer<HttpRouter>

make

Added in v1.0.0 Source

Signature

declare const make: Effect<any, unknown, unknown>

toHttpEffect

Added in v1.0.0 Source

Signature

declare function toHttpEffect<A, E, R>(appLayer: Layer<A, E, R>): Effect<Effect<HttpServerResponse, RouteNotFound | Only<"Error", R> | Only<"GlobalRequires", R>, Scope | HttpServerRequest | Only<"GlobalRequires", R> | Only<"Requires", R>>, Without<E>, Scope | Exclude<Without<R>, HttpRouter>>

TypeId

Added in v1.0.0 Source

Signature

declare const TypeId: unique symbol

TypeId type

Added in v1.0.0 Source

Signature

type TypeId = typeof TypeId

use

Added in v1.0.0 Source

A helper function that is the equivalent of:

Signature

declare function use<A, E, R>(f: (router: HttpRouter) => Effect<A, E, R>): Layer<never, E, HttpRouter | Exclude<R, Scope>>

Example

import * as HttpLayerRouter from "@effect/platform/HttpLayerRouter"
import * as Effect from "effect/Effect"
import * as Layer from "effect/Layer"
const MyRoute = Layer.scopedDiscard(Effect.gen(function*() {
const router = yield* HttpLayerRouter.HttpRouter
// then use `yield* router.add(...)` to add a route
}))

Middleware

cors

Added in v1.0.0 Source

A middleware that applies CORS headers to the HTTP response.

Signature

declare function cors(options?: {
readonly allowedHeaders?: readonly Array<string>;
readonly allowedMethods?: readonly Array<string>;
readonly allowedOrigins?: readonly Array<string> | Predicate<string>;
readonly credentials?: boolean;
readonly exposedHeaders?: readonly Array<string>;
readonly maxAge?: number;
}): Layer<never, never, HttpRouter>

A middleware that disables the logger for some routes.

Signature

declare const disableLogger: Layer.Layer<never>

Example

import * as HttpLayerRouter from "@effect/platform/HttpLayerRouter"
import * as HttpServerResponse from "@effect/platform/HttpServerResponse"
import * as Layer from "effect/Layer"
const Route = HttpLayerRouter.add("GET", "/hello", HttpServerResponse.text("Hello, World!")).pipe(
// disable the logger for this route
Layer.provide(HttpLayerRouter.disableLogger)
)

middleware

Added in v1.0.0 Source

Create a middleware layer that can be used to modify requests and responses.

By default, the middleware only affects the routes that it is provided to.

If you want to create a middleware that applies globally to all routes, pass the global option as true.

Signature

declare const middleware: middleware.Make<never, never> & <Config extends {
handles?: any;
provides?: any;
} = {}>() => middleware.Make<Config extends {
provides: infer R;
} ? R : never, Config extends {
handles: infer E;
} ? E : never>

Example

import * as HttpLayerRouter from "@effect/platform/HttpLayerRouter"
import * as HttpMiddleware from "@effect/platform/HttpMiddleware"
import * as HttpServerResponse from "@effect/platform/HttpServerResponse"
import * as Context from "effect/Context"
import * as Effect from "effect/Effect"
import * as Layer from "effect/Layer"
// Here we are defining a CORS middleware
const CorsMiddleware = HttpLayerRouter.middleware(HttpMiddleware.cors()).layer
// You can also use HttpLayerRouter.cors() to create a CORS middleware
class CurrentSession extends Context.Tag("CurrentSession")<CurrentSession, {
readonly token: string
}>() {}
// You can create middleware that provides a service to the HTTP requests.
const SessionMiddleware = HttpLayerRouter.middleware<{
provides: CurrentSession
}>()(
Effect.gen(function*() {
yield* Effect.log("SessionMiddleware initialized")
return (httpEffect) =>
Effect.provideService(httpEffect, CurrentSession, {
token: "dummy-token"
})
})
).layer
Effect.gen(function*() {
const router = yield* HttpLayerRouter.HttpRouter
yield* router.add(
"GET",
"/hello",
Effect.gen(function*() {
// Requests can now access the current session
const session = yield* CurrentSession
return HttpServerResponse.text(`Hello, World! Your token is ${session.token}`)
})
)
}).pipe(
Layer.effectDiscard,
// Provide the SessionMiddleware & CorsMiddleware to some routes
Layer.provide([SessionMiddleware, CorsMiddleware])
)

middleware

Added in v1.0.0 Source

Middleware interface

Added in v1.0.0 Source

Signature

interface Middleware<Config extends {
error: any;
handles: any;
layerError: any;
layerRequires: any;
provides: any;
requires: any;
}> {
readonly [MiddlewareTypeId]: Config;
readonly combine: <Config2 extends {
error: any;
handles: any;
layerError: any;
layerRequires: any;
provides: any;
requires: any;
}>(other: Middleware<Config2>) => Middleware<{
error: Config2["error"] | Exclude<Config["error"], Config2["handles"]>;
handles: Config2["handles"] | Config["handles"];
layerError: Config["layerError"] | Config2["layerError"];
layerRequires: Config["layerRequires"] | Config2["layerRequires"];
provides: Config["provides"] | Config2["provides"];
requires: Exclude<Config["requires"], Config2["provides"]> | Config2["requires"];
}>;
readonly layer: [Config["requires"]] extends [never] ? Layer<From<"Requires", Config["provides"]>, Config["layerError"], Config["layerRequires"] | From<"Requires", any[any]> | From<"Error", Config["error"]>> : "Need to .combine(middleware) that satisfy the missing request dependencies";
}

Signature

declare const MiddlewareTypeId: unique symbol

MiddlewareTypeId type

Added in v1.0.0 Source

Signature

type MiddlewareTypeId = typeof MiddlewareTypeId

unhandled interface

Added in v1.0.0 Source

A pseudo-error type that represents an error that should be not handled by the middleware.

Signature

interface unhandled {
readonly _: typeof _;
}

Models

RouteContext interface

Added in v1.0.0 Source

Signature

interface RouteContext {
readonly [RouteContextTypeId]: typeof RouteContextTypeId;
readonly params: Readonly<Record<string, string | undefined>>;
readonly route: Route<unknown, unknown>;
}

PathInput

PathInput type

Added in v1.0.0 Source

Signature

type PathInput = `/${string}` | "*"

prefixPath

Added in v1.0.0 Source

Signature

declare const prefixPath: {
(prefix: string): (self: string) => string;
(self: string, prefix: string): string;
}

Re-Exports

FindMyWay

Added in v1.0.0

Signature

declare const FindMyWay: any

Request Types

GlobalProvided type

Added in v1.0.0 Source

Services provided to global middleware.

Signature

type GlobalProvided = HttpServerRequest.HttpServerRequest | Scope.Scope

Provided type

Added in v1.0.0 Source

Services provided by the HTTP router, which are available in the request context.

Signature

type Provided = HttpServerRequest.HttpServerRequest | Scope.Scope | HttpServerRequest.ParsedSearchParams | RouteContext

Request

Added in v1.0.0 Source

Request interface

Added in v1.0.0 Source

Represents a request-level dependency, that needs to be provided by middleware.

Signature

interface Request<Kind extends string, T> {
readonly _: typeof _;
readonly kind: Kind;
readonly type: T;
}

Route

prefixRoute

Added in v1.0.0 Source

Signature

declare const prefixRoute: {
(prefix: string): <E, R>(self: Route<E, R>) => Route<E, R>;
<E, R>(self: Route<E, R>, prefix: string): Route<E, R>;
}

route

Added in v1.0.0 Source

Signature

declare function route<E, R>(method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "*", path: PathInput, handler: Effect<HttpServerResponse, E, R> | (request: HttpServerRequest) => Effect<HttpServerResponse, E, R>, options?: {
readonly uninterruptible?: boolean;
}): Route<E, Exclude<R, Provided>>

Route

Added in v1.0.0 Source

Route interface

Added in v1.0.0 Source

Signature

interface Route<E = never, R = never> {
readonly [RouteTypeId]: typeof RouteTypeId;
readonly handler: Effect<HttpServerResponse, E, R>;
readonly method: HttpMethod | "*";
readonly path: PathInput;
readonly prefix: Option<string>;
readonly uninterruptible: boolean;
}

RouteTypeId

Added in v1.0.0 Source

Signature

declare const RouteTypeId: unique symbol

RouteTypeId type

Added in v1.0.0 Source

Signature

type RouteTypeId = typeof RouteTypeId

Route Context

params

Added in v1.0.0 Source

Signature

declare const params: Effect.Effect<Readonly<Record<string, string | undefined>>, never, RouteContext>

RouteContext

Added in v1.0.0 Source

Signature

declare const RouteContext: Tag<RouteContext, RouteContext>

schemaJson

Added in v1.0.0 Source

Signature

declare const schemaJson: <R, I extends Partial<{
readonly body: any;
readonly cookies: Readonly<Record<string, string | undefined>>;
readonly headers: Readonly<Record<string, string | undefined>>;
readonly method: Method.HttpMethod;
readonly pathParams: Readonly<Record<string, string | undefined>>;
readonly searchParams: Readonly<Record<string, string | ReadonlyArray<string> | undefined>>;
readonly url: string;
}>, A>(schema: Schema.Schema<A, I, R>, options?: ParseOptions) => Effect.Effect<A, Error.RequestError | ParseResult.ParseError, RouteContext | R | ServerRequest.HttpServerRequest | ServerRequest.ParsedSearchParams>

schemaNoBody

Added in v1.0.0 Source

Signature

declare const schemaNoBody: <R, I extends Partial<{
readonly cookies: Readonly<Record<string, string | undefined>>;
readonly headers: Readonly<Record<string, string | undefined>>;
readonly method: Method.HttpMethod;
readonly pathParams: Readonly<Record<string, string | undefined>>;
readonly searchParams: Readonly<Record<string, string | ReadonlyArray<string> | undefined>>;
readonly url: string;
}>, A>(schema: Schema.Schema<A, I, R>, options?: ParseOptions) => Effect.Effect<A, ParseResult.ParseError, R | RouteContext | ServerRequest.HttpServerRequest | ServerRequest.ParsedSearchParams>

schemaParams

Added in v1.0.0 Source

Signature

declare const schemaParams: <A, I extends Readonly<Record<string, string | ReadonlyArray<string> | undefined>>, R>(schema: Schema.Schema<A, I, R>, options?: ParseOptions) => Effect.Effect<A, ParseResult.ParseError, R | RouteContext | ServerRequest.ParsedSearchParams>

Signature

declare const schemaPathParams: <A, I extends Readonly<Record<string, string | undefined>>, R>(schema: Schema.Schema<A, I, R>, options?: ParseOptions) => Effect.Effect<A, ParseResult.ParseError, R | RouteContext>

Server

serve

Added in v1.0.0 Source

Serves the provided application layer as an HTTP server.

Signature

declare function serve<A, E, R, HE, HR = Only<"Requires", R> | Only<"GlobalRequires", R>>(appLayer: Layer<A, E, R>, options?: {
readonly disableListenLog?: boolean;
readonly disableLogger?: boolean;
readonly middleware?: (effect: Effect<HttpServerResponse, RouteNotFound | Only<"Error", R> | Only<"GlobalError", R>, Scope | HttpServerRequest | Only<"Requires", R> | Only<"GlobalRequires", R>>) => Effect<HttpServerResponse, HE, HR>;
readonly routerConfig?: any;
}): Layer<A, Without<E>, HttpServer | Exclude<Without<R>, HttpRouter> | Exclude<Exclude<HR, GlobalProvided>, HttpRouter>>

toWebHandler

Added in v1.0.0 Source

Signature

declare function toWebHandler<A, E, R extends HttpRouter | Request<"Requires", any> | Request<"GlobalRequires", any> | Request<"Error", any> | Request<"GlobalError", any>, HE, HR = Exclude<Only<"Requires", R>, A> | Exclude<Only<"GlobalRequires", R>, A>>(appLayer: Layer<A, E, R>, options?: {
readonly disableLogger?: boolean;
readonly memoMap?: MemoMap;
readonly middleware?: (effect: Effect<HttpServerResponse, RouteNotFound | Only<"Error", R> | Only<"GlobalError", R>, Scope | HttpServerRequest | Only<"Requires", R> | Only<"GlobalRequires", R>>) => Effect<HttpServerResponse, HE, HR>;
readonly routerConfig?: any;
}): {
readonly dispose: () => Promise<void>;
readonly handler: [HR] extends [never] ? (request: Request, context?: Context<never>) => Promise<Response> : (request: Request, context: Context<HR>) => Promise<Response>;
}