Code:
https://gist.github.com/haxxorsid/348169a3a6c93ee241dfdb8170709651
Run:
git clone https://gist.github.com/haxxorsid/348169a3a6c93ee241dfdb8170709651.git
cd 348169a3a6c93ee241dfdb8170709651
npm install
npm start
In browser: http://localhost:3000/my-scale/resize/100/123?url=image.jpg
It resizes image.jpg(without overwriting the file) to 100width & 123height and displays that in browser.
Error:
AssertionError [ERR_ASSERTION]: headers have already been sent
Can someone solve this issue for me. Maybe this issue is not at all related to koajs.
Yea, that entire request isn't wrapped in a promise. The promise resolves and Koa returns, then you set status.
Make sure your middleware returns a promise which resolves after you set ctx.status.
@fl0w I didn't understood. I am new to this, can you give me a example code or fix my existing code? I am not able to write the correct solution to this. As you said correctly, the problem is arrising between Line 37 & Line 48 that is related toctx.set and ctx.status.
@haxxorsid I wrote an article describing how Koa middleware works, including an example that covers why your code does not work (and @fl0w gave the correct answer) so I hope it will explain it in more detail for you: https://medium.com/netscape/mastering-koa-middleware-f0af6d327a69
@jeffijoe
Did as you and fl0w said:
router.get('/my-scale/resize/:width/:height?', async(ctx, next) => {
const protocol = (options.baseHost.startsWith('https')) ? https : http
let format = 'webp'
const imageUrl = getImageUrl(options.baseHost, ctx.query.url)
const width = parseInt(ctx.params.width, 10)
const height = parseInt(ctx.params.height, 10) || null
const transformer = transform(width, height).on('error', function sharpError(err) {
ctx.status = 500;
next(new Error(err))
})
const etagBuffer = Buffer.from([imageUrl, width, height, format])
ctx.set('ETag', etag(etagBuffer, {weak: true}))
if (ctx.fresh) {
ctx.status = 304;
next();
}
const request = new Promise(resolve => protocol.get(imageUrl, resolve));
const result = await request;
if (result.statusCode >= 400) {
ctx.status = result.statusCode;
next();
}
ctx.status = result.statusCode;
const inputFormat = result.headers['content-type'] || ''
format = format || inputFormat.replace('image/', '')
format = sharp.format.hasOwnProperty(format) ? format : 'jpeg'
ctx.type = 'image/' + format
result.pipe(transformer).pipe(ctx)
});
What is wrong in this? Can you rectify this?
All the places you use next() you need to return next() instead. Please read the article to understand why. 馃槃
@jeffijoe Ok I rectified and updated the gist, but I am receiving a 404 not found. Route is reachable, but still ...any idea?
Condition: result.statusCode >= 400 comes up as true. Any idea why? I have image present in root, still there is some problem in fetching image in function getImageUrl or maybe there is some problem in promise.
@haxxorsid another thing I noticed, https://gist.github.com/haxxorsid/348169a3a6c93ee241dfdb8170709651#file-server-js-L36
You should not pass anything to next(); if you want to throw an error, you should just throw it.
Additionally, I don't think ctx is a Stream, so you might want to pipe to ctx.res instead.
@jeffijoe Ok fixed and updated the gist. I am receiving "OK" on screen. Almost close to complete this...
I expect output to be like this:

But I am getting output like this:
Actually, instead of result.pipe(transformer).pipe(ctx.res), try ctx.body = result.pipe(transformer)
WORKED!!!
