You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 lines
2.6 KiB

'use strict'
const reusify = require('reusify')
const { pathToRegexp } = require('path-to-regexp')
function middie (complete) {
var middlewares = []
var pool = reusify(Holder)
return {
use,
run
}
function use (url, f) {
if (f === undefined) {
f = url
url = null
}
var regexp
if (url) {
regexp = pathToRegexp(sanitizePrefixUrl(url), [], {
end: false,
strict: false
})
}
if (Array.isArray(f)) {
for (var val of f) {
middlewares.push({
regexp,
fn: val
})
}
} else {
middlewares.push({
regexp,
fn: f
})
}
return this
}
function run (req, res, ctx) {
if (!middlewares.length) {
complete(null, req, res, ctx)
return
}
req.originalUrl = req.url
var holder = pool.get()
holder.req = req
holder.res = res
holder.url = sanitizeUrl(req.url)
holder.context = ctx
holder.done()
}
function Holder () {
this.next = null
this.req = null
this.res = null
this.url = null
this.context = null
this.i = 0
var that = this
this.done = function (err) {
var req = that.req
var res = that.res
var url = that.url
var context = that.context
var i = that.i++
req.url = req.originalUrl
if (res.finished === true) {
that.req = null
that.res = null
that.context = null
that.i = 0
pool.release(that)
return
}
if (err || middlewares.length === i) {
complete(err, req, res, context)
that.req = null
that.res = null
that.context = null
that.i = 0
pool.release(that)
} else {
var middleware = middlewares[i]
var fn = middleware.fn
var regexp = middleware.regexp
if (regexp) {
var result = regexp.exec(url)
if (result) {
req.url = req.url.replace(result[0], '')
if (req.url.startsWith('/') === false) {
req.url = '/' + req.url
}
fn(req, res, that.done)
} else {
that.done()
}
} else {
fn(req, res, that.done)
}
}
}
}
}
function sanitizeUrl (url) {
for (var i = 0, len = url.length; i < len; i++) {
var charCode = url.charCodeAt(i)
if (charCode === 63 || charCode === 35) {
return url.slice(0, i)
}
}
return url
}
function sanitizePrefixUrl (url) {
if (url === '') return url
if (url === '/') return ''
if (url[url.length - 1] === '/') return url.slice(0, -1)
return url
}
module.exports = middie