-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
InputStream blocks with Jetty HTTP client using an InputStreamResponseListener #2570
Comments
Originally asked on stackoverflow.com at ... |
If you can reproduce, please attach DEBUG logs. |
@mpetzold if you have no other logging frameworks present, you can start your test project with |
One message which could be related. I will try to extract the other messages. 2018-05-24 17:31:34.991 DEBUG org.eclipse.jetty.io.WriteFlusher - ignored: WriteFlusher@3e6b079c{IDLE}->null |
@mpetzold please include the entire DEBUG log. The origin of that specific stacktrace... Also, since you are using SSL, what are your SslContextFactory settings? |
openjdk version "1.8.0_171" |
I currently do not set a SslContextFactory on client side. |
once again, wget is working without any problems |
wget ignores Content-Length and reads to socket EOL, not HTTP protocol EOL. |
Since you have SSL present in your stacktrace, you most definitely have an SslContextFactory present.
Do this, once your HttpClient is started, use Are you using a 3rd party encryption library? (eg: Bouncy Castle) |
server is sending a Content-Length header! |
Ah, sorry: new SslContextFactory(true); |
Even if the Content-Length header is present, it could be wrong value. Quite a common occurrence. Eg:
In this scenario, byte 50 now belongs to the next response in the HTTP protocol.
In this scenario, the protocol isn't finished, the client is still waiting on byte 51. |
On server side I am also using Jetty and setting the Content-Length header of the response to InputStream.available(). My response headers: Date: Wed, 23 May 2018 16:46:06 GMT The Content-Length matches the size the OS (on server side) tells me. |
OS is a recent Linux on client and server side. |
Large(-ish) file you got there. While the underlying cause is important to discover, I should note that an old enhancement request on #929 could prove useful here. Have you verified the server behavior thoroughly?
The response headers you posted don't seem to be the ones that would be produced by Jetty's own ResourceService / DefaultServlet static file serving, so it seems that your server side is doing the file serving using your own code. |
According to filesystem on client side I can also confirm that all bytes are received by the client and size matches Content-Length. |
Exactly. I am using Jetty+Jersey on server side:
|
sha1sum is identical on client and on server side. However, this time I cannot find "org.eclipse.jetty.io.WriteFlusher - ignored" in the log output. But the InputStream is still blocking. |
Do you have that client side DEBUG log yet? (the final minute of logs should be sufficient) |
Please find the log file from client side attached. This is only the last part because it is very long for this large file. I am not 100% sure if this reflects the end, please let me know if you need more. |
There's a lot of unrelated things going on in this log, but the log doesn't contain the thread-id that would help to filter out the unrelated activity and correlate the related events together. |
This is the related request: 2018-05-24 18:15:19.542 DEBUG o.eclipse.jetty.client.HttpReceiver - Request/Response succeeded: Result[HttpRequest[GET /my/path/to/artifact HTTP/1.1]@21989fe2 > HttpResponse[HTTP/1.1 200 OK]@33044a59] null |
I've created a small project to attempt to replicate this report. https://github.com/jetty-project/jetty-jersey-large-file This is jetty + jersey on the server side, using your StreamingOutput facility. Attempted with a 1.7GB file with no issues (so far). Output of server:
Output of client:
Next step is to add SSL to the server side and see if anything changes. |
Added SSL to the example project - jetty-project/jetty-jersey-large-file@3b91354 The results are the same. Server side:
Client side:
@mpetzold can you fork that example project and replicate the issue you are seeing? (This minimal example plus a reproduction would go a long way to solve this issue) |
Could this be related to an open web socket connection to the same server? I am using the same HttpClient instance for both, actually several, connections. |
Also on server side I am using one web server instance to handle HTTP and WebSocket requests. I am using a context handler collection for several endpoints. |
InputStreamResponseListener is blocking at line 318 at lock.wait(). It seems that onSuccess() is not (!) called, however, onComplete() is called and returnes. |
@mpetzold that's normal. The problem isn't that lock, its somewhere else. Can you replicate with the example codebase? Also, websocket on the same server/client will have no impact on this. |
I did not test the example codebase. It is too far away from my complex implementation. I think it could be about the WebSocket connection. However, I still need to disable this and test. |
@joakime what could the problem with the data be? |
One niggle with your codebase. }, MediaType.APPLICATION_OCTET_STREAM).header("Content-Length", inputStream.available()) ... The use of
https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html#available-- Also note that For your example codebase, either use the artifact file size properly, or don't set a Content-Length. |
Ok. Also blocking with WebSocket connection disabled. |
Something else. The link to the InputStreamResponseListener that you just referenced is for the code that processes |
Maybe this is a bug then. I am sending Content-Length header. Checked it with an HTTP client tool. Thanks for the hint about available(). I was aware about this, however, in my case it seems to give the correct size of the artifact. |
Is your Server code sending both a |
If your server code doesn't set a |
Using actual file size (File.length()) instead of InputStream.available(). Size of file in Linux filesystem (ls -l): 613971248 Response headers (according to Chrome Restlet HTTP client):
@joakime So why is it using code that processes Transfer-Encoding: chunked? |
I am also checking for the response code, as suggested in you examples: |
Found the problem. I am overriding onSuccess(). Thus this method is not called in InputStreamResponseListener. I'm very sorry for wasting your time. I could have realized earlier. However, I would recommend a clean API for streaming response. I was working with the class just as with the other response handlers (all clean interfaces). There could be something like:
|
@mpetzold can you clarify what you mean by:
|
I am using an internal API similar to the one suggested in my last comment. I implemented a proxy object extending the InputStreamResponseListener class to handle the events. There I override all methods in order to call each method for my API. I forgot to call super.onSuccess() in order to keep everything in InputStreamResponseListener working. I was somehow thinking it was an interface. This is my API on the user side:
|
Im am using Jetty 9.4.8 HTTP client and want to write a stream of incoming data to a file. Currently I am using an InputStreamResponseListener and IOUtils.copy(..) writing to a FileOutputStream. I have also tried Files.copy().
InputStream is blocked in some cases when I use the InputStreamResponseListener object to handle the InputStream. IMHO this is a bug. I also think that onSuccess() should not be called by Jetty in case InputStream is not fully read or blocking.
The text was updated successfully, but these errors were encountered: