1.0.9 • Published 2 years ago

koa-branch-router v1.0.9

Weekly downloads
2
License
ISC
Repository
github
Last release
2 years ago

Koa branch router

Coverage Status

Koa branch router is a simple radix tree (-ish) router for koa.

Why?

  • There seem to be no radix tree routers with nested router support (at the time of writing).
  • Popular routers handle middlewares in an inconvenient way. See Middleware Routing.

Features

  • Express-style routing using verbs like router.get, router.put, router.post, etc.
  • Nested routes and middlewares.
  • Path params and wildcard capturing.

Usage

const Koa = require('koa');
const Router = require('koa-branch-router');

const app = new Koa();
const router = new Router();

router.get('/', (ctx) => {
  ctx.body = 'Hello World!';
});

app.use(router.routes());
app.listen(9000);

Middleware Routing

Middlewares are only called if a handler registered in the same router matches agaist the path.

Note

Middlewares and Handlers are essentially the same except:

// treated as a middleware if added using .use()
router.use('/', middleware)

// treated as a handler if added using .all() or .get(), .post() etc
router.all('/', handler)

Routing Example

// the path `/users/42/images`

router
  .use('/users', new Router()
    .use(userMiddleware) // <-- not called
    .get('/', listUsers)
    .get('/:userId', getUser)

  .use('/users/:userId/images', new Router()
    .use(imageMiddleware) // <-- called
    .get('/', listImages) // <-- called
    .get('/:imageId', getImage);

If you dont want this behaviour, you should use a route fragment.

// the path `/users/42/images`

router
  .use('/users', new Router.Fragment()
    .use(userMiddleware)) // <-- called

      // fragments don't add a routing boundary and
      // behave like a middleware registered on the
      // parent router.

  .use('/users', new Router()
    .use(userMiddleware) // <-- not called
    .get('/', listUsers)
    .get('/:userId', getUser)

  .use('/users/:userId/images', new Router()
    .use(imageMiddleware) // <-- called
    .get('/', listImages) // <-- called
    .get('/:imageId', getImage);

Nested Routers

You may nest routers.

const userRouter = new Router()
  .use('/', listUsers) // becomes `/users/`
  .use('/:id', getUser); // becomes `/users/:id`

const tokenRouter = new Router({ prefix: '/tokens' })
  .use('/', listUsers) // becomes `/auth/tokens/`
  .use('/:id', getUser); // becomes `/auth/tokens/:id`

const fileRouter = new Router()
  .use('/files', listFiles) // remains `/files/`
  .use('/files/:id', getFile)); // remains `/files/:id`

const rootRouter = router
  .use('/users', userRouter)
  .use('/auth', tokenRouter)
  .use(fileRouter);

Path Matching

Static

router.all('/users', ...)
PathMatch
/userstrue
/users/42false

Named Parameters

Named parameters like :name match a single path segment delimited by /

router.all('/users/:name', ...)
PathMatchCaptured Params
/usersfalse
/users/gwentrue{ name: 'gwen' }
/users/profiletrue{ name: 'profile' }
/users/gwen/profilefalse

Wildcard

Catches paths starting with the provided path, and captures the rest until the end.

router.all('/users/*path', ...)
PathMatchCaptured Params
/usersfalse
/users/gwentrue{ path: 'gwen' }
/users/profiletrue{ path: 'profile' }
/users/gwen/profiletrue{ path: 'gwen/profile' }

Wildcards can be used without capturing as well.

router.all('/users/*', ...)

Quirks

  • Captured parameters are decoded using decodeURIComponent, whereas wildcard captures are not.

API

new Router(options)

Initialize a new router.

Options

OptionDefaultDescription
options.prefix''Router prefix
options.caseSensitivefalseCase sensitive paths
options.strictfalseTreat /foo and /foo/ as different urls

router.verb()

Registers handlers for path. Supported verbs are:

router
  .get(path, ctx => ...)
  .post(path, ctx => ...)
  .patch(path, ctx => ...)
  .put(path, ctx => ...)
  .delete(path, ctx => ...)
  .del(path, ctx => ...) // alias for `.delete()`
  .all(path, ctx => ...); // matches all methods

You may pass multiple handlers.

router.get(
  path,
  (ctx, next) => ...,
  (ctx) => ...);

router.use()

Registers middleware for path

router
  .use(parseToken)
  .use(authorize);
// or multiple
router.use(parseToken, authorize);
// or with path
router.use('/users', authUser);

router.routes()

Returns router middleware.

app.use(router.routes());

new Router.Fragment(options)

Initialize a new route fragment. Fragments don't add a routing boundary and behave like a middleware registered on the parent router. See Middleware Routing.

Accepts the same options as a router. See Router Options

The API is again similar to the router except that there is no .routes() method. Only routers can be mounted on apps.

ctx.params

This object contains key-value pairs of named route parameters.

// GET /user/42
router.get('/user/:name', (ctx) => {
  ctx.params.name // => '42'
});
1.0.9

2 years ago

1.0.8

3 years ago

1.0.7

3 years ago

1.0.6

3 years ago

1.0.5

4 years ago

1.0.4

4 years ago

1.0.2

4 years ago

1.0.3

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago

1.0.0-beta.6

4 years ago

1.0.0-beta.4

4 years ago

1.0.0-beta.5

4 years ago

1.0.0-beta.2

4 years ago

1.0.0-beta.3

4 years ago

1.0.0-beta.1

4 years ago

1.0.0-beta.0

4 years ago