Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions examples/01-hello-world/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* 01 — Hello World
*
* The simplest possible http-native server.
* Registers a single GET route and starts listening on port 3000.
*
* Run:
* bun examples/01-hello-world/server.js
*
* Test:
* curl http://localhost:3000/
*/

import { createApp } from "@http-native/core";

const app = createApp();

/**
* A basic GET route that returns a JSON response.
* This route is automatically optimized by the Rust static fast-path
* analyzer — the response is served directly from Rust without
* crossing the JS bridge.
*/
app.get("/", (req, res) => {
res.json({ message: "Hello from http-native!" });
});

const server = await app.listen({ port: 3000 });

console.log(`Server running at ${server.url}`);
44 changes: 44 additions & 0 deletions examples/02-route-params/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* 02 — Route Parameters
*
* Demonstrates parameterized routes with :param syntax.
* Parameters are extracted from the URL path and available
* via req.params.
*
* Run:
* bun examples/02-route-params/server.js
*
* Test:
* curl http://localhost:3000/users/42
* curl http://localhost:3000/posts/7/comments/3
*/

import { createApp } from "@http-native/core";

const app = createApp();

/**
* Single parameter route.
* GET /users/42 → { id: "42", type: "user" }
*/
app.get("/users/:id", (req, res) => {
res.json({
id: req.params.id,
type: "user",
});
});

/**
* Multiple parameters in a single route.
* GET /posts/7/comments/3 → { postId: "7", commentId: "3" }
*/
app.get("/posts/:postId/comments/:commentId", (req, res) => {
res.json({
postId: req.params.postId,
commentId: req.params.commentId,
});
});

const server = await app.listen({ port: 3000 });

console.log(`Server running at ${server.url}`);
95 changes: 95 additions & 0 deletions examples/03-http-methods/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* 03 — HTTP Methods
*
* Demonstrates all supported HTTP methods: GET, POST, PUT,
* DELETE, PATCH, OPTIONS, and the catch-all `all()`.
*
* Run:
* bun examples/03-http-methods/server.js
*
* Test:
* curl http://localhost:3000/items
* curl -X POST -H "Content-Type: application/json" -d '{"name":"Widget"}' http://localhost:3000/items
* curl -X PUT -H "Content-Type: application/json" -d '{"name":"Gadget"}' http://localhost:3000/items/1
* curl -X DELETE http://localhost:3000/items/1
* curl -X PATCH -H "Content-Type: application/json" -d '{"name":"Updated"}' http://localhost:3000/items/1
*/

import { createApp } from "@http-native/core";

const app = createApp();

/** In-memory store for demonstration */
const items = new Map();
let nextId = 1;

/**
* GET /items — List all items
*/
app.get("/items", (req, res) => {
res.json({ items: [...items.values()] });
});

/**
* POST /items — Create a new item
* Reads the JSON body via req.json()
*/
app.post("/items", (req, res) => {
const body = req.json();
if (!body || !body.name) {
return res.status(400).json({ error: "name is required" });
}

const id = String(nextId++);
const item = { id, name: body.name };
items.set(id, item);

res.status(201).json(item);
});

/**
* PUT /items/:id — Replace an item
*/
app.put("/items/:id", (req, res) => {
const body = req.json();
if (!body || !body.name) {
return res.status(400).json({ error: "name is required" });
}

const item = { id: req.params.id, name: body.name };
items.set(req.params.id, item);

res.json(item);
});

/**
* PATCH /items/:id — Partially update an item
*/
app.patch("/items/:id", (req, res) => {
const existing = items.get(req.params.id);
if (!existing) {
return res.status(404).json({ error: "Item not found" });
}

const body = req.json();
const updated = { ...existing, ...body };
items.set(req.params.id, updated);

res.json(updated);
});

/**
* DELETE /items/:id — Delete an item
*/
app.delete("/items/:id", (req, res) => {
const existed = items.delete(req.params.id);
if (!existed) {
return res.status(404).json({ error: "Item not found" });
}

res.json({ deleted: true });
});

const server = await app.listen({ port: 3000 });

console.log(`Server running at ${server.url}`);
65 changes: 65 additions & 0 deletions examples/04-middleware/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* 04 — Middleware
*
* Demonstrates global middleware, path-scoped middleware,
* and the next() function for chaining.
*
* Run:
* bun examples/04-middleware/server.js
*
* Test:
* curl http://localhost:3000/
* curl http://localhost:3000/admin/dashboard
* curl -H "Authorization: Bearer secret-token" http://localhost:3000/admin/dashboard
*/

import { createApp } from "@http-native/core";

const app = createApp();

/**
* Global middleware — runs on every request.
* Logs the method and path, then calls next() to continue.
*/
app.use((req, res, next) => {
console.log(`${req.method} ${req.path}`);
return next();
});

/**
* Global middleware — adds a custom response header.
* Middleware without next() auto-advances to the next middleware.
*/
app.use((req, res) => {
res.set("X-Powered-By", "http-native");
});

/**
* Path-scoped middleware — only runs for /admin/* routes.
* Checks for an Authorization header before allowing access.
*/
app.use("/admin", (req, res, next) => {
const auth = req.header("authorization");
if (!auth || auth !== "Bearer secret-token") {
return res.status(401).json({ error: "Unauthorized" });
}
return next();
});

/**
* Public route — accessible without authentication.
*/
app.get("/", (req, res) => {
res.json({ message: "Public endpoint" });
});

/**
* Protected route — requires the /admin middleware to pass.
*/
app.get("/admin/dashboard", (req, res) => {
res.json({ message: "Admin dashboard", secret: "classified data" });
});

const server = await app.listen({ port: 3000 });

console.log(`Server running at ${server.url}`);
70 changes: 70 additions & 0 deletions examples/05-error-handling/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* 05 — Error Handling
*
* Demonstrates global error handlers, custom 404 pages,
* and throwing errors from route handlers.
*
* Run:
* bun examples/05-error-handling/server.js
*
* Test:
* curl http://localhost:3000/
* curl http://localhost:3000/fail
* curl http://localhost:3000/not-a-real-route
*/

import { createApp } from "@http-native/core";

const app = createApp();

/**
* A route that works normally.
*/
app.get("/", (req, res) => {
res.json({ status: "ok" });
});

/**
* A route that deliberately throws an error.
* The error handler below will catch it.
*/
app.get("/fail", (req, res) => {
throw new Error("Something went wrong!");
});

/**
* A route that throws a custom HTTP error with a status code.
*/
app.get("/forbidden", (req, res) => {
const error = new Error("Access denied");
error.status = 403;
throw error;
});

/**
* Custom 404 handler — catches all unmatched routes.
* Uses the app.404() shorthand.
*/
app["404"]((req, res) => {
res.status(404).json({
error: "Not Found",
path: req.path,
hint: "Try GET / or GET /fail",
});
});

/**
* Global error handler — catches all thrown errors.
* Receives (error, req, res) instead of (req, res).
*/
app.error((error, req, res) => {
const status = error.status || 500;
res.status(status).json({
error: error.message || "Internal Server Error",
path: req.path,
});
});

const server = await app.listen({ port: 3000 });

console.log(`Server running at ${server.url}`);
56 changes: 56 additions & 0 deletions examples/06-cors/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* 06 — CORS (Cross-Origin Resource Sharing)
*
* Demonstrates the built-in CORS middleware with various
* configurations: wildcard, specific origins, and credentials.
*
* Run:
* bun examples/06-cors/server.js
*
* Test:
* curl -H "Origin: https://example.com" -v http://localhost:3000/api/data
* curl -X OPTIONS -H "Origin: https://example.com" -v http://localhost:3000/api/data
*/

import { createApp } from "@http-native/core";
import { cors } from "@http-native/core/cors";

const app = createApp();

/**
* Apply CORS middleware globally.
* This allows requests from specific origins with credentials.
*/
app.use(
cors({
origin: ["https://example.com", "https://app.example.com"],
methods: ["GET", "POST", "PUT", "DELETE"],
allowedHeaders: ["Content-Type", "Authorization"],
credentials: true,
maxAge: 86400,
}),
);

/**
* API endpoint — CORS headers are automatically added.
*/
app.get("/api/data", (req, res) => {
res.json({
items: [
{ id: 1, name: "Alpha" },
{ id: 2, name: "Beta" },
],
});
});

/**
* Another endpoint — same CORS policy applies.
*/
app.post("/api/data", (req, res) => {
const body = req.json();
res.status(201).json({ created: true, data: body });
});

const server = await app.listen({ port: 3000 });

console.log(`Server running at ${server.url}`);
Loading
Loading