Skip to content

Commit

Permalink
Fix serving Images through external rewrite with Image component (ver…
Browse files Browse the repository at this point in the history
…cel#21001)

This PR fixes the issue described here: vercel#20909

The _req passed to getRequestHandler doesn't have `on` function which is required by http-proxy. It throws the error e.on is not a function. We should also wait for buffer to finish writing before sending the response. 

Fixes: vercel#20909
Closes: vercel#24177
  • Loading branch information
umarsenpai authored and SokratisVidros committed Apr 20, 2021
1 parent 854c58a commit 0f33bef
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 6 deletions.
26 changes: 20 additions & 6 deletions packages/next/next-server/server/image-optimizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,14 +194,15 @@ export async function imageOptimizer(
maxAge = getMaxAge(upstreamRes.headers.get('Cache-Control'))
} else {
try {
const _req: any = {
headers: req.headers,
method: req.method,
url: href,
}
const resBuffers: Buffer[] = []
const mockRes: any = new Stream.Writable()

const isStreamFinished = new Promise(function (resolve, reject) {
mockRes.on('finish', () => resolve(true))
mockRes.on('end', () => resolve(true))
mockRes.on('error', () => reject())
})

mockRes.write = (chunk: Buffer | string) => {
resBuffers.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))
}
Expand All @@ -222,11 +223,24 @@ export async function imageOptimizer(
mockRes.finished = false
mockRes.statusCode = 200

const mockReq: any = new Stream.Readable()

mockReq._read = () => {
mockReq.emit('end')
mockReq.emit('close')
return Buffer.from('')
}

mockReq.headers = req.headers
mockReq.method = req.method
mockReq.url = href

await server.getRequestHandler()(
_req,
mockReq,
mockRes,
nodeUrl.parse(href, true)
)
await isStreamFinished
res.statusCode = mockRes.statusCode

upstreamBuffer = Buffer.concat(resBuffers)
Expand Down
33 changes: 33 additions & 0 deletions test/integration/image-optimizer/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -796,4 +796,37 @@ describe('Image Optimizer', () => {
expect(res.status).toBe(404)
})
})

describe('External rewrite support with for serving static content in images', () => {
beforeAll(async () => {
const newConfig = `{
async rewrites() {
return [
{
source: '/:base(next-js)/:rest*',
destination: 'https://assets.vercel.com/image/upload/v1538361091/repositories/:base/:rest*',
},
]
},
}`
nextConfig.replace('{ /* replaceme */ }', newConfig)
appPort = await findPort()
app = await launchApp(appDir, appPort)
})

afterAll(async () => {
await killApp(app)
nextConfig.restore()
await fs.remove(imagesDir)
})

it('should return response when image is served from an external rewrite', async () => {
const query = { url: '/next-js/next-js-bg.png', w: 64, q: 75 }
const opts = { headers: { accept: 'image/webp' } }
const res = await fetchViaHTTP(appPort, '/_next/image', query, opts)
expect(res.status).toBe(200)
expect(res.headers.get('Content-Type')).toBe('image/webp')
await expectWidth(res, 64)
})
})
})

0 comments on commit 0f33bef

Please sign in to comment.