in zuul-core/src/main/java/com/netflix/zuul/filters/endpoint/ProxyEndpoint.java [917:998]
protected void handleOriginNonSuccessResponse(HttpResponse originResponse, DiscoveryResult chosenServer) {
int respStatus = originResponse.status().code();
OutboundException obe;
StatusCategory statusCategory;
ClientException.ErrorType niwsErrorType;
if (respStatus == 503) {
statusCategory = ZuulStatusCategory.FAILURE_ORIGIN_THROTTLED;
niwsErrorType = ClientException.ErrorType.SERVER_THROTTLED;
obe = new OutboundException(OutboundErrorType.SERVICE_UNAVAILABLE, requestAttempts);
if (currentRequestStat != null) {
currentRequestStat.updateWithHttpStatusCode(respStatus);
currentRequestStat.serviceUnavailable();
}
} else {
statusCategory = ZuulStatusCategory.FAILURE_ORIGIN;
niwsErrorType = ClientException.ErrorType.GENERAL;
obe = new OutboundException(OutboundErrorType.ERROR_STATUS_RESPONSE, requestAttempts);
if (currentRequestStat != null) {
currentRequestStat.updateWithHttpStatusCode(respStatus);
currentRequestStat.generalError();
}
}
obe.setStatusCode(respStatus);
long duration = 0;
if (currentRequestStat != null) {
duration = currentRequestStat.duration();
}
if (currentRequestAttempt != null) {
currentRequestAttempt.complete(respStatus, duration, obe);
}
// Flag this error with the ExecutionListener.
origin.onRequestExceptionWithServer(zuulRequest, chosenServer, attemptNum, new ClientException(niwsErrorType));
boolean retryable5xxResponse = isRetryable5xxResponse(zuulRequest, originResponse);
if (retryable5xxResponse) {
origin.originRetryPolicyAdjustmentIfNeeded(zuulRequest, originResponse);
origin.adjustRetryPolicyIfNeeded(zuulRequest);
}
if (retryable5xxResponse && isBelowRetryLimit()) {
logger.debug(
"Retrying: status={}, attemptNum={}, maxRetries={}, startedSendingResponseToClient={},"
+ " hasCompleteBody={}, method={}",
respStatus,
attemptNum,
origin.getMaxRetriesForRequest(context),
startedSendingResponseToClient,
zuulRequest.hasCompleteBody(),
zuulRequest.getMethod());
// detach from current origin.
ByteBufUtil.touch(originResponse, "ProxyEndpoint handling non-success retry, request: ", zuulRequest);
unlinkFromOrigin();
releasePartialResponse(originResponse);
// ensure body reader indexes are reset so retry is able to access the body buffer
// otherwise when the body is read by netty (in writeBufferedBodyContent) the body will appear empty
zuulRequest.resetBodyReader();
// retry request with different origin
passport.add(PassportState.ORIGIN_RETRY_START);
proxyRequestToOrigin();
} else {
SessionContext zuulCtx = context;
logger.info(
"Sending error to client: status={}, attemptNum={}, maxRetries={},"
+ " startedSendingResponseToClient={}, hasCompleteBody={}, method={}",
respStatus,
attemptNum,
origin.getMaxRetriesForRequest(zuulCtx),
startedSendingResponseToClient,
zuulRequest.hasCompleteBody(),
zuulRequest.getMethod());
// This is a final response after all retries that will go to the client
ByteBufUtil.touch(originResponse, "ProxyEndpoint handling non-success response, request: ", zuulRequest);
zuulResponse = buildZuulHttpResponse(originResponse, statusCategory, obe);
invokeNext(zuulResponse);
}
}