-
Notifications
You must be signed in to change notification settings - Fork 0
Routing
Tanzim Hossain edited this page Apr 28, 2026
·
4 revisions
NextRush uses a high-performance segment-trie router (@nextrush/router) with O(k) path matching where k is the number of path segments. Static routes additionally use an O(1) hash map fast path.
import { createRouter } from 'nextrush';
const router = createRouter();
// or with options:
const router = createRouter({
prefix: '/api', // prepended to all routes
caseSensitive: false, // (default) — /Users matches /users
strict: false, // (default) — trailing slash ignored
});router.get('/users', (ctx) => ctx.json([]));
router.post('/users', (ctx) => ctx.json({ created: true }));
router.put('/users/:id', (ctx) => ctx.json({ updated: ctx.params.id }));
router.patch('/users/:id', (ctx) => ctx.json({ patched: ctx.params.id }));
router.delete('/users/:id', (ctx) => { ctx.status = 204; });
router.head('/users', (ctx) => { ctx.status = 200; });
router.options('/users', (ctx) => { ctx.status = 200; });
// All HTTP methods at once
router.all('/health', (ctx) => ctx.json({ status: 'ok' }));
// Explicit method name
router.route('GET', '/users', (ctx) => ctx.json([]));Named route parameters are captured with :name syntax:
router.get('/users/:id', (ctx) => {
const { id } = ctx.params; // string
ctx.json({ id });
});
// Multiple parameters
router.get('/orgs/:orgId/repos/:repoId', (ctx) => {
const { orgId, repoId } = ctx.params;
ctx.json({ orgId, repoId });
});// Matches /files/any/nested/path
router.get('/files/*', (ctx) => {
ctx.json({ path: ctx.params['*'] });
});Pass middleware functions before the final handler:
const auth = async (ctx, next) => {
if (!ctx.get('authorization')) {
ctx.status = 401;
ctx.json({ error: 'Unauthorized' });
return;
}
await next();
};
// auth runs first, then the handler
router.get('/protected', auth, (ctx) => {
ctx.json({ data: 'secret' });
});// Permanent redirect (default 301)
router.redirect('/old-path', '/new-path');
// Temporary redirect
router.redirect('/temp', '/destination', 302);
// With parameter substitution
router.redirect('/users/:id', '/profiles/:id');Mount a router onto the application at a path prefix:
import { createApp, createRouter, listen } from 'nextrush';
const users = createRouter();
users.get('/', (ctx) => ctx.json([])); // GET /api/users
users.get('/:id', (ctx) => ctx.json({})); // GET /api/users/:id
users.post('/', (ctx) => ctx.json({})); // POST /api/users
const posts = createRouter();
posts.get('/', (ctx) => ctx.json([])); // GET /api/posts
const app = createApp();
app.route('/api/users', users);
app.route('/api/posts', posts);
listen(app, 3000);Routers can also be composed with app.use() via router.routes():
// Directly as middleware
app.use(router.routes());
// Or via app.route() (recommended — handles prefix stripping automatically)
app.route('/api', router);| Option | Type | Default | Description |
|---|---|---|---|
prefix |
string |
'' |
Path prefix prepended to all routes |
caseSensitive |
boolean |
false |
Whether path matching is case-sensitive |
strict |
boolean |
false |
Whether trailing slashes are significant |
Query parameters are available on ctx.query (not part of routing, always available):
router.get('/search', (ctx) => {
const { q, page = '1' } = ctx.query as { q?: string; page?: string };
ctx.json({ query: q, page: Number(page) });
});
// GET /search?q=hello&page=2Registering the same method + path twice throws at startup:
router.get('/users', handler1);
router.get('/users', handler2); // Error: Route conflict: GET /users is already registeredNextRush · MIT License · Docs · Issues