Add 404 support and some more error handling
This commit is contained in:
parent
1290069287
commit
f1cff5d9ea
4 changed files with 162 additions and 16 deletions
23
flaska.mjs
23
flaska.mjs
|
@ -341,11 +341,6 @@ export class Flaska {
|
|||
this._onreserror = handler
|
||||
}
|
||||
|
||||
onerror(handler) {
|
||||
assertIsHandler(handler, 'onerror()')
|
||||
this._onerror = handler
|
||||
}
|
||||
|
||||
before(handler) {
|
||||
assertIsHandler(handler, 'before()')
|
||||
this._before.push(handler)
|
||||
|
@ -427,6 +422,18 @@ export class Flaska {
|
|||
|
||||
requestStartInternal(ctx) {
|
||||
let route = this.routers[ctx.method].match(ctx.url)
|
||||
if (!route) {
|
||||
let middle = this._on404(ctx)
|
||||
if (middle && middle.then) {
|
||||
return middle.then(() => {
|
||||
this.requestEnd(null, ctx)
|
||||
}, err => {
|
||||
this.requestEnd(err, ctx)
|
||||
})
|
||||
}
|
||||
return this.requestEnd(null, ctx)
|
||||
}
|
||||
|
||||
ctx.params = route.params
|
||||
|
||||
if (route.middlewares.length) {
|
||||
|
@ -467,7 +474,11 @@ export class Flaska {
|
|||
|
||||
requestEnd(err, ctx) {
|
||||
if (err) {
|
||||
this._onerror(err, ctx)
|
||||
try {
|
||||
this._onerror(err, ctx)
|
||||
} catch (err) {
|
||||
this._backuperror(err, ctx)
|
||||
}
|
||||
}
|
||||
if (ctx.res.writableEnded) {
|
||||
return
|
||||
|
|
13
test.mjs
13
test.mjs
|
@ -4,18 +4,11 @@ const port = 51024
|
|||
const flaska = new Flaska({}, )
|
||||
|
||||
flaska.get('/', function(ctx) {
|
||||
return new Promise(function(res, rej) {
|
||||
ctx.body = { status: true }
|
||||
setTimeout(res, 1000)
|
||||
})
|
||||
ctx.body = { status: true }
|
||||
})
|
||||
|
||||
flaska.after(function(ctx) {
|
||||
if (ctx.aborted) {
|
||||
process.stdout.write("A")
|
||||
} else {
|
||||
process.stdout.write(".")
|
||||
}
|
||||
flaska.get('/error', function(ctx) {
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
flaska.listen(port, function() {
|
||||
|
|
|
@ -274,6 +274,126 @@ t.describe('#requestStart()', function() {
|
|||
}), createRes())
|
||||
})
|
||||
|
||||
t.test('calls 404 if route handler is not found', function(cb) {
|
||||
const on404Error = spy()
|
||||
|
||||
let handler = function() {
|
||||
throw new Error('should not be called')
|
||||
}
|
||||
|
||||
let flaska = new Flaska({}, faker)
|
||||
flaska.on404(on404Error)
|
||||
flaska.get('/test', function() { throw new Error('should not be called') })
|
||||
flaska.compile()
|
||||
|
||||
flaska.requestEnd = function(err, ctx) {
|
||||
if (err) return cb(err)
|
||||
|
||||
try {
|
||||
assert.ok(ctx)
|
||||
assert.strictEqual(on404Error.callCount, 1)
|
||||
assert.strictEqual(on404Error.firstCall[0], ctx)
|
||||
cb()
|
||||
} catch (err) { cb(err) }
|
||||
}
|
||||
|
||||
flaska.requestStart(createReq({
|
||||
url: '/nope',
|
||||
method: 'GET',
|
||||
}), createRes())
|
||||
})
|
||||
|
||||
t.test('calls 404 if route handler is not found and supports promise', function(cb) {
|
||||
let checkCtx = null
|
||||
const assertError = new Error('should be seen')
|
||||
const on404Error = function(ctx) {
|
||||
checkCtx = ctx
|
||||
return Promise.resolve().then(function() { return Promise.reject(assertError) })
|
||||
}
|
||||
|
||||
let flaska = new Flaska({}, faker)
|
||||
flaska.on404(on404Error)
|
||||
flaska.get('/test', function() { throw new Error('should not be called') })
|
||||
flaska.compile()
|
||||
|
||||
flaska.requestEnd = function(err, ctx) {
|
||||
if (err && err !== assertError) return cb(err)
|
||||
|
||||
try {
|
||||
assert.ok(err)
|
||||
assert.ok(ctx)
|
||||
assert.strictEqual(ctx, checkCtx)
|
||||
assert.strictEqual(err, assertError)
|
||||
cb()
|
||||
} catch (err) { cb(err) }
|
||||
}
|
||||
|
||||
flaska.requestStart(createReq({
|
||||
url: '/nope',
|
||||
method: 'GET',
|
||||
}), createRes())
|
||||
})
|
||||
|
||||
t.test(`should handle unexpected errors in on404 correctly`, function(cb) {
|
||||
const assertError = new Error('should be seen')
|
||||
let checkCtx = null
|
||||
|
||||
let flaska = new Flaska({}, faker)
|
||||
flaska.on404(function(ctx) {
|
||||
checkCtx = ctx
|
||||
throw assertError
|
||||
})
|
||||
flaska.get('/test', function() { throw new Error('should not be called') })
|
||||
flaska.compile()
|
||||
|
||||
flaska.requestEnd = function(err, ctx) {
|
||||
if (err && err !== assertError) return cb(err)
|
||||
|
||||
try {
|
||||
assert.ok(err)
|
||||
assert.ok(ctx)
|
||||
assert.strictEqual(ctx, checkCtx)
|
||||
assert.strictEqual(err, assertError)
|
||||
cb()
|
||||
} catch (err) { cb(err) }
|
||||
}
|
||||
|
||||
flaska.requestStart(createReq({
|
||||
url: '/nope',
|
||||
method: 'GET',
|
||||
}), createRes())
|
||||
})
|
||||
|
||||
t.test(`should handle unexpected errors in middleware correctly`, function(cb) {
|
||||
const assertError = new Error('should be seen')
|
||||
let checkCtx = null
|
||||
|
||||
let flaska = new Flaska({}, faker)
|
||||
let middles = [function(ctx) {
|
||||
checkCtx = ctx
|
||||
throw assertError
|
||||
}]
|
||||
flaska.get('/test', middles, function() { throw new Error('should not be called') })
|
||||
flaska.compile()
|
||||
|
||||
flaska.requestEnd = function(err, ctx) {
|
||||
if (err && err !== assertError) return cb(err)
|
||||
|
||||
try {
|
||||
assert.ok(err)
|
||||
assert.ok(ctx)
|
||||
assert.strictEqual(ctx, checkCtx)
|
||||
assert.strictEqual(err, assertError)
|
||||
cb()
|
||||
} catch (err) { cb(err) }
|
||||
}
|
||||
|
||||
flaska.requestStart(createReq({
|
||||
url: '/test',
|
||||
method: 'GET',
|
||||
}), createRes())
|
||||
})
|
||||
|
||||
t.test('should work with synchronous handler', function(cb) {
|
||||
const assertBody = { a: 1 }
|
||||
let handler = function(ctx) {
|
||||
|
|
|
@ -39,6 +39,28 @@ t.describe('#requestEnd()', function() {
|
|||
|
||||
flaska.requestEnd(assertError, ctx)
|
||||
})
|
||||
|
||||
t.test('calls backup onerror correctly if error throws', function(cb) {
|
||||
const assertErrorNotSeen = new Error('should not be seen')
|
||||
const assertError = new Error('test')
|
||||
|
||||
let onFinish = function(body) {
|
||||
try {
|
||||
assert.strictEqual(ctx.status, 500)
|
||||
assert.strictEqual(ctx.body.status, 500)
|
||||
assert.strictEqual(ctx.body.message, 'Internal Server Error')
|
||||
cb()
|
||||
} catch (err) { cb(err) }
|
||||
}
|
||||
const ctx = createCtx({}, onFinish)
|
||||
|
||||
let flaska = new Flaska({}, fakerHttp, fakeStream)
|
||||
flaska.onerror(function() {
|
||||
throw assertError
|
||||
})
|
||||
|
||||
flaska.requestEnd(assertErrorNotSeen, ctx)
|
||||
})
|
||||
|
||||
t.test('call res and end correctly when dealing with objects', function(cb) {
|
||||
const assertStatus = 202
|
||||
|
|
Loading…
Reference in a new issue