I have a route like this:
api.put('/my/path', mdw0, body({fields:'body'}),mdw1, mdw2, controller);
The first middleware mdw0 reads some headers before the body is parsed and might decide to send an error if the size is > allowed_size or to call await next()
The problem is that the connection remains active till the end of the upload, so I don't have any advantage in using this strategy, the actual response with 413 arrives to the browser immediately if I kill the node process otherwise it remains in pending till the end.
So, how can i manually end the connection after i set ctx.status and ctx.body?
ctx.res.end()
Thanks, It was one of my first attempt.
I have something like this
ctx.status=413;
ctx.body=jcompose(ctx.status);
ctx.res.end();
Unfortunately, the upload keeps going till the end, even if morgan prints the log out.
I even tried to throw an error:
ctx.throw ('payload too big',413)
The upload keeps going till the end.
This seems to be app specific problem, or perhaps (what looks like) koa-router. I can't reproduce this at all. Throw works as intended (and I'm pretty sure there's tests coverage for this as well).
'use strict'
const Koa = require('koa')
const app = new Koa()
app.use((ctx, next) => {
ctx.state.mwCalled = []
return next()
.catch((err) => { ctx.body = ctx.state.mwCalled })
})
app.use((ctx, next) => {
ctx.state.mwCalled.push('first')
return next()
})
app.use((ctx, next) => {
ctx.state.mwCalled.push('second')
ctx.throw('payload to big', 413)
return next()
})
app.use((ctx, next) => {
ctx.state.mwCalled.push('third')
})
app.listen()
I tried your code, I made just few changes in the middleware 2 that now looks like:
app.use((ctx, next) => {
ctx.state.mwCalled.push('second')
let contentLen = parseInt(ctx.request.header['content-length']);
if (contentLen > 10971520) {
console.log("Content-lenth too big, I throw an exception");
ctx.throw('payload to big', 413)
}
else
return next()
})
When I upload a file with size less then 10971520, I get ["first", "second", "third"]
If I upload a bigger file, I see in the console "Content-lenth too big, I throw an exception" but in the browser the network status is "pending" till the end of the upload.
When the whole file has been uploaded, I finally receive the output.
As expected, it is just [ "first", "second"]
So, it actually blocks the flow, but it does not stop the upload.
I believe this is an issue with node itself, not with koa. I remember doing the same thing before v1, but http changed some time
Can you send a response code like 204 or 500? or ctx.res.close()
this will require investigating http itself. if anyone wants to make a non-koa test case, that would be great!
So I'm trying my luck on this one by POSTing a large file to a native node server, e.g:
'use strict'
const http = require('http')
// edit noticed now that this was the last iteration, tried multiple "variations" :)
function handleRequest (req, res) {
if (parseInt(req.headers['content-length']) > 1375347) {
res.end('to large')
}
res.end('done in full')
}
const server = http.createServer(handleRequest)
server.listen(8000)
It seems to me that even though res.end() is called, the socket isn't actually destroyed and there still an 100 continuation handshake. res.end() just sets closed state and writes what's passed (i.e. user cannot write now).
If socket is manually res.destroy()'ed (via ctx.res.destroy() in Koa context), I think OP would get the expected result (i.e. connection dropped, don't care about the full file being sent or not - though I'm not sure about the implications of actually doing this).
I'm still new to the inner workings of http and haven't even begun debugging socket, so I might be off here.
Most helpful comment
So I'm trying my luck on this one by POSTing a large file to a native node server, e.g:
It seems to me that even though
res.end()is called, the socket isn't actually destroyed and there still an 100 continuation handshake.res.end()just sets closed state and writes what's passed (i.e. user cannot write now).If socket is manually
res.destroy()'ed (viactx.res.destroy()in Koa context), I think OP would get the expected result (i.e. connection dropped, don't care about the full file being sent or not - though I'm not sure about the implications of actually doing this).I'm still new to the inner workings of http and haven't even begun debugging socket, so I might be off here.