@goa/router
@goa/router
is The Router For Creating Middleware For Goa Apps.
yarn add @goa/router
Table Of Contents
- Table Of Contents
- API
- Verbs
- Allowed Methods
- Named Routes
- Multiple Middleware
- Nested Routes
- Router Prefixes
- URL Parameters
- Copyright & License
API
The package is available by importing its default class:
import Router from '@goa/router'
The example below creates a really simple router that responds to the GET /
and POST /users/:uid
requests. Because of allowedMethods
, it will also send a response to the OPTIONS
request with the allow
header.
Example | Output |
---|---|
import rqt, { aqt } from 'rqt'
import Goa from '@goa/koa'
import Router from '@goa/router'
const goa = new Goa()
const router = new Router()
router
.get('/', (ctx) => {
ctx.body = `Hello world`
})
.post('/users/:uid', (ctx) => {
ctx.body = `You have edited the user ${ctx.params.uid}`
})
goa.use(router.routes())
goa.use(router.allowedMethods()) |
# GET /
Hello world
# POST /users/100
You have edited the user 100
# OPTIONS /
HEAD, GET |
Router
: Router For Goa Apps.
Name | Type & Description |
---|---|
constructor | new (opts?: !RouterConfig) => Router |
Create a new router. import Goa from '@goa/koa'
import Router from '@goa/router'
const app = new Goa()
const router = new Router()
router.get('/', (ctx, next) => {
// ctx.router available
})
app
.use(router.routes())
.use(router.allowedMethods()) |
|
static url | (path: string, ...params: !Object[]) => string |
Generate URL from url pattern and given const url = Router.url('/users/:id', { id: 1 })
// => "/users/1" |
|
opts | !RouterConfig |
Stored options passed to the Router constructor. | |
allowedMethods | (options: !AllowedMethodsOptions) => !Middleware |
Returns separate middleware for responding to import Goa from '@goa/koa'
import Router from '@goa/router'
const app = new Goa()
const router = new Router()
app.use(router.routes())
app.use(router.allowedMethods()) |
|
param | (param: string, middleware: !Middleware) => !Router |
Run middleware for named route parameters. Useful for auto-loading or validation. router
.param('user', (id, ctx, next) => {
ctx.user = users[id]
if (!ctx.user) return ctx.status = 404
return next()
})
.get('/users/:user', ctx => {
ctx.body = ctx.user
})
.get('/users/:user/friends', async ctx => {
ctx.body = await ctx.user.getFriends()
}) |
|
redirect | (source: string, destination: string, code?: number) => !Router |
Redirect source to destination URL with optional 30x status code .
Both source and destination can be route names.
|
|
route | (name: string) => Layer |
Lookup route with given name . If the route is not found, returns null .
|
|
url | (name: string, ...params: !Object[]) => (string | !Error) |
Generate URL for route. Takes a route name and map of named // To use urls, a named route should be created:
router.get('user', '/users/:id', (ctx, next) => {
// ...
}) Get the URL by passing a simple parameter router.url('user', 3)
// => "/users/3" Get the URL by passing parameters in an object router.url('user', { id: 3 })
// => "/users/3" Use the url method for redirects to named routes: router.use((ctx) => {
ctx.redirect(ctx.router.url('sign-in'))
}) Pass an object query: router.url('user', { id: 3 }, { query: { limit: 1 } })
// => "/users/3?limit=1" Pass an already serialised query: router.url('user', { id: 3 }, { query: 'limit=1' })
// => "/users/3?limit=1" |
|
use | (path: (string | !Array<string> | !Middleware), ...middleware: !Middleware[]) => !Router |
Use given middleware.
Middleware run in the order they are defined by // session middleware will run before authorize
router
.use(session())
.use(authorize())
// use middleware only with given path
router.use('/users', userAuth())
// or with an array of paths
router.use(['/users', '/admin'], userAuth())
app.use(router.routes()) |
|
prefix | (prefix: string) => !Router |
Set the path prefix for a Router instance that was already initialized. router.prefix('/things/:thing_id') |
|
middleware routesalias |
() => !Middleware |
Returns router middleware which dispatches a route matching the request. |
RouterConfig
: Config for the router.
Name | Type | Description |
---|---|---|
methods | !Array<string> | The methods to serve. Default HEAD , OPTIONS , GET , PUT , PATCH , POST , DELETE . |
prefix | string | Prefix router paths. |
routerPath | string | Custom routing path. |
Verbs
Routes are assigned to the router by calling HTTP method verbs on the instance:
router
.get('/', (ctx, next) => {
ctx.body = 'Hello World!'
})
.post('/users', (ctx, next) => {
// ...
})
.put('/users/:id', (ctx, next) => {
// ...
})
.del('/users/:id', (ctx, next) => {
// ...
})
.all('/users/:id', (ctx, next) => {
// ...
})
Additionally, router.all()
can be used to match against all methods. router.del()
is an alias for router.delete()
.
When a route is matched, its path is available at ctx._matchedRoute
and if named, the name is available at ctx._matchedRouteName
.
Route paths will be translated to regular expressions using path-to-regexp.
Query strings will not be considered when matching requests.
Allowed Methods
The router can respond to the OPTIONS
request with the allow
header.
Example with Boom
const app = new Goa()
const router = new Router()
app.use(router.routes())
app.use(router.allowedMethods({
throw: true,
notImplemented: () => new Boom.notImplemented(),
methodNotAllowed: () => new Boom.methodNotAllowed(),
}))
AllowedMethodsOptions
: The options for the allowedMethods
middleware generation.
Name | Type | Description |
---|---|---|
throw | boolean | Throw error instead of setting status and header. |
notImplemented | () => !Error | Throw the returned value in place of the default NotImplemented error. |
methodNotAllowed | () => !Error | Throw the returned value in place of the default MethodNotAllowed error. |
Named Routes
Routes can optionally have names. This allows generation of URLs and easy renaming of URLs during development.
router.get('user', '/users/:id', (ctx, next) => {
// ...
})
router.url('user', 3)
// => "/users/3"
Multiple Middleware
Multiple middleware may be passed to the router.
router.get(
'/users/:id',
async (ctx, next) => {
const user = await User.findOne(ctx.params.id)
ctx.user = user
await next()
},
ctx => {
console.log(ctx.user)
// => { id: 17, name: "Alex" }
}
)
Nested Routes
It's possible to create a Router instance, and then pass another Router instance to its .use
call to nest the two.
Source | Output |
---|---|
const forums = new Router()
const posts = new Router()
posts.get('/', (ctx) => {
ctx.body = ctx.params
})
posts.get('/:pid', (ctx) => {
ctx.body = ctx.params
})
forums.use('/forums/:fid/posts',
posts.routes(),
posts.allowedMethods())
goa.use(forums.routes()) |
// GET /forums/123/posts
{ fid: '123' }
// GET /forums/123/posts/123
{ fid: '123', pid: '123' }
|
Router Prefixes
Route paths can be prefixed at the router level.
const router = new Router({
prefix: '/users',
})
router.get('/', (ctx) => {
// responds to "/users"
ctx.body = ctx.params
})
router.get('/:id', (ctx) => {
// responds to "/users/:id"
ctx.body = ctx.params
})
goa.use(router.routes())
// Request /users
{}
// Request /users/123
{ id: '123' }
URL Parameters
Named route parameters are captured and added to ctx.params
.
const router = new Router()
router.get('/:category/:title', (ctx) => {
// the params are exposed to the context.
ctx.body = ctx.params
})
goa.use(router.routes())
// Request /programming/how-to-node
{ category: 'programming', title: 'how-to-node' }
Copyright & License
GNU Affero General Public License v3.0
Original Work by Alexander C. Mingoia under MIT License found in COPYING.
There's also a fork in the Koa org.
© Idio 2019 |