Skip to content

Commit

Permalink
feat: ignore response if already sent by raw level outgoing API. (#153)
Browse files Browse the repository at this point in the history
  • Loading branch information
usualoma authored Mar 25, 2024
1 parent dd0e0cd commit 3fc502a
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 0 deletions.
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,33 @@ type Http2Bindings = {
}
```
## Direct response from Node.js API
You can directly respond to the client from the Node.js API.
In that case, the response from Hono should be ignored, so return RESPONSE_ALREADY_SENT.
> [!NOTE]
> This feature can be used when migrating existing Node.js applications to Hono, but we recommend using Hono's API for new applications.
```ts
import { serve } from '@hono/node-server'
import type { HttpBindings } from '@hono/node-server'
import { RESPONSE_ALREADY_SENT } from '@hono/node-server/utils/response'
import { Hono } from 'hono'

const app = new Hono<{ Bindings: HttpBindings }>()

app.get('/', (c) => {
const { outgoing } = c.env
outgoing.writeHead(200, { 'Content-Type': 'text/plain' })
outgoing.end('Hello World\n')

return RESPONSE_ALREADY_SENT
})

serve(app)
```

## Related projects

- Hono - <https://hono.dev>
Expand Down
8 changes: 8 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
"types": "./dist/vercel.d.ts",
"require": "./dist/vercel.js",
"import": "./dist/vercel.mjs"
},
"./utils/*": {
"types": "./dist/utils/*.d.ts",
"require": "./dist/utils/*.js",
"import": "./dist/utils/*.mjs"
}
},
"typesVersions": {
Expand All @@ -34,6 +39,9 @@
],
"vercel": [
"./dist/vercel.d.ts"
],
"utils/*": [
"./dist/utils/*.d.ts"
]
}
},
Expand Down
3 changes: 3 additions & 0 deletions src/listener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { getAbortController, newRequest } from './request'
import { cacheKey, getInternalBody } from './response'
import type { CustomErrorHandler, FetchCallback, HttpBindings } from './types'
import { writeFromReadableStream, buildOutgoingHttpHeaders } from './utils'
import { X_ALREADY_SENT } from './utils/response/constants'
import './globals'

const regBuffer = /^no$/i
Expand Down Expand Up @@ -128,6 +129,8 @@ const responseViaResponseObject = async (
outgoing.writeHead(res.status, resHeaderRecord)
outgoing.end(new Uint8Array(buffer))
}
} else if (resHeaderRecord[X_ALREADY_SENT]) {
// do nothing, the response has already been sent
} else {
outgoing.writeHead(res.status, resHeaderRecord)
outgoing.end()
Expand Down
4 changes: 4 additions & 0 deletions src/utils/response.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { X_ALREADY_SENT } from './response/constants'
export const RESPONSE_ALREADY_SENT = new Response(null, {
headers: { [X_ALREADY_SENT]: 'true' },
})
1 change: 1 addition & 0 deletions src/utils/response/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const X_ALREADY_SENT = 'x-hono-already-sent'
23 changes: 23 additions & 0 deletions test/utils/response.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Hono } from 'hono'
import request from 'supertest'
import type { HttpBindings } from '../../src/'
import { createAdaptorServer } from '../../src/server'
import { RESPONSE_ALREADY_SENT } from '../../src/utils/response'

describe('RESPONSE_ALREADY_SENT', () => {
const app = new Hono<{ Bindings: HttpBindings }>()
app.get('/', (c) => {
const { outgoing } = c.env
outgoing.writeHead(200, { 'Content-Type': 'text/plain' })
outgoing.end('Hono!')
return RESPONSE_ALREADY_SENT
})
const server = createAdaptorServer(app)

it('Should return 200 response - GET /', async () => {
const res = await request(server).get('/')
expect(res.status).toBe(200)
expect(res.headers['content-type']).toMatch('text/plain')
expect(res.text).toBe('Hono!')
})
})

0 comments on commit 3fc502a

Please sign in to comment.