Bunary is v0.x and under active development — APIs may still move between minor releases.

    Requests

    Accessing and working with incoming HTTP requests.

    The Request Context

    Every route handler receives a RequestContext object with access to the incoming request data:

    app.post("/users", async (ctx) => {
      // The context provides:
      ctx.request  // The native Request object
      ctx.params   // Route parameters (e.g., { id: "123" })
      ctx.query    // URLSearchParams object
      
      return { received: true };
    });
    

    Accessing Request Properties

    Access request data through the native ctx.request object:

    app.post("/users", async (ctx) => {
      const method = ctx.request.method;  // "POST"
      const url = new URL(ctx.request.url);
      const path = url.pathname;          // "/users"
      
      return { method, path };
    });
    

    Request Headers

    Access request headers through ctx.request.headers:

    app.get("/info", (ctx) => {
      const contentType = ctx.request.headers.get("content-type");
      const authorization = ctx.request.headers.get("authorization");
      const userAgent = ctx.request.headers.get("user-agent");
      
      return {
        contentType,
        hasAuth: !!authorization,
        userAgent,
      };
    });
    

    Route Parameters

    Access dynamic route segments via ctx.params:

    // GET /users/123
    app.get("/users/:id", (ctx) => {
      const id = ctx.params.id; // "123"
      return { userId: id };
    });
    
    // GET /posts/456/comments/789
    app.get("/posts/:postId/comments/:commentId", (ctx) => {
      const { postId, commentId } = ctx.params;
      return { postId, commentId };
    });
    

    Query Parameters

    Access query string parameters via ctx.query, which is a URLSearchParams object:

    // GET /search?q=bunary&page=2&limit=10
    app.get("/search", (ctx) => {
      const q = ctx.query.get("q");           // "bunary"
      const page = ctx.query.get("page");     // "2"
      const limit = ctx.query.get("limit");   // "10"
      
      return {
        query: q,
        page: parseInt(page || "1"),
        limit: parseInt(limit || "20"),
      };
    });
    
    // Get all values for a key
    // GET /filter?tag=typescript&tag=bun
    app.get("/filter", (ctx) => {
      const tags = ctx.query.getAll("tag"); // ["typescript", "bun"]
      return { tags };
    });
    

    Request Body

    Parse the request body using the native Request methods:

    JSON Body

    app.post("/users", async (ctx) => {
      const body = await ctx.request.json();
      
      return {
        received: body,
        name: body.name,
        email: body.email,
      };
    });
    

    Form Data

    app.post("/contact", async (ctx) => {
      const formData = await ctx.request.formData();
      
      const name = formData.get("name");
      const email = formData.get("email");
      const message = formData.get("message");
      
      return { name, email, message };
    });
    

    Raw Text

    app.post("/webhook", async (ctx) => {
      const rawBody = await ctx.request.text();
      
      return { received: rawBody.length };
    });
    

    Typed Request Bodies

    Use TypeScript type assertions for type-safe request handling:

    interface CreateUserBody {
      name: string;
      email: string;
      password: string;
    }
    
    app.post("/users", async (ctx) => {
      const body = await ctx.request.json() as CreateUserBody;
      
      // TypeScript knows body.name, body.email, body.password
      const user = await createUser(body);
      
      return user;
    });
    

    Last updated