Skip to content

Commit

Permalink
refactor(helper/proxy): return the original content-length if the res…
Browse files Browse the repository at this point in the history
…ponse is uncompressed
  • Loading branch information
usualoma committed Oct 30, 2024
1 parent 5998770 commit 3a5ef0f
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 25 deletions.
74 changes: 57 additions & 17 deletions src/helper/proxy/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,34 @@ import { proxyFetch } from '.'
describe('Proxy Middleware', () => {
describe('proxyFetch', () => {
beforeEach(() => {
global.fetch = vi.fn().mockResolvedValue(
new Response('ok', {
headers: {
'Content-Encoding': 'gzip',
'Content-Length': '100',
'Content-Range': 'bytes 0-2/1024',
'X-Response-Id': '456',
},
})
)
global.fetch = vi.fn().mockImplementation((req) => {
if (req.url === 'https://example.com/compressed') {
return Promise.resolve(
new Response('ok', {
headers: {
'Content-Encoding': 'gzip',
'Content-Length': '1',
'Content-Range': 'bytes 0-2/1024',
'X-Response-Id': '456',
},
})
)
} else if (req.url === 'https://example.com/uncompressed') {
return Promise.resolve(
new Response('ok', {
headers: {
'Content-Length': '2',
'Content-Range': 'bytes 0-2/1024',
'X-Response-Id': '456',
},
})
)
}
return Promise.resolve(new Response('not found', { status: 404 }))
})
})

it('simple proxy', async () => {
it('compressed', async () => {
const app = new Hono()
app.get('/proxy/:path', (c) =>
proxyFetch(
Expand All @@ -28,10 +43,10 @@ describe('Proxy Middleware', () => {
})
)
)
const res = await app.request('/proxy/test')
const res = await app.request('/proxy/compressed')
const req = (global.fetch as ReturnType<typeof vi.fn>).mock.calls[0][0]

expect(req.url).toBe('https://example.com/test')
expect(req.url).toBe('https://example.com/compressed')
expect(req.headers.get('X-Request-Id')).toBe('123')
expect(req.headers.get('Accept-Encoding')).toBeNull()

Expand All @@ -42,6 +57,31 @@ describe('Proxy Middleware', () => {
expect(res.headers.get('Content-Range')).toBe('bytes 0-2/1024')
})

it('uncompressed', async () => {
const app = new Hono()
app.get('/proxy/:path', (c) =>
proxyFetch(
new Request(`https://example.com/${c.req.param('path')}`, {
headers: {
'X-Request-Id': '123',
'Accept-Encoding': 'gzip',
},
})
)
)
const res = await app.request('/proxy/uncompressed')
const req = (global.fetch as ReturnType<typeof vi.fn>).mock.calls[0][0]

expect(req.url).toBe('https://example.com/uncompressed')
expect(req.headers.get('X-Request-Id')).toBe('123')
expect(req.headers.get('Accept-Encoding')).toBeNull()

expect(res.status).toBe(200)
expect(res.headers.get('X-Response-Id')).toBe('456')
expect(res.headers.get('Content-Length')).toBe('2')
expect(res.headers.get('Content-Range')).toBe('bytes 0-2/1024')
})

it('proxySetRequestHeaders option', async () => {
const app = new Hono()
app.get('/proxy/:path', (c) =>
Expand All @@ -63,10 +103,10 @@ describe('Proxy Middleware', () => {
}
)
)
const res = await app.request('/proxy/test')
const res = await app.request('/proxy/compressed')
const req = (global.fetch as ReturnType<typeof vi.fn>).mock.calls[0][0]

expect(req.url).toBe('https://example.com/test')
expect(req.url).toBe('https://example.com/compressed')
expect(req.headers.get('X-Request-Id')).toBe('abc')
expect(req.headers.get('X-Forwarded-For')).toBe('127.0.0.1')
expect(req.headers.get('X-Forwarded-Host')).toBe('example.com')
Expand Down Expand Up @@ -95,10 +135,10 @@ describe('Proxy Middleware', () => {
}
)
)
const res = await app.request('/proxy/test')
const res = await app.request('/proxy/compressed')
const req = (global.fetch as ReturnType<typeof vi.fn>).mock.calls[0][0]

expect(req.url).toBe('https://example.com/test')
expect(req.url).toBe('https://example.com/compressed')
expect(req.headers.get('X-Request-Id')).toBe('123')
expect(req.headers.get('Accept-Encoding')).toBeNull()

Expand Down
14 changes: 6 additions & 8 deletions src/helper/proxy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,6 @@
* Proxy Helper for Hono.
*/

/*
* The following headers will be deleted from the response:
* * Content-Encoding
* * Content-Length
*/
const forceDeleteResponseHeaderNames = ['Content-Encoding', 'Content-Length']

// Typical header names for requests for proxy use
type ProxyRequestHeaderName = 'X-Forwarded-For' | 'X-Forwarded-Proto' | 'X-Forwarded-Host'

Expand Down Expand Up @@ -73,7 +66,12 @@ export const proxyFetch: ProxyFetch = async (input, proxyInit) => {

const res = await fetch(req)
const resHeaders = new Headers(res.headers)
for (const key of forceDeleteResponseHeaderNames.concat(proxyDeleteResponseHeaderNames)) {
if (resHeaders.has('content-encoding')) {
resHeaders.delete('content-encoding')
// Content-Length is the size of the compressed content, not the size of the original content
resHeaders.delete('content-length')
}
for (const key of proxyDeleteResponseHeaderNames) {
resHeaders.delete(key)
}

Expand Down

0 comments on commit 3a5ef0f

Please sign in to comment.