Core Concepts

Request & Response

Understanding the CanxRequest and CanxResponse objects for handling HTTP communication.

Request Object

The CanxRequest object wraps the native Bun Request with additional helpers.

PropertyTypeDescription
methodstringHTTP method
pathstringURL path
paramsobjectRoute parameters
queryobjectQuery parameters
idstringUnique request ID
timestampnumberRequest timestamp
request-properties.ts
1app.get("/users/:id", async (req, res) => {
2 // Request properties
3 const method = req.method; // "GET"
4 const path = req.path; // "/users/123"
5 const id = req.id; // "canx_abc123" (unique request ID)
6 const timestamp = req.timestamp; // 1705312800000
7
8 // Route parameters
9 const userId = req.params.id; // "123"
10
11 // Query parameters (from ?key=value)
12 const page = req.query.page; // "1"
13 const limit = req.query.limit; // "10"
14
15 // Headers
16 const auth = req.header("authorization");
17 const contentType = req.header("content-type");
18
19 // Cookies
20 const session = req.cookie("session_id");
21
22 return res.json({ userId, page, limit });
23});

Reading Request Body

request-body.ts
1app.post("/users", async (req, res) => {
2 // Generic body parsing (auto-detects content type)
3 const data = await req.body();
4
5 // Typed body parsing
6 interface CreateUser { name: string; email: string; }
7 const user = await req.body<CreateUser>();
8
9 return res.json({ created: user });
10});
11
12app.post("/form", async (req, res) => {
13 // Form data (multipart/form-data)
14 const formData = await req.formData();
15
16 // Uploaded files
17 const files = await req.files();
18 const avatar = files.get("avatar");
19
20 return res.json({ success: true });
21});
22
23app.post("/raw", async (req, res) => {
24 // Raw text
25 const text = await req.text();
26
27 // ArrayBuffer
28 const buffer = await req.arrayBuffer();
29
30 return res.json({ length: text.length });
31});

Request Context

Store and retrieve data throughout the request lifecycle.

context.ts
1// Store data in request context
2const authMiddleware = async (req, res, next) => {
3 const user = await verifyToken(req.header("authorization"));
4 req.context.set("user", user);
5 req.context.set("authenticated", true);
6 return next();
7};
8
9// Access context data in handler
10app.get("/profile", authMiddleware, (req, res) => {
11 const user = req.context.get("user");
12 const isAuth = req.context.get("authenticated");
13 return res.json({ user, isAuth });
14});

Response Object

The CanxResponse provides a fluent API for building responses.

json-response.ts
1app.get("/api/users", (req, res) => {
2 // Basic JSON response (200)
3 return res.json({ users: [] });
4});
5
6app.post("/api/users", async (req, res) => {
7 const user = await createUser(await req.body());
8
9 // JSON with status code
10 return res.status(201).json({
11 message: "User created",
12 data: user
13 });
14});
15
16app.get("/api/error", (req, res) => {
17 // Error response
18 return res.status(404).json({
19 error: "Not found",
20 code: "RESOURCE_NOT_FOUND"
21 });
22});

HTML & Text Responses

html-response.ts
1app.get("/page", (req, res) => {
2 return res.html(`
3 <!DOCTYPE html>
4 <html>
5 <head><title>Hello</title></head>
6 <body><h1>Hello CanxJS!</h1></body>
7 </html>
8 `);
9});
10
11app.get("/text", (req, res) => {
12 return res.text("Plain text response");
13});
14
15app.get("/empty", (req, res) => {
16 return res.empty(204); // No content
17});

Setting Headers

headers.ts
1app.get("/api/data", (req, res) => {
2 return res
3 .status(200)
4 .header("X-Request-Id", req.id)
5 .header("Cache-Control", "max-age=3600")
6 .headers({
7 "X-Custom-Header": "value",
8 "X-Another": "value2"
9 })
10 .json({ data: "example" });
11});

Cookies

cookies.ts
1app.post("/login", async (req, res) => {
2 const { username, password } = await req.body();
3 const token = await authenticate(username, password);
4
5 // Set cookie with options
6 return res
7 .cookie("session", token, {
8 httpOnly: true,
9 secure: true,
10 sameSite: "Strict",
11 maxAge: 86400, // 1 day in seconds
12 path: "/"
13 })
14 .json({ success: true });
15});
16
17app.post("/logout", (req, res) => {
18 // Clear cookie
19 return res.clearCookie("session").json({ loggedOut: true });
20});

File & Stream Responses

files.ts
1app.get("/download/:filename", async (req, res) => {
2 const path = `./uploads/${req.params.filename}`;
3
4 // Send file (inline)
5 return res.file(path);
6});
7
8app.get("/export", async (req, res) => {
9 // Download with custom filename
10 return res.download("./data/report.pdf", "monthly-report.pdf");
11});
12
13app.get("/stream", (req, res) => {
14 const stream = createReadableStream();
15 return res.stream(stream);
16});

Server-Sent Events

sse.ts
1app.get("/events", (req, res) => {
2 async function* generateEvents() {
3 for (let i = 0; i < 10; i++) {
4 yield JSON.stringify({ count: i, time: Date.now() });
5 await new Promise(r => setTimeout(r, 1000));
6 }
7 }
8
9 return res.sse(generateEvents());
10});

Redirects

redirect.ts
1app.get("/old-page", (req, res) => {
2 return res.redirect("/new-page"); // 302 default
3});
4
5app.get("/moved", (req, res) => {
6 return res.redirect("/new-url", 301); // Permanent redirect
7});

Next Steps

Explore the complete API reference or learn about database models.