Skip to content

Commit 12701c0

Browse files
committed
adding support for transfer encoding (chunked)
1 parent 9c966dc commit 12701c0

File tree

3 files changed

+60
-9
lines changed

3 files changed

+60
-9
lines changed

demos/basic.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ gateway({
3131
const service1 = require('restana')({})
3232
service1
3333
.get('/hi', (req, res) => res.send('Hello World!'))
34+
.get('/hi-chunked', (req, res) => {
35+
res.write('Hello ')
36+
res.write('World!')
37+
res.end()
38+
})
3439
.start(3000).then(() => console.log('Public service listening on 3000 port!'))
3540

3641
const service2 = require('restana')({})

index.js

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,20 +103,40 @@ const handler = (route, proxy, proxyHandler) => async (req, res, next) => {
103103

104104
const onRequestNoOp = (req, res) => { }
105105
const onResponse = async (req, res, stream) => {
106-
if (!res.hasHeader('content-length')) {
106+
const TRANSFER_ENCODING_HEADER_NAME = 'transfer-encoding'
107+
const chunked = stream.headers[TRANSFER_ENCODING_HEADER_NAME]
108+
? stream.headers[TRANSFER_ENCODING_HEADER_NAME].endsWith('chunked')
109+
: false
110+
111+
if (req.headers.connection === 'close' && chunked) {
107112
try {
108-
const resBuffer = Buffer.concat(await toArray(stream))
109-
res.setHeader('content-length', '' + Buffer.byteLength(resBuffer))
110-
res.statusCode = stream.statusCode
111-
res.end(resBuffer)
113+
// remove transfer-encoding header
114+
const transferEncoding = stream.headers[TRANSFER_ENCODING_HEADER_NAME].replace(/(,( )?)?chunked/, '')
115+
if (transferEncoding) {
116+
res.setHeader(TRANSFER_ENCODING_HEADER_NAME, transferEncoding)
117+
} else {
118+
res.removeHeader(TRANSFER_ENCODING_HEADER_NAME)
119+
}
120+
121+
if (!stream.headers['content-length']) {
122+
// pack all pieces into 1 buffer to calculate content length
123+
const resBuffer = Buffer.concat(await toArray(stream))
124+
125+
// add content-length header and send the merged response buffer
126+
res.setHeader('content-length', '' + Buffer.byteLength(resBuffer))
127+
res.statusCode = stream.statusCode
128+
res.end(resBuffer)
129+
130+
return
131+
}
112132
} catch (err) {
113133
res.statusCode = 500
114134
res.end(err.message)
115135
}
116-
} else {
117-
res.statusCode = stream.statusCode
118-
pump(stream, res)
119136
}
137+
138+
res.statusCode = stream.statusCode
139+
pump(stream, res)
120140
}
121141

122142
module.exports = gateway

test/smoke.test.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ describe('API Gateway', () => {
1919
remote.get('/info', (req, res) => res.send({
2020
name: 'fastify-gateway'
2121
}))
22+
remote.get('/chunked', (req, res) => {
23+
res.write('user')
24+
res.write('1')
25+
res.end()
26+
})
2227
remote.get('/cache', (req, res) => {
2328
res.setHeader('x-cache-timeout', '1 second')
2429
res.send({
@@ -279,7 +284,28 @@ describe('API Gateway', () => {
279284
})
280285
})
281286

282-
it('close', async () => {
287+
it('(Connection: close) chunked transfer-encoding support', async () => {
288+
await request(gateway)
289+
.get('/users/chunked')
290+
.set({ Connection: 'close' })
291+
.expect(200)
292+
.then((response) => {
293+
expect(response.text).to.equal('user1')
294+
})
295+
})
296+
297+
it('(Connection: keep-alive) chunked transfer-encoding support', async () => {
298+
await request(gateway)
299+
.get('/users/chunked')
300+
.set('Connection', 'keep-alive')
301+
.then((res) => {
302+
expect(res.text).to.equal('user1')
303+
})
304+
})
305+
306+
it('close', async function () {
307+
this.timeout(10 * 1000)
308+
283309
await remote.close()
284310
await gateway.close()
285311
})

0 commit comments

Comments
 (0)