Skip to content

Don't disable HttpObjectDecoder on upgrade from HTTP/1.x to HTTP/1.x over TLS#7298

Closed
pkolaczk wants to merge 1 commit intonetty:4.1from
pkolaczk:ISSUE-7293-4.1
Closed

Don't disable HttpObjectDecoder on upgrade from HTTP/1.x to HTTP/1.x over TLS#7298
pkolaczk wants to merge 1 commit intonetty:4.1from
pkolaczk:ISSUE-7293-4.1

Conversation

@pkolaczk
Copy link
Copy Markdown

Motivation:

Being able to upgrade plain HTTP 1.x connection to TLS according to RFC 2817.
Switching the transport layer to TLS should be possible without removing HttpClientCodec from the pipeline, because HTTP/1.x layer of the protocol remains untouched by the switch.

Modification:
Don't set HttpObjectDecoder into UPGRADED state if SWITCHING_PROTOCOLS response contains HTTP/1.0 or HTTP/1.1 in the protocol stack described by the Upgrade header.

Describe the modifications you've done.
Added a new method isSwitchingToNonHttp1Protocol and called it from resetNow.
Additionally I had to skip pairing comparison for HTTP 101, because otherwise it resulted with NPE during decoding. I can see no reason why HTTP 100 and 101 would be handled differently in terms of request-response pairing.

Result:

Fixes #7293.

@normanmaurer
Copy link
Copy Markdown
Member

@pkolaczk can you please add a unit test ?

@pkolaczk
Copy link
Copy Markdown
Author

pkolaczk commented Oct 22, 2017

Yes, sure, I'll do. Is the patch ok besides that?

@normanmaurer
Copy link
Copy Markdown
Member

@pkolaczk yes... please also sign our ICLA:

https://netty.io/s/icla

@pkolaczk
Copy link
Copy Markdown
Author

test added

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert the return value.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert return value

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert return value

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert return value

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you will need to release the FullHttpResponse

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you will need to release the FullHttpResponse

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider using finishAndReleaseAll()

@pkolaczk
Copy link
Copy Markdown
Author

ok, if I use finishAndReleaseAll do I still need these release loops at the end?

HTTP/1.x over TLS

This change allows to upgrade a plain HTTP 1.x connection to TLS
according to RFC 2817. Switching the transport layer to TLS should be
possible without removing HttpClientCodec from the pipeline,
because HTTP/1.x layer of the protocol remains untouched by the switch
and the HttpClientCodec state must be retained for proper
handling the remainder of the response message,
per RFC 2817 requirement in point 3.3:

  Once the TLS handshake completes successfully, the server MUST
  continue with the response to the original request.

After this commit, the upgrade can be established by simply
inserting an SslHandler at the front of the pipeline after receiving
101 SWITCHING PROTOCOLS response, exactly as described in SslHander
documentation.

Modifications:
- Don't set HttpObjectDecoder into UPGRADED state if
  101 SWITCHING_PROTOCOLS response contains HTTP/1.0 or HTTP/1.1 in
  the protocol stack described by the Upgrade header.
- Skip pairing comparison for 101 SWITCHING_PROTOCOLS, similar
  to 100 CONTINUE, since 101 is not the final response to the original
  request and the final response is expected after TLS handshake.

Fixes netty#7293.
@normanmaurer
Copy link
Copy Markdown
Member

normanmaurer commented Oct 26, 2017 via email


assertTrue("Channel inbound write failed.",
ch.writeInbound(Unpooled.copiedBuffer(SWITCHING_PROTOCOLS_RESPONSE, CharsetUtil.ISO_8859_1)));
Object switchingProtocolsResponse = ch.readInbound();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just do:

FullHttpResponse switchingProtocolsResponse = ch.readInbound();

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, but wouldn't it be a bit too implicit and hide the real purpose of the test? This test is basically checking if we do get back a decoded response and not just a plain buffer, like it was before the patch.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly I am not sure why this would be any different then the assertThat that would fail below. Both will fail because the type is not what you expect. So I prefer what I suggested as then you can just remove the assertThas and also the cast later on when releasing

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both would fail, but with different message, and in the second case - this would be the assertion failing and not just some code. An assertion failing is a strong indicator to me that the code breaks something this test was really testing for, and not just an accidental breaking of the test caused by e.g. refactoring. I just want to avoid a situation that in the future this call returns an object of a different type, and someone just fixes the test by changing the type in the test instead of thinking why the test was like that.

But anyway, I can change it if you insist. :)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not super strong on it... if you are more happy with your way then its fine.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok thanks, so I leave it as it is.


assertTrue("Channel inbound write failed",
ch.writeInbound(Unpooled.copiedBuffer(RESPONSE, CharsetUtil.ISO_8859_1)));
Object finalResponse = ch.readInbound();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just do:

FullHttpResponse finalResponse = ch.readInbound();

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If my patch did not work, this would throw CCE, which would not be very obvious and could suggest (to someone not knowing the test purpose) the test was broken, and not the code under test.

Copy link
Copy Markdown
Member

@ejona86 ejona86 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't really dig into the test, but this looks about right to me.

@normanmaurer
Copy link
Copy Markdown
Member

@Scottmitch @carl-mastrangelo want to have a look as well ? If I not hear back from you till monday I will merge.

@normanmaurer normanmaurer self-assigned this Oct 27, 2017
@normanmaurer normanmaurer added this to the 4.1.17.Final milestone Oct 27, 2017
@normanmaurer
Copy link
Copy Markdown
Member

Cherry-picked into 4.1 (7995afe) and 4.0 (efcc6c8).

@pkolaczk thanks a lot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants