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