protected void handleOriginNonSuccessResponse()

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);
        }
    }