From 6789dd00159c458163caf05843da6e2a4e0f40c8 Mon Sep 17 00:00:00 2001 From: Deepak kudi Date: Thu, 4 Jun 2026 08:59:18 +0530 Subject: [PATCH 1/2] fix: throw koa http errors from assert --- __tests__/context/assert.test.js | 29 +++++++++++++++++++++++++++++ lib/context.js | 21 ++++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/__tests__/context/assert.test.js b/__tests__/context/assert.test.js index b9dcb2dae..13c8eb4f8 100644 --- a/__tests__/context/assert.test.js +++ b/__tests__/context/assert.test.js @@ -3,6 +3,7 @@ const { describe, it } = require('node:test') const context = require('../../test-helpers/context') const assert = require('node:assert/strict') +const Koa = require('../..') describe('ctx.assert(value, status)', () => { it('should throw an error', () => { @@ -20,4 +21,32 @@ describe('ctx.assert(value, status)', () => { } assert(assertionRan) }) + + it('should throw Koa HttpError instances', () => { + const ctx = context() + + assert.throws(() => { + ctx.assert(false, 404, 'custom message') + }, err => { + assert.strictEqual(err instanceof Koa.HttpError, true) + assert.strictEqual(err.status, 404) + assert.strictEqual(err.message, 'custom message') + assert.strictEqual(err.expose, true) + return true + }) + }) + + it('should throw Koa HttpError instances from assertion helpers', () => { + const ctx = context() + + assert.throws(() => { + ctx.assert.equal('actual', 'expected', 400, 'custom message') + }, err => { + assert.strictEqual(err instanceof Koa.HttpError, true) + assert.strictEqual(err.status, 400) + assert.strictEqual(err.message, 'custom message') + assert.strictEqual(err.expose, true) + return true + }) + }) }) diff --git a/lib/context.js b/lib/context.js index 68ffe3482..0538d614e 100644 --- a/lib/context.js +++ b/lib/context.js @@ -13,6 +13,25 @@ const Cookies = require('cookies') const COOKIES = Symbol('context#cookies') +function rethrowKoaHttpError (fn, args) { + try { + return fn(...args) + } catch (err) { + if (err && typeof err.status === 'number') { + throw createError(err.status, err.message, Object.assign({}, err)) + } + throw err + } +} + +function assert (...args) { + return rethrowKoaHttpError(httpAssert, args) +} + +for (const method of Object.keys(httpAssert)) { + assert[method] = (...args) => rethrowKoaHttpError(httpAssert[method], args) +} + /** * Context prototype. */ @@ -69,7 +88,7 @@ const proto = module.exports = { * @api public */ - assert: httpAssert, + assert, /** * Throw an error with `status` (default 500) and From 48ac662a29687443109acc538ad12c2f9df419e7 Mon Sep 17 00:00:00 2001 From: puneetdixit200 Date: Fri, 5 Jun 2026 09:00:01 +0530 Subject: [PATCH 2/2] fix: preserve assert error stack --- __tests__/context/assert.test.js | 50 ++++++++++++++++++++++++++++++++ lib/context.js | 4 ++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/__tests__/context/assert.test.js b/__tests__/context/assert.test.js index 13c8eb4f8..1acb75837 100644 --- a/__tests__/context/assert.test.js +++ b/__tests__/context/assert.test.js @@ -3,6 +3,7 @@ const { describe, it } = require('node:test') const context = require('../../test-helpers/context') const assert = require('node:assert/strict') +const httpAssert = require('http-assert') const Koa = require('../..') describe('ctx.assert(value, status)', () => { @@ -36,6 +37,20 @@ describe('ctx.assert(value, status)', () => { }) }) + it('should throw Koa HttpError instances with default status', () => { + const ctx = context() + + assert.throws(() => { + ctx.assert(false, 'custom message without status') + }, err => { + assert.strictEqual(err instanceof Koa.HttpError, true) + assert.strictEqual(err.status, 500) + assert.strictEqual(err.message, 'custom message without status') + assert.strictEqual(err.expose, false) + return true + }) + }) + it('should throw Koa HttpError instances from assertion helpers', () => { const ctx = context() @@ -49,4 +64,39 @@ describe('ctx.assert(value, status)', () => { return true }) }) + + it('should throw Koa HttpError instances from assertion helpers without explicit status', () => { + const ctx = context() + + assert.throws(() => { + ctx.assert.ok(false, 'custom helper message without status') + }, err => { + assert.strictEqual(err instanceof Koa.HttpError, true) + assert.strictEqual(err.status, 500) + assert.strictEqual(err.message, 'custom helper message without status') + assert.strictEqual(err.expose, false) + return true + }) + }) + + it('should rethrow non-http assertion helper errors unchanged', () => { + const ctx = context() + const originalFail = httpAssert.fail + const error = new Error('custom helper failure') + + httpAssert.fail = function () { + throw error + } + + try { + assert.throws(() => { + ctx.assert.fail() + }, err => { + assert.strictEqual(err, error) + return true + }) + } finally { + httpAssert.fail = originalFail + } + }) }) diff --git a/lib/context.js b/lib/context.js index 0538d614e..cfc2745e0 100644 --- a/lib/context.js +++ b/lib/context.js @@ -18,7 +18,9 @@ function rethrowKoaHttpError (fn, args) { return fn(...args) } catch (err) { if (err && typeof err.status === 'number') { - throw createError(err.status, err.message, Object.assign({}, err)) + const props = Object.assign({}, err) + props.stack = err.stack + throw createError(err.status, err.message, props) } throw err }