use of io.gravitee.gateway.api.handler.Handler in project gravitee-gateway by gravitee-io.
the class ApiReactorHandler method doHandle.
@Override
protected void doHandle(Request serverRequest, Response serverResponse, Handler<Response> handler) {
// Prepare request execution context
ExecutionContext executionContext = executionContextFactory.create(serverRequest);
executionContext.setAttribute(ExecutionContext.ATTR_CONTEXT_PATH, serverRequest.contextPath());
try {
// Set execution context attributes and metrics specific to this handler
serverRequest.metrics().setApi(api.getId());
executionContext.setAttribute(ExecutionContext.ATTR_API, api.getId());
executionContext.setAttribute(ExecutionContext.ATTR_INVOKER, invoker);
// Enable logging at client level
if (api.getProxy().getLoggingMode().isClientMode()) {
serverRequest = new LoggableClientRequest(serverRequest);
serverResponse = new LoggableClientResponse(serverRequest, serverResponse);
}
Cors cors = api.getProxy().getCors();
if (cors != null && cors.isEnabled()) {
Request finalServerRequest = serverRequest;
Response finalServerResponse = serverResponse;
new CorsHandler(cors).responseHandler(new Handler<Response>() {
@Override
public void handle(Response response) {
handleClientRequest(finalServerRequest, finalServerResponse, executionContext, new CorsResponseHandler(handler));
}
}).handle(serverRequest, serverResponse, handler);
} else {
handleClientRequest(serverRequest, serverResponse, executionContext, handler);
}
} catch (Exception ex) {
logger.error("An unexpected error occurs while processing request", ex);
serverRequest.metrics().setMessage(Throwables.getStackTraceAsString(ex));
// Send an INTERNAL_SERVER_ERROR (500)
serverResponse.status(HttpStatusCode.INTERNAL_SERVER_ERROR_500);
serverResponse.headers().set(HttpHeaders.CONNECTION, HttpHeadersValues.CONNECTION_CLOSE);
serverResponse.end();
handler.handle(serverResponse);
}
}
use of io.gravitee.gateway.api.handler.Handler in project gravitee-gateway by gravitee-io.
the class FailoverInvoker method invoke.
@Override
public Request invoke(ExecutionContext executionContext, Request serverRequest, ReadStream<Buffer> stream, Handler<ProxyConnection> connectionHandler) {
final Request failoverServerRequest = new FailoverRequest(serverRequest);
circuitBreaker.execute(new io.vertx.core.Handler<Future<ProxyConnection>>() {
@Override
public void handle(Future<ProxyConnection> event) {
invoker.invoke(executionContext, failoverServerRequest, stream, proxyConnection -> {
proxyConnection.exceptionHandler(event::fail);
proxyConnection.responseHandler(response -> event.complete(new FailoverProxyConnection(proxyConnection, response)));
});
}
}).setHandler(new io.vertx.core.Handler<AsyncResult<ProxyConnection>>() {
@Override
public void handle(AsyncResult<ProxyConnection> event) {
if (event.failed()) {
FailoverConnection connection = new FailoverConnection();
connectionHandler.handle(connection);
connection.sendBadGatewayResponse();
} else {
FailoverProxyConnection proxyConnection = (FailoverProxyConnection) event.result();
connectionHandler.handle(proxyConnection);
proxyConnection.sendResponse();
}
}
});
return failoverServerRequest;
}
use of io.gravitee.gateway.api.handler.Handler in project gravitee-gateway by gravitee-io.
the class DefaultInvoker method invoke.
@Override
public Request invoke(ExecutionContext executionContext, Request serverRequest, ReadStream<Buffer> stream, Handler<ProxyConnection> connectionHandler) {
TargetEndpoint targetEndpoint = selectEndpoint(serverRequest, executionContext);
if (!targetEndpoint.isReachable()) {
DirectProxyConnection statusOnlyConnection = new DirectProxyConnection(HttpStatusCode.SERVICE_UNAVAILABLE_503);
connectionHandler.handle(statusOnlyConnection);
statusOnlyConnection.sendResponse();
} else {
// Remove duplicate slash
String uri = DUPLICATE_SLASH_REMOVER.matcher(targetEndpoint.uri).replaceAll(URI_PATH_SEPARATOR);
URI requestUri = null;
try {
requestUri = encodeQueryParameters(serverRequest, uri);
} catch (Exception ex) {
serverRequest.metrics().setMessage(getStackTraceAsString(ex));
// Request URI is not correct nor correctly encoded, returning a bad request
DirectProxyConnection statusOnlyConnection = new DirectProxyConnection(HttpStatusCode.BAD_REQUEST_400);
connectionHandler.handle(statusOnlyConnection);
statusOnlyConnection.sendResponse();
}
if (requestUri != null) {
uri = requestUri.toString();
// Add the endpoint reference in metrics to know which endpoint has been invoked while serving the request
serverRequest.metrics().setEndpoint(uri);
final HttpMethod httpMethod = extractHttpMethod(executionContext, serverRequest);
ProxyRequest proxyRequest = ProxyRequestBuilder.from(serverRequest).uri(requestUri).method(httpMethod).headers(setProxyHeaders(serverRequest.headers(), requestUri, targetEndpoint.endpoint)).build();
ProxyConnection proxyConnection = targetEndpoint.endpoint.connector().request(proxyRequest);
// Enable logging at proxy level
if (api.getProxy().getLoggingMode().isProxyMode()) {
proxyConnection = new LoggableProxyConnection(proxyConnection, proxyRequest);
}
connectionHandler.handle(proxyConnection);
// Plug underlying stream to connection stream
ProxyConnection finalProxyConnection = proxyConnection;
stream.bodyHandler(buffer -> {
finalProxyConnection.write(buffer);
if (finalProxyConnection.writeQueueFull()) {
serverRequest.pause();
finalProxyConnection.drainHandler(aVoid -> serverRequest.resume());
}
}).endHandler(aVoid -> finalProxyConnection.end());
}
}
// Resume the incoming request to handle content and end
serverRequest.resume();
return serverRequest;
}
use of io.gravitee.gateway.api.handler.Handler in project gravitee-gateway by gravitee-io.
the class ApiReactorHandler method handleClientRequest.
private void handleClientRequest(Request serverRequest, Response serverResponse, ExecutionContext executionContext, Handler<Response> handler) {
serverRequest.pause();
// Apply request policies
RequestPolicyChainProcessor requestPolicyChain = new RequestPolicyChainProcessor(policyResolvers);
requestPolicyChain.setResultHandler(requestPolicyChainResult -> {
if (requestPolicyChainResult.isFailure()) {
sendPolicyFailure(requestPolicyChainResult.getPolicyResult(), serverResponse);
handler.handle(serverResponse);
} else {
// Call an invoker to get a proxy connection (connection to an underlying backend, mainly HTTP)
Invoker upstreamInvoker = (Invoker) executionContext.getAttribute(ExecutionContext.ATTR_INVOKER);
long serviceInvocationStart = System.currentTimeMillis();
AtomicReference<ProxyConnection> proxyConnection = new AtomicReference<>();
Request invokeRequest = upstreamInvoker.invoke(executionContext, serverRequest, requestPolicyChainResult.getPolicyChain(), connection -> {
proxyConnection.set(connection);
connection.responseHandler(proxyResponse -> handleProxyResponse(serverRequest, serverResponse, executionContext, proxyResponse, serviceInvocationStart, handler));
requestPolicyChain.setStreamErrorHandler(result -> {
connection.cancel();
sendPolicyFailure(result.getPolicyResult(), serverResponse);
handler.handle(serverResponse);
});
});
// Plug server request stream to request policy chain stream
invokeRequest.bodyHandler(chunk -> requestPolicyChainResult.getPolicyChain().write(chunk)).endHandler(aVoid -> requestPolicyChainResult.getPolicyChain().end());
}
});
requestPolicyChain.execute(serverRequest, serverResponse, executionContext);
}
Aggregations