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
|
this._onreserror = handler
|
||||||
}
|
}
|
||||||
|
|
||||||
onerror(handler) {
|
|
||||||
assertIsHandler(handler, 'onerror()')
|
|
||||||
this._onerror = handler
|
|
||||||
}
|
|
||||||
|
|
||||||
before(handler) {
|
before(handler) {
|
||||||
assertIsHandler(handler, 'before()')
|
assertIsHandler(handler, 'before()')
|
||||||
this._before.push(handler)
|
this._before.push(handler)
|
||||||
|
@ -427,6 +422,18 @@ export class Flaska {
|
||||||
|
|
||||||
requestStartInternal(ctx) {
|
requestStartInternal(ctx) {
|
||||||
let route = this.routers[ctx.method].match(ctx.url)
|
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
|
ctx.params = route.params
|
||||||
|
|
||||||
if (route.middlewares.length) {
|
if (route.middlewares.length) {
|
||||||
|
@ -467,7 +474,11 @@ export class Flaska {
|
||||||
|
|
||||||
requestEnd(err, ctx) {
|
requestEnd(err, ctx) {
|
||||||
if (err) {
|
if (err) {
|
||||||
this._onerror(err, ctx)
|
try {
|
||||||
|
this._onerror(err, ctx)
|
||||||
|
} catch (err) {
|
||||||
|
this._backuperror(err, ctx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ctx.res.writableEnded) {
|
if (ctx.res.writableEnded) {
|
||||||
return
|
return
|
||||||
|
|
13
test.mjs
13
test.mjs
|
@ -4,18 +4,11 @@ const port = 51024
|
||||||
const flaska = new Flaska({}, )
|
const flaska = new Flaska({}, )
|
||||||
|
|
||||||
flaska.get('/', function(ctx) {
|
flaska.get('/', function(ctx) {
|
||||||
return new Promise(function(res, rej) {
|
ctx.body = { status: true }
|
||||||
ctx.body = { status: true }
|
|
||||||
setTimeout(res, 1000)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
flaska.after(function(ctx) {
|
flaska.get('/error', function(ctx) {
|
||||||
if (ctx.aborted) {
|
process.exit(1)
|
||||||
process.stdout.write("A")
|
|
||||||
} else {
|
|
||||||
process.stdout.write(".")
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
flaska.listen(port, function() {
|
flaska.listen(port, function() {
|
||||||
|
|
|
@ -274,6 +274,126 @@ t.describe('#requestStart()', function() {
|
||||||
}), createRes())
|
}), 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) {
|
t.test('should work with synchronous handler', function(cb) {
|
||||||
const assertBody = { a: 1 }
|
const assertBody = { a: 1 }
|
||||||
let handler = function(ctx) {
|
let handler = function(ctx) {
|
||||||
|
|
|
@ -40,6 +40,28 @@ t.describe('#requestEnd()', function() {
|
||||||
flaska.requestEnd(assertError, ctx)
|
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) {
|
t.test('call res and end correctly when dealing with objects', function(cb) {
|
||||||
const assertStatus = 202
|
const assertStatus = 202
|
||||||
// Calculated manually just in case
|
// Calculated manually just in case
|
||||||
|
|
Loading…
Reference in a new issue