Home > Mobile >  How to configure client timeouts for http streamed responses?
How to configure client timeouts for http streamed responses?

Time:09-23

I'm trying to perform a request to an http endpoint that streams data for a non-trivial amount of time with Jetty HttpClient. I want to setup a timeout to bound the request time budget. I'm expecting to give up after a precise amount of time in case I'm not receiving any data, but to let the request finish if it started to stream the response.

httpClient.newRequest("http://some-host.local/an/endpoint/that/streams)
            .method(HttpMethod.GET)
            .idleTimeout(100, TimeUnit.MILLISECONDS)
            .timeout(2000, TimeUnit.MILLISECONDS) 
            .send();

I understand that the request goes trough several states: Queued,Begin, [...], Completed. I found these two timeouts:

  • timeout() - Starts on the Queued state; it is disabled on Completed state.
  • idleTimeout() - Starts after the Begin state; it is reset each time content arrives; it is disabled on Completed state

When many requests are Queued but not yet Begin (e.g. all connections are used), the idleTimeout() does not apply to them. A request can only be evicted from the queue by a timeout expiration.

The problem I am facing is that I'm having troubles to set a meaningful timeout that allows me to stop a request that takes too long to start, without also stopping requests that are receiving streamed data.

Is there a way to take into account the time spent awaiting in the queue? I'm trying to bound the time from send() to first byte received.

CodePudding user response:

Sounds like you have a custom requirement.

Create a custom Listener, which implements both a selection of RequestListener and ResponseListener interfaces.

This custom Listener will be responsible for tracking requests that "take too long to start" and when the timer has triggered evaluate if the exchange is valid, or should be cancelled via Request.abort().

Some key events:

  • The Request.BeginListener should start your timing for the request (this means the request was created, but not yet queued).
  • The Request.QueuedListener is when the request hits the queue, but has not yet been sent).
  • The Request.CommitListener is when the request has been sent to the remote server.
  • The Response.BeginListener the first line of the response header has been parsed.
  • The Response.ContentListener the first byte of response content has been received.

For other events, check out the other RequestListener and ResponseListener classes and their javadoc.

RequestListener implementations are registered via

httpClient.getRequestListeners().add(mycustomlistener);

ResponseListener implementations are registered via the Request object.

client.newRequest(uri)
   .onResponseBegin(listener)
   .onResponseContent(listener)
   .onResponseSuccess(listener)
   .onResponseFailure(listener)
   .send(listener); // async send (good place to cancel timer on the exchange)
  • Related