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.
497 lines
10 KiB
497 lines
10 KiB
4 years ago
|
'use strict'
|
||
|
|
||
|
const middie = require('./middie')
|
||
|
const t = require('tap')
|
||
|
const http = require('http')
|
||
|
const serveStatic = require('serve-static')
|
||
|
const test = t.test
|
||
|
|
||
|
test('use no function', t => {
|
||
|
t.plan(3)
|
||
|
|
||
|
const instance = middie(function (err, a, b) {
|
||
|
t.error(err)
|
||
|
t.equal(a, req)
|
||
|
t.equal(b, res)
|
||
|
})
|
||
|
|
||
|
const req = {
|
||
|
url: '/test'
|
||
|
}
|
||
|
const res = {}
|
||
|
|
||
|
instance.run(req, res)
|
||
|
})
|
||
|
|
||
|
test('use a function', t => {
|
||
|
t.plan(5)
|
||
|
|
||
|
const instance = middie(function (err, a, b) {
|
||
|
t.error(err)
|
||
|
t.equal(a, req)
|
||
|
t.equal(b, res)
|
||
|
})
|
||
|
const req = {
|
||
|
url: '/test'
|
||
|
}
|
||
|
const res = {}
|
||
|
|
||
|
t.equal(instance.use(function (req, res, next) {
|
||
|
t.pass('function called')
|
||
|
next()
|
||
|
}), instance)
|
||
|
|
||
|
instance.run(req, res)
|
||
|
})
|
||
|
|
||
|
test('use two functions', t => {
|
||
|
t.plan(5)
|
||
|
|
||
|
const instance = middie(function (err, a, b) {
|
||
|
t.error(err)
|
||
|
t.equal(a, req)
|
||
|
t.equal(b, res)
|
||
|
})
|
||
|
const req = {
|
||
|
url: '/test'
|
||
|
}
|
||
|
const res = {}
|
||
|
var counter = 0
|
||
|
|
||
|
instance.use(function (req, res, next) {
|
||
|
t.is(counter++, 0, 'first function called')
|
||
|
next()
|
||
|
}).use(function (req, res, next) {
|
||
|
t.is(counter++, 1, 'second function called')
|
||
|
next()
|
||
|
})
|
||
|
|
||
|
instance.run(req, res)
|
||
|
})
|
||
|
|
||
|
test('stop the middleware chain if one errors', t => {
|
||
|
t.plan(1)
|
||
|
|
||
|
const instance = middie(function (err, a, b) {
|
||
|
t.ok(err, 'error is forwarded')
|
||
|
})
|
||
|
const req = {
|
||
|
url: '/test'
|
||
|
}
|
||
|
const res = {}
|
||
|
|
||
|
instance.use(function (req, res, next) {
|
||
|
next(new Error('kaboom'))
|
||
|
}).use(function (req, res, next) {
|
||
|
t.fail('this should never be called')
|
||
|
next()
|
||
|
})
|
||
|
|
||
|
instance.run(req, res)
|
||
|
})
|
||
|
|
||
|
test('run restricted by path', t => {
|
||
|
t.plan(11)
|
||
|
|
||
|
const instance = middie(function (err, a, b) {
|
||
|
t.error(err)
|
||
|
t.equal(a, req)
|
||
|
t.equal('/test', req.url)
|
||
|
t.equal(b, res)
|
||
|
})
|
||
|
const req = {
|
||
|
url: '/test'
|
||
|
}
|
||
|
const res = {}
|
||
|
|
||
|
t.equal(instance.use(function (req, res, next) {
|
||
|
t.ok('function called')
|
||
|
next()
|
||
|
}), instance)
|
||
|
|
||
|
t.equal(instance.use('/test', function (req, res, next) {
|
||
|
t.ok('function called')
|
||
|
next()
|
||
|
}), instance)
|
||
|
|
||
|
t.equal(instance.use('/test', function (req, res, next) {
|
||
|
t.equal('/', req.url)
|
||
|
next()
|
||
|
}), instance)
|
||
|
|
||
|
t.equal(instance.use('/no-call', function (req, res, next) {
|
||
|
t.fail('should not call this function')
|
||
|
next()
|
||
|
}), instance)
|
||
|
|
||
|
instance.run(req, res)
|
||
|
})
|
||
|
|
||
|
test('run restricted by path - prefix override', t => {
|
||
|
t.plan(10)
|
||
|
|
||
|
const instance = middie(function (err, a, b) {
|
||
|
t.error(err)
|
||
|
t.equal(a, req)
|
||
|
t.equal('/test/other/one', req.url)
|
||
|
t.equal(b, res)
|
||
|
})
|
||
|
const req = {
|
||
|
url: '/test/other/one'
|
||
|
}
|
||
|
const res = {}
|
||
|
|
||
|
t.equal(instance.use(function (req, res, next) {
|
||
|
t.ok('function called')
|
||
|
next()
|
||
|
}), instance)
|
||
|
|
||
|
t.equal(instance.use('/test', function (req, res, next) {
|
||
|
t.ok('function called')
|
||
|
next()
|
||
|
}), instance)
|
||
|
|
||
|
t.equal(instance.use('/test', function (req, res, next) {
|
||
|
t.equal('/other/one', req.url)
|
||
|
next()
|
||
|
}), instance)
|
||
|
|
||
|
instance.run(req, res)
|
||
|
})
|
||
|
|
||
|
test('run restricted by path - prefix override 2', t => {
|
||
|
t.plan(10)
|
||
|
|
||
|
const instance = middie(function (err, a, b) {
|
||
|
t.error(err)
|
||
|
t.equal(a, req)
|
||
|
t.equal('/tasks-api/task', req.url)
|
||
|
t.equal(b, res)
|
||
|
})
|
||
|
const req = {
|
||
|
url: '/tasks-api/task'
|
||
|
}
|
||
|
const res = {}
|
||
|
|
||
|
t.equal(instance.use(function (req, res, next) {
|
||
|
t.ok('function called')
|
||
|
next()
|
||
|
}), instance)
|
||
|
|
||
|
t.equal(instance.use('/tasks-api', function (req, res, next) {
|
||
|
t.ok('function called')
|
||
|
next()
|
||
|
}), instance)
|
||
|
|
||
|
t.equal(instance.use('/tasks-api', function (req, res, next) {
|
||
|
t.equal('/task', req.url)
|
||
|
next()
|
||
|
}), instance)
|
||
|
|
||
|
instance.run(req, res)
|
||
|
})
|
||
|
|
||
|
test('run restricted by array path', t => {
|
||
|
t.plan(9)
|
||
|
|
||
|
const instance = middie(function (err, a, b) {
|
||
|
t.error(err)
|
||
|
t.equal(a, req)
|
||
|
t.equal('/test', req.url)
|
||
|
t.equal(b, res)
|
||
|
})
|
||
|
const req = {
|
||
|
url: '/test'
|
||
|
}
|
||
|
const res = {}
|
||
|
|
||
|
t.equal(instance.use(function (req, res, next) {
|
||
|
t.ok('function called')
|
||
|
next()
|
||
|
}), instance)
|
||
|
|
||
|
t.equal(instance.use(['/test', '/other-path'], function (req, res, next) {
|
||
|
t.ok('function called')
|
||
|
next()
|
||
|
}), instance)
|
||
|
|
||
|
t.equal(instance.use(['/no-call', 'other-path'], function (req, res, next) {
|
||
|
t.fail('should not call this function')
|
||
|
next()
|
||
|
}), instance)
|
||
|
|
||
|
instance.run(req, res)
|
||
|
})
|
||
|
|
||
|
test('run array of middleware restricted by path', t => {
|
||
|
t.plan(10)
|
||
|
|
||
|
const instance = middie(function (err, a, b) {
|
||
|
t.error(err)
|
||
|
t.equal(a, req)
|
||
|
t.equal('/test', req.url)
|
||
|
t.equal(b, res)
|
||
|
})
|
||
|
const req = {
|
||
|
url: '/test'
|
||
|
}
|
||
|
const res = {}
|
||
|
|
||
|
t.equal(instance.use([function (req, res, next) {
|
||
|
t.ok('function called')
|
||
|
next()
|
||
|
}, function (req, res, next) {
|
||
|
t.ok('function called')
|
||
|
next()
|
||
|
}]), instance)
|
||
|
|
||
|
t.equal(instance.use('/test', [function (req, res, next) {
|
||
|
t.ok('function called')
|
||
|
next()
|
||
|
}, function (req, res, next) {
|
||
|
t.ok('function called')
|
||
|
next()
|
||
|
}]), instance)
|
||
|
|
||
|
instance.run(req, res)
|
||
|
})
|
||
|
|
||
|
test('run array of middleware restricted by array path', t => {
|
||
|
t.plan(10)
|
||
|
|
||
|
const instance = middie(function (err, a, b) {
|
||
|
t.error(err)
|
||
|
t.equal(a, req)
|
||
|
t.equal('/test', req.url)
|
||
|
t.equal(b, res)
|
||
|
})
|
||
|
const req = {
|
||
|
url: '/test'
|
||
|
}
|
||
|
const res = {}
|
||
|
|
||
|
t.equal(instance.use([function (req, res, next) {
|
||
|
t.ok('function called')
|
||
|
next()
|
||
|
}, function (req, res, next) {
|
||
|
t.ok('function called')
|
||
|
next()
|
||
|
}]), instance)
|
||
|
|
||
|
t.equal(instance.use(['/test', '/other-path'], [function (req, res, next) {
|
||
|
t.ok('function called')
|
||
|
next()
|
||
|
}, function (req, res, next) {
|
||
|
t.ok('function called')
|
||
|
next()
|
||
|
}]), instance)
|
||
|
|
||
|
instance.run(req, res)
|
||
|
})
|
||
|
|
||
|
test('Should strip the url to only match the pathname', t => {
|
||
|
t.plan(6)
|
||
|
|
||
|
const instance = middie(function (err, a, b) {
|
||
|
t.error(err)
|
||
|
t.equal(a, req)
|
||
|
t.equal(req.url, '/test#foo?bin=baz')
|
||
|
t.equal(b, res)
|
||
|
})
|
||
|
const req = {
|
||
|
url: '/test#foo?bin=baz'
|
||
|
}
|
||
|
const res = {}
|
||
|
|
||
|
t.equal(instance.use('/test', function (req, res, next) {
|
||
|
t.pass('function called')
|
||
|
next()
|
||
|
}), instance)
|
||
|
|
||
|
instance.run(req, res)
|
||
|
})
|
||
|
|
||
|
test('should keep the context', t => {
|
||
|
t.plan(6)
|
||
|
|
||
|
const instance = middie(function (err, a, b, ctx) {
|
||
|
t.error(err)
|
||
|
t.equal(a, req)
|
||
|
t.equal(b, res)
|
||
|
t.ok(ctx.key)
|
||
|
})
|
||
|
const req = {
|
||
|
url: '/test'
|
||
|
}
|
||
|
const res = {}
|
||
|
|
||
|
t.equal(instance.use(function (req, res, next) {
|
||
|
t.pass('function called')
|
||
|
next()
|
||
|
}), instance)
|
||
|
|
||
|
instance.run(req, res, { key: true })
|
||
|
})
|
||
|
|
||
|
test('should add `originalUrl` property to req', t => {
|
||
|
t.plan(2)
|
||
|
|
||
|
const instance = middie(function (err) {
|
||
|
t.error(err)
|
||
|
})
|
||
|
const req = {
|
||
|
url: '/test'
|
||
|
}
|
||
|
const res = {}
|
||
|
|
||
|
instance.use(function (req, res, next) {
|
||
|
t.equal(req.originalUrl, '/test')
|
||
|
next()
|
||
|
})
|
||
|
|
||
|
instance.run(req, res)
|
||
|
})
|
||
|
|
||
|
test('basic serve static', t => {
|
||
|
const instance = middie(function () {
|
||
|
t.fail('the default route should never be called')
|
||
|
})
|
||
|
instance.use(serveStatic(__dirname))
|
||
|
const server = http.createServer(instance.run.bind(instance))
|
||
|
|
||
|
server.listen(0, function () {
|
||
|
http.get(`http://localhost:${server.address().port}/README.md`, function (res) {
|
||
|
t.is(res.statusCode, 200)
|
||
|
res.resume()
|
||
|
server.close()
|
||
|
server.unref()
|
||
|
t.end()
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('limit serve static to a specific folder', t => {
|
||
|
const instance = middie(function () {
|
||
|
t.fail('the default route should never be called')
|
||
|
req.destroy()
|
||
|
server.close()
|
||
|
server.unref()
|
||
|
})
|
||
|
instance.use('/assets', serveStatic(__dirname))
|
||
|
const server = http.createServer(instance.run.bind(instance))
|
||
|
var req
|
||
|
|
||
|
server.listen(0, function () {
|
||
|
req = http.get(`http://localhost:${server.address().port}/assets/README.md`, function (res) {
|
||
|
t.is(res.statusCode, 200)
|
||
|
res.resume()
|
||
|
server.close()
|
||
|
server.unref()
|
||
|
t.end()
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('should match all chain', t => {
|
||
|
t.plan(2)
|
||
|
const instance = middie(function (err, req, res) {
|
||
|
t.error(err)
|
||
|
t.deepEqual(req, {
|
||
|
url: '/inner/in/depth',
|
||
|
originalUrl: '/inner/in/depth',
|
||
|
undefined: true,
|
||
|
null: true,
|
||
|
empty: true,
|
||
|
root: true,
|
||
|
inner: true,
|
||
|
innerSlashed: true,
|
||
|
innerIn: true,
|
||
|
innerInSlashed: true,
|
||
|
innerInDepth: true,
|
||
|
innerInDepthSlashed: true
|
||
|
})
|
||
|
})
|
||
|
const req = {
|
||
|
url: '/inner/in/depth'
|
||
|
}
|
||
|
const res = {}
|
||
|
|
||
|
const prefixes = [
|
||
|
{ prefix: undefined, name: 'undefined' },
|
||
|
{ prefix: null, name: 'null' },
|
||
|
{ prefix: '', name: 'empty' },
|
||
|
{ prefix: '/', name: 'root' },
|
||
|
{ prefix: '/inner', name: 'inner' },
|
||
|
{ prefix: '/inner/', name: 'innerSlashed' },
|
||
|
{ prefix: '/inner/in', name: 'innerIn' },
|
||
|
{ prefix: '/inner/in/', name: 'innerInSlashed' },
|
||
|
{ prefix: '/inner/in/depth', name: 'innerInDepth' },
|
||
|
{ prefix: '/inner/in/depth/', name: 'innerInDepthSlashed' }
|
||
|
]
|
||
|
prefixes.forEach(function (o) {
|
||
|
instance.use(o.prefix, function (req, res, next) {
|
||
|
if (req[o.name]) throw new Error('Called twice!')
|
||
|
req[o.name] = true
|
||
|
next()
|
||
|
})
|
||
|
})
|
||
|
|
||
|
instance.run(req, res)
|
||
|
})
|
||
|
|
||
|
test('should match the same slashed path', t => {
|
||
|
t.plan(3)
|
||
|
const instance = middie(function (err, req, res) {
|
||
|
t.error(err)
|
||
|
t.deepEqual(req, {
|
||
|
url: '/path',
|
||
|
originalUrl: '/path'
|
||
|
})
|
||
|
})
|
||
|
const req = {
|
||
|
url: '/path'
|
||
|
}
|
||
|
const res = {}
|
||
|
|
||
|
instance.use('/path/', function (req, res, next) {
|
||
|
t.pass('function called')
|
||
|
next()
|
||
|
})
|
||
|
|
||
|
instance.use('/path/inner', function (req, res, next) {
|
||
|
t.fail()
|
||
|
next()
|
||
|
})
|
||
|
|
||
|
instance.run(req, res)
|
||
|
})
|
||
|
|
||
|
test('if the function calls res.end the iterator should stop', t => {
|
||
|
t.plan(1)
|
||
|
|
||
|
const instance = middie(function () {
|
||
|
t.fail('we should not be here')
|
||
|
})
|
||
|
const req = {
|
||
|
url: '/test'
|
||
|
}
|
||
|
const res = {
|
||
|
finished: false,
|
||
|
end: function () {
|
||
|
t.pass('res.end')
|
||
|
this.finished = true
|
||
|
}
|
||
|
}
|
||
|
|
||
|
instance
|
||
|
.use(function (req, res, next) {
|
||
|
res.end('hello')
|
||
|
next()
|
||
|
})
|
||
|
.use(function (req, res, next) {
|
||
|
t.fail('we should not be here')
|
||
|
})
|
||
|
|
||
|
instance.run(req, res)
|
||
|
})
|