Community
Participate
Working Groups
Build Identifier: 7.2.0.v20101020 If you set a port 80 proxy for the HttpClient and then try to send an HTTPS request, you'll get into a loop where exceptions are continually generated. I'll attach a test program. The output looks like this: ... 2011-10-12 09:34:09.574:WARN::EXCEPTION ConnectExchange@14633156=CONNECT//localhost:80google.com:443#9 HttpException(400,null,null) at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:362) at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:212) at org.eclipse.jetty.client.HttpConnection.handle(HttpConnection.java:262) at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:510) at org.eclipse.jetty.io.nio.SelectChannelEndPoint.access$000(SelectChannelEndPoint.java:34) at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:40) at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:450) at java.lang.Thread.run(Thread.java:662) 2011-10-12 09:34:09.577:WARN::EXCEPTION ConnectExchange@5569009=CONNECT//localhost:80google.com:443#9 HttpException(400,null,null) at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:362) at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:212) at org.eclipse.jetty.client.HttpConnection.handle(HttpConnection.java:262) at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:510) at org.eclipse.jetty.io.nio.SelectChannelEndPoint.access$000(SelectChannelEndPoint.java:34) at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:40) at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:450) at java.lang.Thread.run(Thread.java:662) ... Reproducible: Always Steps to Reproduce: 1. Have a web server running on localhost, port 80 2. Run the attached BadProxyTest program 3. Observe the exception loop
Created attachment 205037 [details] Test program to reproduce the problem.
Created attachment 205109 [details] Unit Test Hi Chris, I've written a pure jetty unit test which is doing what leads to your exception loop. - create a jetty server on a random port acting as the proxy - start a client using that proxy - send an https request (e.g. I tried https://google.com, https://web.de, etc.). Test is always green and the response is as expected. Could you please confirm that you get this problem also when the proxy is running on a high port (e.g. 8080) and with a more recent jetty version? Attached is the unit test. Feel free to modify it to reproduce your issue. Cheers, Thomas
Oh and what kind of proxy are you running on port 80?
For the record: I've had a look at the code from jetty 7.2.0 and the exception is thrown if a non printing char occurs in the parsed string: else if (ch < HttpTokens.SPACE && ch>=0) { throw new HttpException(HttpStatus.BAD_REQUEST_400); } I can't see an obvious reason how this can happen in your case. So it'll be good to get the information I requested above. Cheers, Thomas
(In reply to comment #3) > Oh and what kind of proxy are you running on port 80? Nginx was running on port 80. Using wireshark I can see that the HttpClient sends an HTTP CONNECT request, which I've read nginx doesn't support. Nginx sends back a malformed response; it contains some HTML but no HTTP headers. I'm not concerned that an exception is thrown; the problem is the fact that it loops continuously once this happens. I'll try running the unit test that was attached.
I haven't been able to run the unit test, but I doubt it would show the problem. I'm pretty sure you need a web server that doesn't handle the HTTP CONNECT request. I initially saw the problem using a site mirroring tool called netspiegel (https://github.com/ariya/X2/tree/d6fac7ebe456956854bd17e9405d4e873fd1b4f7/network/netspiegel). This program can act as a web server, and simply drops the connection if it gets an HTTP request whose method isn't GET. Using wireshark I'm able to see the HTTP CONNECT being sent, and then the connection is broken. The exception I see when using netspiegel is: 2011-10-13 08:55:26.751:WARN::EXCEPTION ConnectExchange@6131844=CONNECT//ec2-67-202-16-167.compute-1.amazonaws.com:80google.com:443#9 org.eclipse.jetty.io.EofException at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:319) at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:212) at org.eclipse.jetty.client.HttpConnection.handle(HttpConnection.java:262) at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:510) at org.eclipse.jetty.io.nio.SelectChannelEndPoint.access$000(SelectChannelEndPoint.java:34) at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:40) at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:450) at java.lang.Thread.run(Thread.java:662)
Are you 100% sure that the client is not rerequesting and that jetty loops with a single request being made by the client? Can you attach a snoop file for a single request which I can examine in wireshark?
(In reply to comment #7) > Are you 100% sure that the client is not rerequesting and that jetty loops with > a single request being made by the client? > > Can you attach a snoop file for a single request which I can examine in > wireshark? There are repeated HTTP CONNECT requests made, but only one call to HttpClient.send(). I'm using BadProxyTest.java which only does one send() and has no looping. I'm attaching a traffic dump taken from wireshark.
Created attachment 205200 [details] TCP data recorded using wireshark
Created attachment 206205 [details] Test to reproduce the issue. Given the new information I've been able to reproduce the issue with a Unit test using plain jetty. The client ends up in the loop when the proxy responsible for handling the Connect request will simply close the connection without sending any response (as shown in your wireshark). I will now find and fix the root cause. :)
Created attachment 206236 [details] proposed patch Proposed patch to remove the HttpExchange from HttpClients queue in HttpDestination.ConnectExchange.onException().
Created attachment 206323 [details] proposed patch Better patch attached + Tests.
Created attachment 206394 [details] proposed patch New patch files. Now with support for onExpire and little changes in onResponseComplete as discussed.
Created attachment 206406 [details] proposed patch Additional commit for a new testcase (504 returned by proxy) and enhanced unit tests by reusing the proxy.
Created attachment 206417 [details] proposed patch Merged the 5 commits to a single one as requested.
Patch applied with some additional tweaks.
Fixed.