Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Response not sent when client sends "Expect: 100-continue" request header #293

Closed
bclozel opened this issue Feb 22, 2018 · 0 comments
Closed
Labels
type/bug A general bug
Milestone

Comments

@bclozel
Copy link
Member

bclozel commented Feb 22, 2018

Consider the following sample server:

// this server reads the request body then replies with "test"
NettyContext context = HttpServer
	.create(8080)
	.newHandler((req, res) -> {
		return req.receiveContent()
			.then(res.sendString(Mono.just("test")).then());
	})
	.block();

When an HTTP client sends the following request, things work as expected:

curl --data "Test" http://localhost:8080/demo --header "Content-Type: text/plain" --header "Expect:" -vvv
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> POST /demo HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Type: text/plain
> Content-Length: 4
>
* upload completely sent off: 4 out of 4 bytes
< HTTP/1.1 200 OK
< transfer-encoding: chunked
<
* Connection #0 to host localhost left intact
test%

Some HTTP clients, when sending a large request body, can send "Expect: 100-continue" request headers (see this article for more on that).

Expected behavior

With the following command:

curl --data "Test" http://localhost:8080/demo --header "Content-Type: text/plain" --header "Expect: 100-continue"

I expect the server:

  1. to answer HTTP/1.1 100 Continue
  2. to read the request body
  3. reply with HTTP/1.1 200 Continue and the "test" response body

Actual behavior

Instead, the HTTP client get no reply once it's sent the request body - it's hanged:

curl --data "Test" http://localhost:8080/demo --header "Content-Type: text/plain" --header "Expect: 100-continue" -vvv
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> POST /demo HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Type: text/plain
> Expect: 100-continue
> Content-Length: 4
>
< HTTP/1.1 100 Continue
* We are completely uploaded and fine

On the server side, we can read the following:

         +-------------------------------------------------+
         |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 50 4f 53 54 20 2f 64 65 6d 6f 20 48 54 54 50 2f |POST /demo HTTP/|
|00000010| 31 2e 31 0d 0a 48 6f 73 74 3a 20 6c 6f 63 61 6c |1.1..Host: local|
|00000020| 68 6f 73 74 3a 38 30 38 30 0d 0a 55 73 65 72 2d |host:8080..User-|
|00000030| 41 67 65 6e 74 3a 20 63 75 72 6c 2f 37 2e 35 34 |Agent: curl/7.54|
|00000040| 2e 30 0d 0a 41 63 63 65 70 74 3a 20 2a 2f 2a 0d |.0..Accept: */*.|
|00000050| 0a 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 74 |.Content-Type: t|
|00000060| 65 78 74 2f 70 6c 61 69 6e 0d 0a 45 78 70 65 63 |ext/plain..Expec|
|00000070| 74 3a 20 31 30 30 2d 63 6f 6e 74 69 6e 75 65 0d |t: 100-continue.|
|00000080| 0a 43 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 3a |.Content-Length:|
|00000090| 20 34 0d 0a 0d 0a                               | 4....          |
+--------+-------------------------------------------------+----------------+
20:44:58.347 [reactor-http-nio-4] DEBUG r.i.n.h.server.HttpServerOperations - Increasing pending responses, now 1
20:44:58.347 [reactor-http-nio-4] DEBUG r.ipc.netty.http.server.HttpServer - [id: 0xe1bb4076, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:53272] READ COMPLETE
20:44:58.347 [reactor-http-nio-4] DEBUG r.i.netty.channel.ChannelOperations - [HttpServer] [id: 0xe1bb4076, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:53272] handler is being applied: reactor.ipc.netty.http.server.DummyTest$$Lambda$7/1182461167@2c155cf3
20:44:58.347 [reactor-http-nio-4] DEBUG r.i.n.c.ChannelOperationsHandler - [id: 0xe1bb4076, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:53272] Writing object DefaultFullHttpResponse(decodeResult: success, version: HTTP/1.1, content: EmptyByteBufBE)
HTTP/1.1 100 Continue
20:44:58.348 [reactor-http-nio-4] DEBUG r.ipc.netty.http.server.HttpServer - [id: 0xe1bb4076, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:53272] WRITE: 25B
         +-------------------------------------------------+
         |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 48 54 54 50 2f 31 2e 31 20 31 30 30 20 43 6f 6e |HTTP/1.1 100 Con|
|00000010| 74 69 6e 75 65 0d 0a 0d 0a                      |tinue....       |
+--------+-------------------------------------------------+----------------+
20:44:58.348 [reactor-http-nio-4] DEBUG r.ipc.netty.http.server.HttpServer - [id: 0xe1bb4076, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:53272] USER_EVENT: [Handler Terminated]
20:44:58.348 [reactor-http-nio-4] DEBUG r.i.n.c.ChannelOperationsHandler - [id: 0xe1bb4076, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:53272] Disposing context reactor.ipc.netty.channel.ServerContextHandler@3ac7f46c
20:44:58.348 [reactor-http-nio-4] DEBUG r.ipc.netty.http.server.HttpServer - [id: 0xe1bb4076, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:53272] FLUSH
20:44:58.348 [reactor-http-nio-4] DEBUG r.ipc.netty.http.server.HttpServer - [id: 0xe1bb4076, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:53272] READ: 4B
         +-------------------------------------------------+
         |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 54 65 73 74                                     |Test            |
+--------+-------------------------------------------------+----------------+
20:44:58.349 [reactor-http-nio-4] DEBUG r.i.n.c.ChannelOperationsHandler - [id: 0xe1bb4076, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:53272] No ChannelOperation attached. Dropping: Test
20:44:58.349 [reactor-http-nio-4] DEBUG r.ipc.netty.http.server.HttpServer - [id: 0xe1bb4076, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:53272] READ COMPLETE

Steps to reproduce

These curl commands are quite artificial, but you can reproduce this behavior naturally with curl, when sending large files like:

curl --data @bigint.txt http://localhost:8080/demo --header "Content-Type: text/plain"

Reactor Netty version

master branch, 0.7.5.BUILD-SNAPSHOT

JVM version (e.g. java -version)

java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode)

OS version (e.g. uname -a)

17.4.0 Darwin Kernel Version 17.4.0: Sun Dec 17 09:19:54 PST 2017; root:xnu-4570.41.2~1/RELEASE_X86_64 x86_64
@bclozel bclozel added the type/bug A general bug label Feb 22, 2018
@violetagg violetagg added this to the 0.7.5.RELEASE milestone Feb 23, 2018
smaldini pushed a commit that referenced this issue Feb 26, 2018
HttpServerHandler now write informational response separately.
In order to fully work the fix correctly defers header sending on subscribe.
This can give precedence to the expect100Continue logic in receiveObject()
smaldini pushed a commit that referenced this issue Feb 27, 2018
HttpServerHandler now write informational response separately.
In order to fully work the fix correctly defers header sending on subscribe.
This can give precedence to the expect100Continue logic in receiveObject()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type/bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants