Skip to content

Commit

Permalink
initial commit 1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
jkyberneees committed Jan 6, 2019
1 parent 92a090e commit de41864
Show file tree
Hide file tree
Showing 7 changed files with 3,706 additions and 1 deletion.
107 changes: 106 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,107 @@
# middleware-if-unless
Invokes connect-like middleware if / unless routing criteria matches. Inspired on express-unless module.
Invokes connect-like middleware if / unless routing criteria matches. Inspired on [express-unless](https://www.npmjs.com/package/express-unless) module.

## Main features
- Advanced routes matching capabilities. Uses [find-my-way](https://www.npmjs.com/package/find-my-way) or any compatible router to match the routes.
- `iff`: execute middleware only if the routes matches. Ideal use case: API gateways (see: [k-fastify-gateway](https://www.npmjs.com/package/k-fastify-gateway))
- `unless`: execute middleware always unless the routes matches.
- Arbitraty chaining of iff -> unless of vice-versa.
- Low overhead, crazy fast implementation.


# Usage example
How to extend any connect-like middleware:
```js
const iu = require('middleware-if-unless')()

const middleware = function (req, res, next) {
res.body = 'hit'

return next()
}

// extend middleware with iff/unless capabilities
iu(middleware)
```
## unless
Execute middleware unless routing restrictions matches:
```js
const app = require('express')()
app.use(middleware.unless([
'/not/allowed/to/hit'
]))

...
```
In this example, all requests except `[GET] /not/allowed/to/hit` will cause the middleware to be executed.

## if
Execute middleware only if routing restrictions matches:
```js
const app = require('express')()
app.use(middleware.iff([
{
methods: ['POST', 'DELETE', 'PUT', 'PATCH'],
url: '/tasks/:id'
}
]))

...
```
### Chaining
You can optionally chain iff -> unless or vice-versa:
```js
app.use(middleware
.iff(req => req.url.startsWith('/pets')) // 4 check
.iff([ // 3 check
'/pets/*',
'/pets/:id/*'
]).unless([ // 2 check
'/pets/:id/owners',
{
url: '/pets/:id', methods: ['DELETE']
}
]).unless(req => req.url.endsWith('.js')) // 1 check
)
```
# Configuration
## module
```js
const iu = require('middleware-if-unless')(
// optional router configuration:
// https://www.npmjs.com/package/find-my-way#findmywayoptions
{
}
,
// optional router factory:
// allows to override find-my-way as default router
function(opts){}
)
```
## iff / unless
Both methods share the same configuration format:

### - routing criteria is a function
```js
middleware.iff(req => req.url.startsWith('/pets'))
```
### - routing criteria is an array of routes
```js
middleware.iff([
'/login', // if string is passed, the GET method is inferred
{
methods: ['DELETE', 'POST', '...'],
url: '/task/:id/*'
}
])
```
### - routing criteria is an object
```js
middleware.unless({ endpoints: [
'/login', // if string is passed, the GET method is inferred
{
methods: ['DELETE', 'POST', '...'],
url: '/task/:id/*'
}
]})
```
68 changes: 68 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const op = () => true

module.exports = function (routerOpts = {}, routerFactory) {
routerOpts.defaultRoute = () => false
routerFactory = routerFactory || require('find-my-way')

function exec (options, isIff = true) {
const middleware = this

// independent router instance per config
const router = routerFactory(routerOpts)

const opts = typeof options === 'function' ? { custom: options } : (Array.isArray(options) ? { endpoints: options } : options)
if (opts.endpoints && opts.endpoints.length) {
// setup matching router
opts.endpoints.map(endpoint => typeof endpoint === 'string' ? { methods: ['GET'], url: endpoint } : endpoint).forEach(({ methods, url }) => {
router.on(methods, url, op)
})
}

const result = function (req, res, next) {
// supporting custom matching function
if (opts.custom) {
if (opts.custom(req)) {
if (isIff) {
return middleware(req, res, next)
}
} else if (!isIff) {
return middleware(req, res, next)
}

// leave here and do not process opts.endpoints
return next()
}

// matching endpoints and moving forward
if (router.lookup(req, res)) {
if (isIff) {
return middleware(req, res, next)
}
} else if (!isIff) {
return middleware(req, res, next)
}

return next()
}

// allowing chaining
result.iff = iff
result.unless = unless

return result
}

function iff (options) {
return exec.call(this, options, true)
}
function unless (options) {
return exec.call(this, options, false)
}

return function (middleware) {
middleware.iff = iff
middleware.unless = unless

return middleware
}
}
Loading

0 comments on commit de41864

Please sign in to comment.