SPB Git

spb/chat-spboucher Public

Private universal chat interface over the OpenRouter ecosystem — 400+ models, branching, streaming, usage tracking. Next.js 16 + SQLite, PWA, deployed on m4m64a at chat.spboucher.ai

TypeScript 78.8% CSS 15.1% JavaScript 4.9% Shell 1.2%
1.2 KB · 36 lines typescript
Raw Blame History
1// Author: Simon-Pierre Boucher2// Contact: contact@spboucher.ai3// Project: chat.spboucher.ai45import { cookies, headers } from "next/headers";6import { NextResponse } from "next/server";7import { getSession, SESSION_COOKIE, type SessionInfo } from "./auth";89/** DB-backed session check for route handlers and server components. */10export async function currentSession(): Promise<SessionInfo | null> {11  const jar = await cookies();12  return getSession(jar.get(SESSION_COOKIE)?.value);13}1415/** Returns the session or a ready-to-return 401 response. Every /api route uses this. */16export async function requireSession(): Promise<17  { session: SessionInfo; unauthorized: null } | { session: null; unauthorized: NextResponse }18> {19  const session = await currentSession();20  if (!session) {21    return {22      session: null,23      unauthorized: NextResponse.json({ error: "Unauthorized" }, { status: 401 }),24    };25  }26  return { session, unauthorized: null };27}2829/** Client IP, trusting X-Forwarded-For from the ngrok tunnel. */30export async function clientIp(): Promise<string> {31  const h = await headers();32  const xff = h.get("x-forwarded-for");33  if (xff) return xff.split(",")[0].trim();34  return h.get("x-real-ip") ?? "unknown";35}36