Note:
HeliumTS is under pre-beta and active development. Expect bugs and breaking changes. If you find any issues, please report them in our GitHub
A stable release is planned for early December 2025.
HTTP Handlers
Overview
HeliumTS provides defineHTTPRequest for creating custom HTTP endpoints. This is useful for:
- Webhooks (Stripe, GitHub, etc.)
- REST APIs
- Third-party integrations (Auth providers)
- File uploads/downloads
- Server-sent events
In this section:
- Examples - Stripe webhooks, OpenAI streaming, auth handlers
Basic Usage
1import { defineHTTPRequest } from "heliumts/server";23export const myEndpoint = defineHTTPRequest("GET", "/api/hello", async (req, ctx) => {4 return { message: "Hello World" };5});
Supported methods: GET, POST, PUT, PATCH, DELETE, ALL
Dynamic Routes
Use :param syntax for dynamic path segments:
1export const getUser = defineHTTPRequest("GET", "/api/users/:id", async (req, ctx) => {2 const userId = req.params.id;3 const user = await db.users.findById(userId);4 return { user };5});67// Multiple parameters8export const getProduct = defineHTTPRequest("GET", "/api/products/:category/:id", async (req, ctx) => {9 const { category, id } = req.params;10 return { category, id };11});
Catch-All Routes
Use * to match any remaining path segments (useful for auth providers):
1import { defineHTTPRequest } from "heliumts/server";2import { auth } from "./auth"; // Better Auth or similar34// Matches /api/auth/signin, /api/auth/signout, /api/auth/callback/google, etc.5export const authHandler = defineHTTPRequest("ALL", "/api/auth/*", async (req, ctx) => {6 const webRequest = await req.toWebRequest();7 return auth.handler(webRequest);8});
Request Object
1export const myHandler = defineHTTPRequest("POST", "/api/data", async (req, ctx) => {2 // HTTP method3 console.log(req.method); // "POST"45 // Headers6 const contentType = req.headers["content-type"];78 // Query parameters9 const search = req.query.q;1011 // Route parameters12 const id = req.params.id;1314 // Cookies15 const sessionId = req.cookies.sessionId;1617 // Parse JSON body18 const body = await req.json();1920 // Parse text body21 const text = await req.text();2223 return { success: true };24});
Request Properties
req.method- HTTP method (GET, POST, etc.)req.headers- Request headers objectreq.query- Query string parametersreq.params- Route parametersreq.cookies- Parsed cookiesreq.json()- Parse JSON bodyreq.text()- Get raw body as textreq.toWebRequest()- Convert to Web API Request
Response Headers & Status Codes
Return a standard Web API Response object for full control:
1export const customHeaders = defineHTTPRequest("GET", "/api/data", async (req, ctx) => {2 const data = { message: "Hello World" };34 return new Response(JSON.stringify(data), {5 status: 200,6 headers: {7 "Content-Type": "application/json",8 "Cache-Control": "max-age=3600",9 "X-Custom-Header": "my-value",10 },11 });12});1314// Error response15export const errorExample = defineHTTPRequest("POST", "/api/resource", async (req, ctx) => {16 const body = await req.json();1718 if (!body.email) {19 return new Response(JSON.stringify({ error: "Email required" }), {20 status: 400,21 headers: { "Content-Type": "application/json" },22 });23 }2425 return { success: true };26});
Common Status Codes
200- OK201- Created400- Bad Request401- Unauthorized403- Forbidden404- Not Found500- Internal Server Error
Streaming Responses
1export const streamData = defineHTTPRequest("GET", "/api/stream", async (req, ctx) => {2 const stream = new ReadableStream({3 async start(controller) {4 for (let i = 0; i < 10; i++) {5 controller.enqueue(`data: ${i}\n\n`);6 await new Promise((resolve) => setTimeout(resolve, 1000));7 }8 controller.close();9 },10 });1112 return new Response(stream, {13 status: 200,14 headers: {15 "Content-Type": "text/event-stream",16 "Cache-Control": "no-cache",17 Connection: "keep-alive",18 },19 });20});
Converting to Web Request
Use toWebRequest() to convert Helium's request to a standard Web API Request for third-party libraries:
1import { defineHTTPRequest } from "heliumts/server";2import { auth } from "./auth"; // Better Auth or similar34export const authHandler = defineHTTPRequest("ALL", "/auth/*", async (req, ctx) => {5 // Convert to Web Request for third-party libraries6 const webRequest = await req.toWebRequest();78 // Pass to third-party handler9 return auth.handler(webRequest);10});
Best Practices
- Use
Responseobjects when you need custom headers or status codes - Set appropriate HTTP status codes for different scenarios
- Always validate request data before processing
- Verify webhook signatures for security
- Add cache headers for cacheable responses
- Handle errors gracefully with try-catch blocks