@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
TypeScript
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