# [![IOPA](https://iopa.io/iopa.png)](https://iopa.io)<br> @iopa/router

[![NPM](https://img.shields.io/badge/iopa-certified-99cc33.svg?style=flat-square)](https://iopa.io/)

[![NPM](https://nodei.co/npm/@iopa/router.png?downloads=true)](https://nodei.co/npm/@iopa/router/)

## About

`@iopa/router` is lightweight and fast router for the IOPA framework

It routes HTTP, COAP and MQTT requests, with simple uri templates and parameter/query string parsing.

## Usage

### Installation:

    npm install @iopa/router

### Hello World

```ts
import type { IContextIopa, IRouterApp, Next} from '@iopa/types'
import { RouterApp } from 'iopa'
import { RouterMiddleware }  from '@iopa/router'

const app: IRouterApp = new RouterApp()

app
  .use(FlipperMiddleware, 'Flipper Middleware')
  .use(RouterMiddleware, 'Router Middleware')
  .get('/hello', async function (context: IContextIopa, next: Next) {
    return context.response.html('<HTML><HEAD></HEAD><BODY>Hello World</BODY>')
  })
  .get('/goodbye', async function (context: IContextIopa, next: Next) {
    return context.response.html('<HTML><HEAD></HEAD><BODY>Goodbye World</BODY>')
  })
```

## Methods
- `app.get`: Match method `GET` requests
- `app.post`: Match method `POST` requests
- `app.put`: Match method `PUT` requests
- `app.head`: Match method `HEAD` requests
- `app.del`: Match `method DELETE` requests
- `app.options`: Match method `OPTIONS` requests
- `app.all`: Match all above request methods

## API

If you want to grab a part of the path you can use capture groups in the pattern:

```js
route.get('/id/:customer', function(context) {
	var customer = context.params.customer; // ex: if the path is /id/bar, then customer = bar
```

Query paramaters in the url are also added to `context.params`:

```js
route.get('/id/:customer', function(context) {
  var base = context.params.base // ex: if the path is /id/bar?name=dog, then customer = bar
  var name = context.params.name // ex: if the path is /id/bar?name=dog, then name = dog
})
```


## Routing

### Basic

```ts
// HTTP Methods
app.get('/', (c) => c.response.text('GET /'))
app.post('/', (c) => c.response.text('POST /'))
app.put('/', (c) => c.response.text('PUT /'))
app.delete('/', (c) => c.response.text('DELETE /'))

// Wildcard
app.get('/wild/*/card', (c) => {
  return c.response.text('GET /wild/*/card')
})

// Any HTTP methods
app.all('/hello', (c) => c.response.text('Any Method /hello'))
```

### Named Parameter

```ts
app.get('/user/:name', (c) => {
  const name = c.param('name')
  ...
})
```

or all parameters at once:

```ts
app.get('/posts/:id/comment/:comment_id', (c) => {
  const { id, comment_id } = c.param()
  ...
})
```

### Regexp

```ts
app.get('/post/:date{[0-9]+}/:title{[a-z]+}', (c) => {
  const { date, title } = c.req.param()
  ...
})
```

### Chained route

```ts
app
  .get('/endpoint', (c) => {
    return c.response.text('GET /endpoint')
  })
  .post((c) => {
    return c.response.text('POST /endpoint')
  })
  .delete((c) => {
    return c.response.text('DELETE /endpoint')
  })
```

## Not Found Handler (use default App in IOPA)

```ts
function NotFound(context: IContextIopa): HandlerResult {
  return context.respondWith({msg: 'NOT FOUND'}, 404)
}
NotFound.id = 'NotFound'
app.properties.set('server.NotFound', NotFound)
```


## Prior Art

For V4, this router was ported from [honojs/hono](https://github.com/honojs/hono) which was developed under MIT license by Yusuke Wada, and enhanced and simplified to fit the `IOPA` architecture.   Essentially the very fast Trie Router and RegExp Router are provided by `hono` unchanged, with most of the pipeline composition handled by `IOPA`

It has been developed to be a core component of the `IOPA` ecosystem.


## License

MIT