An open API service indexing awesome lists of open source software.

https://github.com/idiocc/goa-router

The Router For Creating Middleware For Goa Apps.
https://github.com/idiocc/goa-router

Last synced: about 1 year ago
JSON representation

The Router For Creating Middleware For Goa Apps.

Awesome Lists containing this project

README

          

# @goa/router

[![npm version](https://badge.fury.io/js/%40goa%2Frouter.svg)](https://www.npmjs.com/package/@goa/router)

`@goa/router` is The Router For Creating Middleware For Goa Apps.

```sh
yarn add @goa/router
```

## Table Of Contents

- [Table Of Contents](#table-of-contents)
- [API](#api)
* [`Router`](#type-router)
* [RouterConfig](#type-routerconfig)
- [Verbs](#verbs)
- [Allowed Methods](#allowed-methods)
* [`AllowedMethodsOptions`](#type-allowedmethodsoptions)
- [Named Routes](#named-routes)
- [Multiple Middleware](#multiple-middleware)
- [Nested Routes](#nested-routes)
- [Router Prefixes](#router-prefixes)
- [URL Parameters](#url-parameters)
- [Copyright & License](#copyright--license)



## API

The package is available by importing its default class:

```js
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.

ExampleOutput

```js
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())
```

```sh

# 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.
```js
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 `params`.
```js
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 `OPTIONS` requests with
an `Allow` header containing the allowed methods, as well as responding
with `405 Method Not Allowed` and `501 Not Implemented` as appropriate.
```js
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.
```js
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 `params`. If the route is not found, returns an error. The last argument can be an object with the `query` property.
```js
// To use urls, a named route should be created:
router.get('user', '/users/:id', (ctx, next) => {
// ...
})
```
Get the URL by passing a **simple** parameter
```js
router.url('user', 3)
// => "/users/3"
```
Get the URL by passing parameters in an **object**
```js
router.url('user', { id: 3 })
// => "/users/3"
```
Use the url method for **redirects** to named routes:
```js
router.use((ctx) => {
ctx.redirect(ctx.router.url('sign-in'))
})
```
Pass an **object query**:
```js
router.url('user', { id: 3 }, { query: { limit: 1 } })
// => "/users/3?limit=1"
```
Pass an already **serialised query**:
```js
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 `.use()`. They are invoked
sequentially, requests start at the first middleware and work their way
"down" the middleware stack.
```js
// 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.
```js
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:

```js
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](https://github.com/pillarjs/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](https://github.com/hapijs/boom)**

```js
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.

```js
router.get('user', '/users/:id', (ctx, next) => {
// ...
})

router.url('user', 3)
// => "/users/3"
```



## Multiple Middleware

Multiple middleware may be passed to the router.

```js
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.

SourceOutput

```js
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())
```

```js

// 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.

```js
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())
```
```js
// Request /users
{}
// Request /users/123
{ id: '123' }
```



## URL Parameters

Named route parameters are captured and added to `ctx.params`.

```js
const router = new Router()

router.get('/:category/:title', (ctx) => {
// the params are exposed to the context.
ctx.body = ctx.params
})

goa.use(router.routes())
```
```js
// Request /programming/how-to-node
{ category: 'programming', title: 'how-to-node' }
```



## Copyright & License

GNU Affero General Public License v3.0

[Original Work](https://github.com/ZijianHe/koa-router) by Alexander C. Mingoia under MIT License found in [COPYING](https://github.com/ZijianHe/koa-router/blob/master/LICENSE).

There's also a fork in the [Koa org](https://github.com/koajs/router).


idiocc
© Idio 2019