Incoming HTTP request not being fully read or closed when a constraint validator rejects the request
See original GitHub issueDescribe the bug
Machine: Apple M1 Pro JVM: openjdk 11.0.2 Quarkus: 2.7.4.Final, 2.13.3.Final
There seems to be a race condition between reading a request from a TCP socket and constraint validators.
When a request gets rejected by a constraint validator (such as @Consume
) before Quarkus had a chance to fully ACK the incoming request, Quarkus answers back with the appropriate status code and stops reading the request from the TCP socket but doesn’t close the connection.
This behavior, keeping the connection open but not reading data from the socket, leaves clients in a hanging state after they fully filled the TCP transmission window, waiting for it to be ACK’ed.
The client hang may not be observed if the requests are smaller in size, given that in those cases it’s likely that the request has been completely received and ACK’ed by Quarkus before the constraint validator had the chance to fire. In these cases, no hanging is observed.
Expected behavior
Quarkus should either read the incoming request fully or close the connection, so as to signal to the client that the request transmission should be over.
Actual behavior
Described in the previous section. Follow the steps below to reproduce.
How to Reproduce?
- Create a sample Quarkus application using
quarkus create && cd code-with-quarkus
- Add the following endpoint:
@Path("/hello")
public class GreetingResource {
@POST
@Consumes({"image/jpeg", "image/png"})
@Produces(MediaType.TEXT_PLAIN)
public String hello(byte[] imageFile) {
throw new NotAuthorizedException("");
}
}
- Make a request with a large payload (3MB is enough on my machine, Apple M1 Pro) which breaks the
@Consumes
filter by sending a differentContent-Type
header. For your convenience, here’s a python snippet that’ll do it:
import requests
import os
url = "http://localhost:8080/hello"
payload=b"\x00"+os.urandom(1024 * 1024 * 3)+b"\x00"
headers = {
'Content-Type': 'image/gif'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
At this point, the Python code should hang because the request stream is neither being fully read nor closed by Quarkus.
Output of uname -a
or ver
(macOS M1 Pro) Darwin <REDACTED>.local 21.6.0 Darwin Kernel Version 21.6.0: Mon Aug 22 20:19:52 PDT 2022; root:xnu-8020.140.49~2/RELEASE_ARM64_T6000 arm64
Output of java -version
openjdk version “11.0.2” 2019-01-15 OpenJDK Runtime Environment 18.9 (build 11.0.2+9) OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)
GraalVM version (if different from Java)
No response
Quarkus version or git rev
Reproduced in 2.7.4.Final and 2.13.3.Final
Build tool (ie. output of mvnw --version
or gradlew --version
)
Apache Maven 3.8.6 Maven home: /Users/<REDACTED>/.m2/wrapper/dists/apache-maven-3.8.6-bin/67568434/apache-maven-3.8.6 Java version: 11.0.2, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home Default locale: en_PT, platform encoding: UTF-8 OS name: “mac os x”, version: “10.16”, arch: “x86_64”, family: “mac”
Additional information
No response
Issue Analytics
- State:
- Created a year ago
- Reactions:5
- Comments:19 (10 by maintainers)
I could reproduce this issue and this is a tentative fix for it: https://github.com/quarkusio/quarkus/pull/29119
@geoand Here’s a quick project that’ll help you repro it in 5 minutes. The README has a 3 step guide on what you should do to trigger the issue.
https://github.com/davidreis97/QuarkusRepro28818