--- name: http-endpoints description: Use when building an HTTP val — a web endpoint, API route, webhook receiver, or any val that responds to HTTP requests. Covers the handler signature, Hono usage, the endpoint URL, CORS behavior, redirects, and Val Town-specific limitations. triggers: [http, endpoint, webhook, api, request, response, hono, web, route, fetch, cors, redirect] --- # HTTP Endpoints HTTP vals (`fileType: "http"`) export a request handler and run on every incoming HTTP request. Each HTTP file is assigned a live URL — never construct it yourself; read `links.endpoint` from `list_files` or `create_file` responses, or call `fetch_val_endpoint`. That URL is open to anyone unless the val's app access (`httpPrivacy`) is `restricted`, in which case unauthenticated callers get a `302` to a login page instead of your response — see the `restricted-access` skill. ## Basic handler ```ts // Learn more: https://docs.val.town/vals/http/ export default async function (req: Request): Promise { return Response.json({ ok: true }); } ``` The file must have an `export` — `export default` for the handler. ## Hono When using Hono, export `app.fetch` (not `app`): ```ts import { Hono } from "npm:hono"; import { parseVal, serveImmutableFile } from "https://esm.town/v/std/utils/index.ts"; const app = new Hono(); app.get("/", (c) => c.text("hello")); // Immutable asset caching (see the client-side-js skill): serves the // current-version URLs your HTML shell stamps with immutableFileUrl() app.get("/__immutable/*", (c) => serveImmutableFile(c.req.path)); // View source redirect app.get("/source", (c) => c.redirect(parseVal().links.self.val)); // Always add this for full stack traces on errors: app.onError((err) => Promise.reject(err)); export default app.fetch; ``` Hono's `serveStatic` does **not** work on Val Town. Use `serveFile` / `staticHTTPServer` from `std/utils` for static files. For the full `std/utils` API (`readFile`, `serveFile`, `staticHTTPServer`, `listFiles`, `listFilesByPath`, `httpEndpoint`, `parseVal`, …), fetch `https://utilities.val.run/docs.md`. ## CORS Val Town adds permissive CORS headers by default (`Access-Control-Allow-Origin: *`), so in 99% of cases, you should never need to do anything with CORS. Using Hono's `cors` middleware is almost always unnecessary. If you set **any** CORS header yourself, Val Town stops adding **all** default headers — so either handle CORS completely yourself or don't touch it at all. ## Redirects `Response.redirect` is broken on Val Town. Use one of: ```ts return new Response(null, { status: 302, headers: { Location: "/path" } }); // or, with Hono: return c.redirect("/path"); ``` ## What's not available - **WebSockets**: Val Town does not accept incoming WebSocket connections. Use polling, long polling, or server-sent events instead. - **Filesystem access**: see the platform constraints. For persistent state, use `std/sqlite` or `std/blob`. ## Surfacing client-side errors For HTML responses, add this script tag to send browser errors back to val logs (visible via `get_logs`): ```html ``` ## Verifying changes After editing an HTTP val, fetch it to confirm it returns the expected HTTP response. Do not report a change as done without this step.