UNPKG

@thi.ng/server

Version:

Minimal HTTP server with declarative routing, static file serving and freely extensible via pre/post interceptors

127 lines 4.72 kB
import type { Fn, Fn2 } from "@thi.ng/api"; import { ServerResponse } from "node:http"; import type { Interceptor, ISessionStore, RequestCtx, ServerSession } from "../api.js"; /** * Configuration options for {@link SessionInterceptor}. */ export interface SessionOpts<CTX extends RequestCtx = RequestCtx, SESSION extends ServerSession = ServerSession> { /** * Factory function to create a new session object. See * {@link createSession} for a base implementation. */ factory: Fn<CTX, SESSION>; /** * Session storage implementation. Default: {@link InMemorySessionStore}. */ store?: ISessionStore<SESSION>; /** * Session cookie name * * @defaultValue "__sid" */ cookieName?: string; /** * Additional session cookie config options. * * @defaultValue "Secure;HttpOnly;SameSite=Strict;Path=/" */ cookieOpts?: string; /** * HMAC key/secret used for signing cookies (using SHA256). Max length 64 * bytes. If given as number, generates N random bytes. */ secret?: number | string | Buffer; /** * Callback if session cookie is present, but failed validation. When this * function needs to be called, its result is used as the result of * {@link SessionInterceptor.pre}. * * @remarks * The default implementation simply expires the cookie in the response and * terminates the interceptor chain with a 403. */ onInvalid?: Fn2<CTX, SessionInterceptor<CTX, SESSION>, Promise<boolean>>; } /** * Cached session metadata, stored in a WeakMap. * * @internal */ export interface SessionMeta { hmac: Buffer; cookie: string; } /** * Pre-interceptor which parses & validates session cookie (if available) from * current request and injects/updates session cookie in response. Only a signed * session ID will be stored in the cookie. Thr actual session data and HMAC is * held server side (via configured session storage, see * {@link SessionOpts.store}; by default uses {@link InMemorySessionStore}). */ export declare class SessionInterceptor<CTX extends RequestCtx = RequestCtx, SESSION extends ServerSession = ServerSession> implements Interceptor<CTX> { factory: SessionOpts<CTX, SESSION>["factory"]; onInvalid: Fn2<CTX, SessionInterceptor<CTX, SESSION>, Promise<boolean>>; store: ISessionStore<SESSION>; meta: WeakMap<SESSION, SessionMeta>; secret: Buffer; cookieName: string; cookieOpts: string; constructor({ factory, store, cookieName, cookieOpts, secret, onInvalid, }: SessionOpts<CTX, SESSION>); pre(ctx: CTX): Promise<boolean>; /** * Attempts to delete session for given ID and if successful also sets * force-expired cookie in response. * * @remarks * Intended for logout handlers and/or switching sessions when a user has * successfully authenticated (to avoid session fixation). * * @param ctx * @param sessionID */ deleteSession(ctx: CTX, sessionID: string): Promise<void>; /** * Creates a new session object (via configured * {@link SessionOpts.factory}), pre-computes HMAC and submits it to * configured {@link SessionOpts.store}. If successful, Returns session , * otherwise returns `undefined`. * * @param ctx */ newSession(ctx: CTX): Promise<SESSION | undefined>; /** * Calls {@link SessionInterceptor.newSession} to create a new session and, * if successful, associates it with current context & response. Deletes * existing session (if any). Returns new session object. * * @param ctx */ replaceSession(ctx: CTX): Promise<SESSION | undefined>; withSession(res: ServerResponse, session: SESSION): ServerResponse<import("http").IncomingMessage>; validateSession(cookie: string): Promise<SESSION | undefined>; /** * Appends `set-cookie` header which forces immediate expiry of session cookie. * * @param ctx */ expireCookie(ctx: CTX): void; } /** * Factory function to create a new {@link SessionInterceptor} instance * configured with given options. * * @param opts */ export declare const sessionInterceptor: <CTX extends RequestCtx = RequestCtx, SESSION extends ServerSession = ServerSession>(opts: SessionOpts<CTX, SESSION>) => SessionInterceptor<CTX, SESSION>; /** * Creates a new basic {@link ServerSession}, using a UUID v4 for * {@link ServerSession.id}. * * @remarks * Intended to be used for {@link SessionOpts.factory} and/or as basis for * creating custom session objects. * * @param ctx */ export declare const createSession: (ctx: RequestCtx) => ServerSession; //# sourceMappingURL=session.d.ts.map