Search in sources :

Example 36 with SessionContext

use of com.netflix.zuul.context.SessionContext in project zuul by Netflix.

the class ZuulEndPointRunner method getEndpoint.

protected ZuulFilter<HttpRequestMessage, HttpResponseMessage> getEndpoint(final String endpointName, final HttpRequestMessage zuulRequest) {
    final SessionContext zuulCtx = zuulRequest.getContext();
    if (zuulCtx.getStaticResponse() != null) {
        return STATIC_RESPONSE_ENDPOINT;
    }
    if (endpointName == null) {
        return new MissingEndpointHandlingFilter("NO_ENDPOINT_NAME");
    }
    if (PROXY_ENDPOINT_FILTER_NAME.equals(endpointName)) {
        return newProxyEndpoint(zuulRequest);
    }
    final Endpoint<HttpRequestMessage, HttpResponseMessage> filter = getEndpointFilter(endpointName);
    if (filter == null) {
        return new MissingEndpointHandlingFilter(endpointName);
    }
    return filter;
}
Also used : HttpResponseMessage(com.netflix.zuul.message.http.HttpResponseMessage) MissingEndpointHandlingFilter(com.netflix.zuul.filters.endpoint.MissingEndpointHandlingFilter) HttpRequestMessage(com.netflix.zuul.message.http.HttpRequestMessage) SessionContext(com.netflix.zuul.context.SessionContext)

Example 37 with SessionContext

use of com.netflix.zuul.context.SessionContext in project zuul by Netflix.

the class ProxyEndpoint method processErrorFromOrigin.

private void processErrorFromOrigin(final Throwable ex, final Channel origCh) {
    try {
        final SessionContext zuulCtx = context;
        final ErrorType err = requestAttemptFactory.mapNettyToOutboundErrorType(ex);
        // Be cautious about how much we log about errors from origins, as it can have perf implications at high rps.
        if (zuulCtx.isInBrownoutMode()) {
            // Don't include the stacktrace or the channel info.
            LOG.warn(err.getStatusCategory().name() + ", origin = " + origin.getName() + ": " + String.valueOf(ex));
        } else {
            final String origChInfo = (origCh != null) ? ChannelUtils.channelInfoForLogging(origCh) : "";
            if (LOG.isInfoEnabled()) {
                // Include the stacktrace.
                LOG.warn(err.getStatusCategory().name() + ", origin = " + origin.getName() + ", origin channel info = " + origChInfo, ex);
            } else {
                LOG.warn(err.getStatusCategory().name() + ", origin = " + origin.getName() + ", " + String.valueOf(ex) + ", origin channel info = " + origChInfo);
            }
        }
        // Update the NIWS stat.
        if (currentRequestStat != null) {
            currentRequestStat.failAndSetErrorCode(err);
        }
        // Update RequestAttempt info.
        if (currentRequestAttempt != null) {
            currentRequestAttempt.complete(-1, currentRequestStat.duration(), ex);
        }
        postErrorProcessing(ex, zuulCtx, err, chosenServer.get(), attemptNum);
        final ClientException niwsEx = new ClientException(ClientException.ErrorType.valueOf(err.getClientErrorType().name()));
        if (chosenServer.get() != DiscoveryResult.EMPTY) {
            origin.onRequestExceptionWithServer(zuulRequest, chosenServer.get(), attemptNum, niwsEx);
        }
        if ((isBelowRetryLimit()) && (isRetryable(err))) {
            // retry request with different origin
            passport.add(ORIGIN_RETRY_START);
            origin.adjustRetryPolicyIfNeeded(zuulRequest);
            proxyRequestToOrigin();
        } else {
            // Record the exception in context. An error filter should later run which can translate this into an
            // app-specific error response if needed.
            zuulCtx.setError(ex);
            zuulCtx.setShouldSendErrorResponse(true);
            StatusCategoryUtils.storeStatusCategoryIfNotAlreadyFailure(zuulCtx, err.getStatusCategory());
            origin.recordFinalError(zuulRequest, ex);
            origin.onRequestExecutionFailed(zuulRequest, chosenServer.get(), attemptNum - 1, niwsEx);
            // Send error response to client
            handleError(ex);
        }
    } catch (Exception e) {
        // Use original origin returned exception
        handleError(ex);
    }
}
Also used : ErrorType(com.netflix.zuul.exception.ErrorType) OutboundErrorType(com.netflix.zuul.exception.OutboundErrorType) SessionContext(com.netflix.zuul.context.SessionContext) ClientException(com.netflix.client.ClientException) ClientException(com.netflix.client.ClientException) ZuulException(com.netflix.zuul.exception.ZuulException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) OutboundException(com.netflix.zuul.exception.OutboundException)

Example 38 with SessionContext

use of com.netflix.zuul.context.SessionContext in project zuul by Netflix.

the class ProxyEndpoint method handleOriginNonSuccessResponse.

protected void handleOriginNonSuccessResponse(final HttpResponse originResponse, DiscoveryResult chosenServer) {
    final int respStatus = originResponse.status().code();
    OutboundException obe;
    StatusCategory statusCategory;
    ClientException.ErrorType niwsErrorType;
    if (respStatus == 503) {
        // Treat 503 status from Origin similarly to connection failures, ie. we want to back off from this server
        statusCategory = FAILURE_ORIGIN_THROTTLED;
        niwsErrorType = ClientException.ErrorType.SERVER_THROTTLED;
        obe = new OutboundException(OutboundErrorType.SERVICE_UNAVAILABLE, requestAttempts);
        // TODO(carl-mastrangelo): pass in the clock for testing.
        origin.stats().lastThrottleEvent(ZonedDateTime.now());
        if (originConn != null) {
            originConn.getServer().incrementSuccessiveConnectionFailureCount();
            originConn.getServer().addToFailureCount();
            originConn.flagShouldClose();
        }
        if (currentRequestStat != null) {
            currentRequestStat.updateWithHttpStatusCode(respStatus);
            currentRequestStat.serviceUnavailable();
        }
    } else {
        statusCategory = 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));
    if ((isBelowRetryLimit()) && (isRetryable5xxResponse(zuulRequest, originResponse))) {
        LOG.debug("Retrying: status={}, attemptNum={}, maxRetries={}, startedSendingResponseToClient={}, hasCompleteBody={}, method={}", respStatus, attemptNum, origin.getMaxRetriesForRequest(context), startedSendingResponseToClient, zuulRequest.hasCompleteBody(), zuulRequest.getMethod());
        // detach from current origin.
        unlinkFromOrigin();
        // retry request with different origin
        passport.add(ORIGIN_RETRY_START);
        origin.adjustRetryPolicyIfNeeded(zuulRequest);
        proxyRequestToOrigin();
    } else {
        SessionContext zuulCtx = context;
        LOG.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
        zuulResponse = buildZuulHttpResponse(originResponse, statusCategory, obe);
        invokeNext(zuulResponse);
    }
}
Also used : StatusCategory(com.netflix.zuul.stats.status.StatusCategory) ZuulStatusCategory(com.netflix.zuul.stats.status.ZuulStatusCategory) SessionContext(com.netflix.zuul.context.SessionContext) ClientException(com.netflix.client.ClientException) OutboundException(com.netflix.zuul.exception.OutboundException)

Example 39 with SessionContext

use of com.netflix.zuul.context.SessionContext in project zuul by Netflix.

the class ProxyEndpoint method buildZuulHttpResponse.

private HttpResponseMessage buildZuulHttpResponse(final HttpResponse httpResponse, final StatusCategory statusCategory, final Throwable ex) {
    startedSendingResponseToClient = true;
    // Translate the netty HttpResponse into a zuul HttpResponseMessage.
    final SessionContext zuulCtx = context;
    final int respStatus = httpResponse.status().code();
    final HttpResponseMessage zuulResponse = new HttpResponseMessageImpl(zuulCtx, zuulRequest, respStatus);
    final Headers respHeaders = zuulResponse.getHeaders();
    for (Map.Entry<String, String> entry : httpResponse.headers()) {
        respHeaders.add(entry.getKey(), entry.getValue());
    }
    // a LastHttpContent without any prior HttpContent's.
    if (HttpUtils.hasChunkedTransferEncodingHeader(zuulResponse) || HttpUtils.hasNonZeroContentLengthHeader(zuulResponse)) {
        zuulResponse.setHasBody(true);
    }
    // Store this original response info for future reference (ie. for metrics and access logging purposes).
    zuulResponse.storeInboundResponse();
    channelCtx.channel().attr(ATTR_ZUUL_RESP).set(zuulResponse);
    if (httpResponse instanceof DefaultFullHttpResponse) {
        final ByteBuf chunk = ((DefaultFullHttpResponse) httpResponse).content();
        zuulResponse.bufferBodyContents(new DefaultLastHttpContent(chunk));
    }
    // Request was a success even if server may have responded with an error code 5XX, except for 503.
    if (originConn != null) {
        if (statusCategory == ZuulStatusCategory.FAILURE_ORIGIN_THROTTLED) {
            origin.onRequestExecutionFailed(zuulRequest, originConn.getServer(), attemptNum, new ClientException(ClientException.ErrorType.SERVER_THROTTLED));
        } else {
            origin.onRequestExecutionSuccess(zuulRequest, zuulResponse, originConn.getServer(), attemptNum);
        }
    }
    // Collect some info about the received response.
    origin.recordFinalResponse(zuulResponse);
    origin.recordFinalError(zuulRequest, ex);
    zuulCtx.put(CommonContextKeys.STATUS_CATGEORY, statusCategory);
    zuulCtx.setError(ex);
    zuulCtx.put("origin_http_status", Integer.toString(respStatus));
    return transformResponse(zuulResponse);
}
Also used : DefaultFullHttpResponse(io.netty.handler.codec.http.DefaultFullHttpResponse) HttpResponseMessage(com.netflix.zuul.message.http.HttpResponseMessage) DefaultLastHttpContent(io.netty.handler.codec.http.DefaultLastHttpContent) Headers(com.netflix.zuul.message.Headers) HttpResponseMessageImpl(com.netflix.zuul.message.http.HttpResponseMessageImpl) SessionContext(com.netflix.zuul.context.SessionContext) ClientException(com.netflix.client.ClientException) ByteBuf(io.netty.buffer.ByteBuf) Map(java.util.Map) HashMap(java.util.HashMap)

Example 40 with SessionContext

use of com.netflix.zuul.context.SessionContext in project zuul by Netflix.

the class ProxyEndpoint method getOrigin.

/**
 * Get the implementing origin.
 *
 * Note: this method gets called in the constructor so if overloading it or any methods called within, you cannot
 * rely on your own constructor parameters.
 */
@Nullable
protected NettyOrigin getOrigin(HttpRequestMessage request) {
    SessionContext context = request.getContext();
    OriginManager<NettyOrigin> originManager = (OriginManager<NettyOrigin>) context.get(CommonContextKeys.ORIGIN_MANAGER);
    if (Debug.debugRequest(context)) {
        ImmutableList.Builder<String> routingLogEntries = context.get(CommonContextKeys.ROUTING_LOG);
        if (routingLogEntries != null) {
            for (String entry : routingLogEntries.build()) {
                Debug.addRequestDebug(context, "RoutingLog: " + entry);
            }
        }
    }
    String primaryRoute = context.getRouteVIP();
    if (Strings.isNullOrEmpty(primaryRoute)) {
        // If no vip selected, leave origin null, then later the handleNoOriginSelected() method will be invoked.
        return null;
    }
    // make sure the restClientName will never be a raw VIP in cases where it's the fallback for another route assignment
    String restClientVIP = primaryRoute;
    boolean useFullName = context.getBoolean(CommonContextKeys.USE_FULL_VIP_NAME);
    String restClientName = useFullName ? restClientVIP : VipUtils.getVIPPrefix(restClientVIP);
    NettyOrigin origin = null;
    // allow implementors to override the origin with custom injection logic
    OriginName overrideOriginName = injectCustomOriginName(request);
    if (overrideOriginName != null) {
        // Use the custom vip instead if one has been provided.
        origin = getOrCreateOrigin(originManager, overrideOriginName, request.reconstructURI(), context);
    } else if (restClientName != null) {
        // This is the normal flow - that a RoutingFilter has assigned a route
        OriginName originName = OriginName.fromVip(restClientVIP, restClientName);
        origin = getOrCreateOrigin(originManager, originName, request.reconstructURI(), context);
    }
    verifyOrigin(context, request, restClientName, origin);
    // Update the routeVip on context to show the actual raw VIP from the clientConfig of the chosen Origin.
    if (origin != null) {
        context.set(CommonContextKeys.ACTUAL_VIP, origin.getClientConfig().get(IClientConfigKey.Keys.DeploymentContextBasedVipAddresses));
        context.set(CommonContextKeys.ORIGIN_VIP_SECURE, origin.getClientConfig().get(IClientConfigKey.Keys.IsSecure));
    }
    return origin;
}
Also used : OriginName(com.netflix.zuul.origins.OriginName) NettyOrigin(com.netflix.zuul.origins.NettyOrigin) ImmutableList(com.google.common.collect.ImmutableList) SessionContext(com.netflix.zuul.context.SessionContext) OriginManager(com.netflix.zuul.origins.OriginManager) Nullable(javax.annotation.Nullable)

Aggregations

SessionContext (com.netflix.zuul.context.SessionContext)43 Test (org.junit.Test)23 Headers (com.netflix.zuul.message.Headers)16 HttpRequestMessage (com.netflix.zuul.message.http.HttpRequestMessage)6 HttpResponseMessage (com.netflix.zuul.message.http.HttpResponseMessage)5 HttpResponseMessageImpl (com.netflix.zuul.message.http.HttpResponseMessageImpl)5 DefaultLastHttpContent (io.netty.handler.codec.http.DefaultLastHttpContent)5 HttpQueryParams (com.netflix.zuul.message.http.HttpQueryParams)4 InetSocketAddress (java.net.InetSocketAddress)4 ClientException (com.netflix.client.ClientException)3 ZuulException (com.netflix.zuul.exception.ZuulException)3 HttpRequestMessageImpl (com.netflix.zuul.message.http.HttpRequestMessageImpl)3 StatusCategory (com.netflix.zuul.stats.status.StatusCategory)3 ByteBuf (io.netty.buffer.ByteBuf)3 DefaultHttpContent (io.netty.handler.codec.http.DefaultHttpContent)3 ErrorType (com.netflix.zuul.exception.ErrorType)2 OutboundException (com.netflix.zuul.exception.OutboundException)2 ZuulMessage (com.netflix.zuul.message.ZuulMessage)2 ZuulMessageImpl (com.netflix.zuul.message.ZuulMessageImpl)2 CurrentPassport (com.netflix.zuul.passport.CurrentPassport)2