private Publisher<LiveHttpResponse> sendRequest(LiveHttpRequest request, List<RemoteHost> previousOrigins, int attempt) {
if (attempt >= MAX_RETRY_ATTEMPTS) {
return Flux.error(new NoAvailableHostsException(this.id));
}
Optional<RemoteHost> remoteHost = selectOrigin(request);
if (remoteHost.isPresent()) {
RemoteHost host = remoteHost.get();
List<RemoteHost> newPreviousOrigins = newArrayList(previousOrigins);
newPreviousOrigins.add(remoteHost.get());
return ResponseEventListener.from(host.hostClient().handle(request, HttpInterceptorContext.create())
.map(response -> addStickySessionIdentifier(response, host.origin())))
.whenResponseError(cause -> logError(request, cause))
.whenCancelled(() -> originStatsFactory.originStats(host.origin()).requestCancelled())
.apply()
.doOnNext(this::recordErrorStatusMetrics)
.map(response -> removeUnexpectedResponseBody(request, response))
.map(this::removeRedundantContentLengthHeader)
.onErrorResume(cause -> {
RetryPolicyContext retryContext = new RetryPolicyContext(this.id, attempt + 1, cause, request, previousOrigins);
return retry(request, retryContext, newPreviousOrigins, attempt + 1, cause);
})
.map(response -> addOriginId(host.id(), response));
} else {
RetryPolicyContext retryContext = new RetryPolicyContext(this.id, attempt + 1, null, request, previousOrigins);
return retry(request, retryContext, previousOrigins, attempt + 1, new NoAvailableHostsException(this.id));
}
}