quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.63k stars 2.64k forks source link

Property quarkus.http.limits.max-form-attribute-size behaviour #42987

Open TigasArreis opened 4 weeks ago

TigasArreis commented 4 weeks ago

Describe the bug

I'm defining a endpoint to receive a file as multipart, receiving as parameter @RestForm("file") FileUpload file

However, when trying to upload a file, the api returns 413 Payload Too Large

So I went to quarkus documentation and found a parameter to increase the max form attribute and set it in application.properties

quarkus.http.limits.max-form-attribute-size=50M

However it still does not allow me to upload bigger files

I can use the parameter quarkus.http.limits.max-body-size however this set the size for the whole body and I only want to set the size for each attribute

Expected behavior

quarkus.http.limits.max-form-attribute-size should work according to the documentation

Actual behavior

the parameter seems to be ignored

Output of java -version

21

Quarkus version or git rev

3.14.1

geoand commented 4 weeks ago

Can you please upload a sample project that shows the problem in action? That way we can drill down and find what's wrong

TigasArreis commented 4 weeks ago

Can you please upload a sample project that shows the problem in action? That way we can drill down and find what's wrong

Hello @geoand , thank you for your response

I've created a sample project in: https://github.com/TigasArreis/code-with-quarkus There is an endpoint POST /files that receives a multipart form with "file" key If you try for example to upload a 50Mb file it will return 413 Payload Too Large even with the parameter quarkus.http.limits.max-form-attribute-size=100M set in application.properties

geoand commented 4 weeks ago

Thanks.

I'm afraid I'll also need the code that posts to the server (or a capture of what the multipart HTTP request looks like) as how things are handled is highly dependent on the request

TigasArreis commented 4 weeks ago

Thanks.

I'm afraid I'll also need the code that posts to the server (or a capture of what the multipart HTTP request looks like) as how things are handled is highly dependent on the request

Hello @geoand

I'm using "Bruno" to make the request. With "Insomnia" I got the same result

image

Timeline output:

> POST http://localhost:8080/files
> content-type: multipart/form-data; boundary=--------------------------025152287589632254984823
> data {"_overheadLength":154,"_valueLength":0,"_valuesToMeasure":[{"fd":null,"path":"C:\\Users\\Tiago\\Desktop\\51mbfile.txt","flags":"r","mode":438,"end":null,"bytesRead":0,"closed":false,"_readableState":{"objectMode":false,"highWaterMark":65536,"buffer":{"head":null,"tail":null,"length":0},"length":0,"pipes":[],"flowing":false,"ended":false,"endEmitted":false,"reading":false,"constructed":false,"sync":true,"needReadable":false,"emittedReadable":false,"readableListening":false,"resumeScheduled":false,"errorEmitted":false,"emitClose":true,"autoDestroy":true,"destroyed":false,"errored":null,"closed":false,"closeEmitted":false,"defaultEncoding":"utf8","awaitDrainWriters":null,"multiAwaitDrain":false,"readingMore":false,"dataEmitted":false,"decoder":null,"encoding":null},"_events":{},"_eventsCount":3}],"writable":false,"readable":true,"dataSize":0,"maxDataSize":2097152,"pauseStreams":true,"_released":false,"_streams":["----------------------------025152287589632254984823\r\nContent-Disposition: form-data; name=\"file\"; filename=\"51mbfile.txt\"\r\nContent-Type: text/plain\r\n\r\n",{"source":{"fd":null,"path":"C:\\Users\\Tiago\\Desktop\\51mbfile.txt","flags":"r","mode":438,"end":null,"bytesRead":0,"closed":false,"_readableState":{"objectMode":false,"highWaterMark":65536,"buffer":{"head":null,"tail":null,"length":0},"length":0,"pipes":[],"flowing":false,"ended":false,"endEmitted":false,"reading":false,"constructed":false,"sync":true,"needReadable":false,"emittedReadable":false,"readableListening":false,"resumeScheduled":false,"errorEmitted":false,"emitClose":true,"autoDestroy":true,"destroyed":false,"errored":null,"closed":false,"closeEmitted":false,"defaultEncoding":"utf8","awaitDrainWriters":null,"multiAwaitDrain":false,"readingMore":false,"dataEmitted":false,"decoder":null,"encoding":null},"_events":{},"_eventsCount":3},"dataSize":0,"maxDataSize":null,"pauseStream":true,"_maxDataSizeExceeded":false,"_released":false,"_bufferedEvents":[{"0":"pause"}],"_events":{},"_eventsCount":1},null],"_currentStream":null,"_insideLoop":false,"_pendingNext":false,"_boundary":"--------------------------025152287589632254984823"}
< 413 Request Entity Too Large
< connection: close
< content-length: 0
geoand commented 4 weeks ago

Is there any way those tools can convert the request to cURL?

TigasArreis commented 3 weeks ago

Is there any way those tools can convert the request to cURL?

Hey @geoand

Had no time to reply, but the CURL command is

curl --request POST \
  --url http://localhost:8080/files \
  --header 'content-type: multipart/form-data' \
  --form 'file=C:\Users\Tiago\Desktop\51mbfile.txt'

I saw that this topic was added to discussion, is this confirmed to be a issue?

geoand commented 3 weeks ago

It seems like we have a few different guards against the size of the body.

For the time being, you need to use quarkus.http.limits.max-body-size as you already found.

Currenly, quarkus.http.limits.max-form-attribute-size only works for non-file multipart parts. What we likely need fort this case however, is to be able to set MultiPartParserDefinition.maxIndividualFileSize, via something like quarkus.http.limits.max-individual-file-size.

WDYT @stuartwdouglas?