uNetworking / uWebSockets

Simple, secure & standards compliant web server for the most demanding of applications
Apache License 2.0
17.29k stars 1.75k forks source link

incoming requests with content-length >= 1000000000 are aborted #1693

Closed porsager closed 9 months ago

porsager commented 1 year ago

Trying to receive a request that has a content-length >= 1000000000 (1gb) instantly closes the connection and calls onAborted.

I've been looking for some limit / max magic number in the source of uWebSockets and uWebSockets.js, but can't find anything anywhere.

Is this configurable somehow, or can this limit be removed?

Here's a sample setup:

import fs from 'fs'
import uws from 'uWebSockets.js'

const app = uws.App()

app.post('/*', (res, req) => {
  console.log('length', req.getHeader('content-length'))
  res.onAborted(() => console.log('aborts instantly'))
  res.onData((data, isLast) => {
    console.log('ondata never fires')
  })
})

app.listen(1234, x => x && console.log('listening'))

Then

mkfile -n 1953125b bigfile.mb // precisely 1000000000
curl -v --data-binary @bigfile.mb http://localhost:1234
porsager commented 1 year ago

Huh.. always end up finding things immediately after creating an issue: https://github.com/uNetworking/uWebSockets/issues/1538

Well, count this as a request to up the limit or make it configurable ;)

uNetworkingAB commented 1 year ago

If you send it as chunked it can have any length.

porsager commented 1 year ago

That's unfortunately non trivial when uploading from browsers. Is there any chance we could sponsor this fix ? :)

uNetworkingAB commented 1 year ago

I started looking at it, it should be simple (mainly changing from unsigned int to uint64_t) but it's cluttered all over, maybe best to begin by replacing all unsigned int to some typedef, then experimentally change that typedef to uint64_t but requires a few changes to masks

uNetworkingAB commented 1 year ago

The limit comes from 32-bit but we use the highest 2 bits for state so it's only 30 bit max length.

porsager commented 1 year ago

Sounds great, I did take a short peek back when creating the issue, but I unfortunately don't have the time to take a stab at it myself.

P.s. off topic, but now that I've got you. I wrote you an email late last year regarding paid work on adding http client support. Don't know if it got caught up in spam, but I'm still interested, so if it's something you'd want to talk about you can catch me on rasmus@porsager.com

uNetworkingAB commented 1 year ago

I probably missed it, ignored it, or some combination of both. Right now I have no time. But we will see what happens in the future.

r3wt commented 1 year ago

That's unfortunately non trivial when uploading from browsers. Is there any chance we could sponsor this fix ? :)

no its not, its incredibly easy. const chunks = Math.ceil(fileSize/chunkSize); then send a payload like {chunk: n, bytes: data}; and reassemble on the server. why is this hard, we've been doing this for years.

uNetworkingAB commented 1 year ago

Ideally it should just work

uNetworkingAB commented 9 months ago

https://github.com/uNetworking/uWebSockets/commit/e0394289b6db96e3f0f5b5a2c4b660a71efea5f6

This commit bumps the limit to 62 bits. Feel free to test with the Crc32 example (POST it something, get the correct crc32)

uNetworkingAB commented 9 months ago

I tested with curl and Crc32 example, seems to work. Will give it a few days to fuzz before I do a release