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
Grizzly provider fails to handle HEAD with Content-Length header #150
Comments
I checked the Grizzly code, and there is logic to deal with HEAD requests and response bodies. I tested locally with AHC and didn't see any issues here. Can you create a test case that I can run or perhaps get a thread dump when the hang occurs? |
Just to be clear: my problem is not with HEAD with response bodies: I don't send response body (since spec forbids that). Rather, it's with no body, and Content-Length > 0, to indicate length one would get for GET. I wish the project I am working on was public (it's at private github). AHC tests were pretty hard to follow last time I tried, but do you know of specific ones I could look at, as a starting point / template? I will go ahead myself and try to see -- challenge is that someone has refactored AHC codebase, so while it will be nicer separation, it is also quite different from last release (1.7.6) Hangup breakpoint might make sense, just need to raise timeout value to higher. Although with async operation it may be bit tricky. |
I understood what you meant. My response probably wasn't clear. I meant to say that it shouldn't expect content in the case of a HEAD request and so it shouldn't hang waiting for content. You might look at api/src/test/java/com/ning/http/client/async/AsyncProvidersTest.asyncStatusHEADTest() as a template. |
Ok gotcha. Just wanted to verify -- I often read bug reports too cursorily myself. :) Thanks for the pointer & apologies for lack of test cases so far. |
Looking at code I have, there is one other possible explanation: work-around for (old?) Netty prob with handling of chunk boundaries may be interfering. Hope to refactor code, then go back to trying out Grizzly provider. Btw, what would be the latest stable grizzly version to use? AHC seems to use use "grizzly-websockets", 2.2.16. |
The latest is 2.2.19. AHC should work fine with it. |
Ok. Tried upgrading to 2.2.19 (for some reason, websockets one is needed). Added explicit deps to grizzly-framework, grizzly-http, to reduce likelihood of transitive deps being to some old version. |
The Grizzly WS library is needed for WS support within AHC. Grizzly WS is always released at the same time as the http and core frameworks, so the versions should always match. Not sure if you need a breakpoint yet. If you extend the timeout, you could connect to the process using visualvm and obtain a thread dump. |
This probably won't help a lot, but actual call is done using this part of API:
and failure is via TimeoutException; timeout set at 15000 msecs (or whatever); timeout exception seems to be missing stack trace info during debugging. |
Oh Crivens! I can now make test pass by adding two things:
so I suspect this may be a race condition of some kind. And those have been found from AHC codebase from time to time. :-( For whatever it's worth, request is handled by a JAX-RS end point. |
Oh. One realization on timeouts; this may be explained by fact that the FIRST HEAD call fails, but retry succeeds -- but this only happens when whole-operation timeout limit is not reached. With 15secs it is. |
I spent some more time ensuring that server implementation does not do something stupid, and as far as I can see it does not. I am also looking at AHC tests; one of HEAD tests is disabled, but it seems broken and not related to issue I am seeing. At this point I think that the problem has to be related to reuse of the underlying HTTP connection; in my test I do a sequence of:
The fact that if retries are enabled and second try for HEAD works (with a "fresh" connection, I assume, since timeout probably forces closing of the first connection) suggests that this is somehow related to state handling. I will next try to modify a test to do something like above. |
Managed to write a unit test, similar Head302Test. After failing first, I managed to get it work; initial failure was not related (for HEAD, handler must still access the output stream). Test does GET, HEAD sequence with grizzly provider. One additional difference is that test uses Async listener approach, whereas production code uses blocking executeRequest variant. I will next try changing my HEAD handler to use bare async handler. Maybe I can at least work around the issue, even if I can not figure out what exactly is going on. |
Change to pure async handler thing did not solve the problem, but it does give bit more visibility into state changes.
but then I see two Throwables: first being java.io.IOException("Remotely Closed"), and second java.io.EOFException. |
Here goes: java.io.IOException: Remotely Closed and java.io.EOFException so these are 2 exceptions caught during processing of problematic HEAD request. |
Last comment of the day: timeout occurs for some reason 2 seconds after specified time (if I give 1500 msec, onThrowable gets called bit over 3500 msec after executing request). This on localhost, without real network access. Also: in my test PUT plays a role; if it is commented out, failure does not occur. May try to add it in AHC test sequence tomorrow. |
OK, great - will dig in further on my side. Thanks! |
Could you please capture a wire trace of the http traffic for your failing case? |
This is from unit tests on localhost. Wonder what would be the easiest way to capture it? (sorry it has been a while since I used tcpdump). I can easily run the test on Eclipse, or probably from command line. |
I'm a big fan of wireshark. Another good tool is ngrep. |
Ok, I think I got stuff captured, exported as XML. But github issue tracker has no attachment capabilities. https://jira.codehaus.org/browse/JACKSON-435 (see the attachment) |
Data in question is just 12000 bytes of 0xAC (i.e. data is correct). But same happens with smaller payloads (120 bytes whatever). |
One thing I started thinking is that perhaps I am not reading response that PUT is returning; and that could mess up handling. |
Closing this issue out as I'm unable to reproduce. Please feel free to re-open when you have time to revisit and have a test case we can run. |
I am trying to use Grizzly provider (v1.7.6), and noticed a timeout for simple HEAD request.
Since this is local test, with 15 second timeout, it looks like this is due to blocking.
Same does not happen with Netty provider.
My best guess to underlying problem is that Grizzly provider expects there to be content to read since Content-Length is returned. This would be incorrect assumption, since HTTP specification explicitly states that HEAD requests may contain length indicator, but there is never payload entity to return.
Looking at Netty provider code, I can see explicit handling for this use case, where connection is closed and any content flushes (in case server did send something).
I did not see similar handling in Grizzly provider, but since implementation code structure is very different it may reside somewhere else.
The text was updated successfully, but these errors were encountered: