softwaremill / softwaremill/tapir
Netty server never responds to requests with Expect: 100-continue
Nobody has claimed this yet.
- Dominant language
- Scala
- Stars
- 1.5k
- Forks
- 468
- Avg merge
- 5h 37m
- Merged PRs (30d)
- 34
Description
Problem
A netty server never answers a request that carries Expect: 100-continue. The client gets the interim 100 Continue response, then the connection is closed. It never gets the real response, and no timeout fires either.
How to reproduce
Start any netty server (this uses NettyFutureServer, but the code path is shared by all netty backends) with a PUT endpoint that echoes a string body, then send a raw request:
PUT / HTTP/1.1
Host: localhost:<port>
Content-Type: text/plain
Content-Length: 4
Expect: 100-continue
wait a moment, then send test.
Response received:
HTTP/1.1 100 Continue
connection: close
and then EOF. Expected: 100 Continue, then 200 OK with the echoed body.
Why
NettyServerHandler.channelRead0 has this branch:
} else if (HttpUtil.is100ContinueExpected(request)) {
ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE))
()
}
The route is never run, and the per-request IdleStateHandler (which produces the request timeout) is never installed. On top of that, the write goes through HttpStreamsServerHandler.unbufferedWrite while inFlight == 1 && continueExpected, which sets close = true, so the connection is closed once the 100 Continue is out.
The branch was added in #3337.
Suggested fix
Drop the branch and let the request fall through to runRoute. HttpStreamsServerHandler already handles Expect: 100-continue on its own: it sends the 100 Continue when the body publisher first asks for data, and closes the connection if a response is produced without the body ever being read. That would also give these requests a request timeout, like every other request.
Found while reviewing #5466, which documents the request timeout as starting when the request headers are received — which is not true for these requests.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in NettyServerHandler.channelRead0 and follow the Expect: 100-continue path into HttpStreamsServerHandler.unbufferedWrite. Reproduce the PUT request against NettyFutureServer, then verify that it receives 100 Continue followed by 200 OK with the echoed body and that request timeout handling remains available.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- scala
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 82/100