From e9428057e3f10ee0297d57f149bfbc37b45c7ed5 Mon Sep 17 00:00:00 2001 From: Yusuke Wada Date: Fri, 29 Dec 2023 05:39:23 +0900 Subject: [PATCH] fix: handle response that is not an instance of `Response` --- src/listener.ts | 11 +++++++++++ test/server.test.ts | 15 +++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/listener.ts b/src/listener.ts index 513120a..bce6c2e 100644 --- a/src/listener.ts +++ b/src/listener.ts @@ -25,6 +25,10 @@ const handleResponseError = (e: unknown, outgoing: ServerResponse | Http2ServerR console.info('The user aborted a request.') } else { console.error(e) + outgoing.headersSent + ? outgoing.writeHead(500) + : outgoing.writeHead(500, { 'Content-Type': 'text/plain' }) + outgoing.end(`Error: ${err.message}`) outgoing.destroy(err) } } @@ -54,6 +58,13 @@ const responseViaResponseObject = async ( if (res instanceof Promise) { res = await res.catch(handleFetchError) } + if (!(res instanceof Response)) { + return handleResponseError( + // @ts-expect-error the object must have `toString()` + new Error(`The response is not an instance of Response, but ${res.toString()}`), + outgoing + ) + } if (cacheKey in res) { try { return responseViaCache(res as Response, outgoing) diff --git a/test/server.test.ts b/test/server.test.ts index 26dbff0..40b6636 100644 --- a/test/server.test.ts +++ b/test/server.test.ts @@ -24,6 +24,10 @@ describe('Basic', () => { app.delete('/posts/:id', (c) => { return c.text(`DELETE ${c.req.param('id')}`) }) + // @ts-expect-error the response is string + app.get('/invalid', () => { + return '

HTML

' + }) const server = createAdaptorServer(app) @@ -58,6 +62,14 @@ describe('Basic', () => { expect(res.status).toBe(200) expect(res.text).toBe('DELETE 123') }) + + it('Should return 500 response - GET /invalid', async () => { + const res = await request(server).get('/invalid') + expect(res.status).toBe(500) + expect(res.headers['content-type']).toBe('text/plain') + // The error message might be changed. + expect(res.text).toBe('Error: The response is not an instance of Response, but

HTML

') + }) }) describe('Routing', () => { @@ -478,7 +490,6 @@ describe('Hono compression', () => { }) }) - describe('set child response to c.res', () => { const app = new Hono() app.use('*', async (c, next) => { @@ -497,4 +508,4 @@ describe('set child response to c.res', () => { expect(res.status).toBe(200) expect(res.headers['content-type']).toMatch(/application\/json/) }) -}) \ No newline at end of file +})