public HttpResponseImpl response() throws IOException, InterruptedException { HttpRequestImpl r = request; if (r.timeval() != 0) { // set timer td = new TimedEvent(r.timeval()); client.registerTimer(td); } while (attempts < max_attempts) { try { attempts++; Exchange currExchange = getExchange(); requestFilters(r); HttpResponseImpl response = currExchange.response(); Pair<HttpResponse, HttpRequestImpl> filterResult = responseFilters(response); HttpRequestImpl newreq = filterResult.second; if (newreq == null) { if (attempts > 1) { Log.logError("Succeeded on attempt: " + attempts); } cancelTimer(); return response; } response.body(HttpResponse.ignoreBody()); setExchange(new Exchange(newreq, currExchange.getAccessControlContext())); r = newreq; } catch (IOException e) { if (cancelled) { throw new HttpTimeoutException("Request timed out"); } throw e; } } cancelTimer(); throw new IOException("Retry limit exceeded"); }
public CompletableFuture<HttpResponseImpl> responseAsync(Void v) { CompletableFuture<HttpResponseImpl> cf; if (++attempts > max_attempts) { cf = CompletableFuture.failedFuture(new IOException("Too many retries")); } else { if (currentreq.timeval() != 0) { // set timer td = new TimedEvent(currentreq.timeval()); client.registerTimer(td); } Exchange exch = getExchange(); cf = requestFiltersAsync(currentreq) .thenCompose(exch::responseAsync) .thenCompose(this::responseFiltersAsync) .thenCompose( (Pair<HttpResponse, HttpRequestImpl> pair) -> { HttpResponseImpl resp = (HttpResponseImpl) pair.first; if (resp != null) { if (attempts > 1) { Log.logError("Succeeded on attempt: " + attempts); } return CompletableFuture.completedFuture(resp); } else { currentreq = pair.second; Exchange previous = exch; setExchange(new Exchange(currentreq, currentreq.getAccessControlContext())); // reads body off previous, and then waits for next response return previous .responseBodyAsync(HttpResponse.ignoreBody()) .thenCompose(this::responseAsync); } }) .handle( (BiFunction<HttpResponse, Throwable, Pair<HttpResponse, Throwable>>) Pair::new) .thenCompose( (Pair<HttpResponse, Throwable> obj) -> { HttpResponseImpl response = (HttpResponseImpl) obj.first; if (response != null) { return CompletableFuture.completedFuture(response); } // all exceptions thrown are handled here CompletableFuture<HttpResponseImpl> error = getExceptionalCF(obj.second); if (error == null) { cancelTimer(); return responseAsync(null); } else { return error; } }); } return cf; }