use of io.netty.channel.ConnectTimeoutException in project gravitee-gateway by gravitee-io.
the class HttpEndpointRuleHandler method handle.
@Override
public void handle(Long timer) {
HttpEndpoint endpoint = (HttpEndpoint) rule.endpoint();
logger.debug("Running health-check for endpoint: {} [{}]", endpoint.getName(), endpoint.getTarget());
// Run request for each step
for (io.gravitee.definition.model.services.healthcheck.Step step : rule.steps()) {
try {
URI hcRequestUri = create(endpoint.getTarget(), step.getRequest());
// Prepare HTTP client
HttpClientOptions httpClientOptions = new HttpClientOptions().setMaxPoolSize(1).setKeepAlive(false).setTcpKeepAlive(false);
if (endpoint.getHttpClientOptions() != null) {
httpClientOptions.setIdleTimeout((int) (endpoint.getHttpClientOptions().getIdleTimeout() / 1000)).setConnectTimeout((int) endpoint.getHttpClientOptions().getConnectTimeout()).setTryUseCompression(endpoint.getHttpClientOptions().isUseCompression());
}
// Configure HTTP proxy
HttpProxy proxy = endpoint.getHttpProxy();
if (proxy != null && proxy.isEnabled()) {
ProxyOptions proxyOptions = new ProxyOptions().setHost(proxy.getHost()).setPort(proxy.getPort()).setUsername(proxy.getUsername()).setPassword(proxy.getPassword()).setType(ProxyType.valueOf(proxy.getType().name()));
httpClientOptions.setProxyOptions(proxyOptions);
}
// Configure TLS if required
HttpClientSslOptions sslOptions = endpoint.getHttpClientSslOptions();
if (sslOptions != null && sslOptions.isEnabled()) {
httpClientOptions.setSsl(sslOptions.isEnabled()).setVerifyHost(sslOptions.isHostnameVerifier()).setTrustAll(sslOptions.isTrustAll());
if (sslOptions.getPem() != null && !sslOptions.getPem().isEmpty()) {
httpClientOptions.setPemTrustOptions(new PemTrustOptions().addCertValue(io.vertx.core.buffer.Buffer.buffer(sslOptions.getPem())));
}
} else if (HTTPS_SCHEME.equalsIgnoreCase(hcRequestUri.getScheme())) {
// SSL is not configured but the endpoint scheme is HTTPS so let's enable the SSL on Vert.x HTTP client
// automatically
httpClientOptions.setSsl(true).setTrustAll(true);
}
HttpClient httpClient = vertx.createHttpClient(httpClientOptions);
final int port = hcRequestUri.getPort() != -1 ? hcRequestUri.getPort() : (HTTPS_SCHEME.equals(hcRequestUri.getScheme()) ? 443 : 80);
String relativeUri = (hcRequestUri.getRawQuery() == null) ? hcRequestUri.getRawPath() : hcRequestUri.getRawPath() + '?' + hcRequestUri.getRawQuery();
// Run health-check
HttpClientRequest healthRequest = httpClient.request(HttpMethod.valueOf(step.getRequest().getMethod().name().toUpperCase()), port, hcRequestUri.getHost(), relativeUri);
// Set timeout on request
if (endpoint.getHttpClientOptions() != null) {
healthRequest.setTimeout(endpoint.getHttpClientOptions().getReadTimeout());
}
// Prepare request
if (step.getRequest().getHeaders() != null) {
step.getRequest().getHeaders().forEach(httpHeader -> healthRequest.headers().set(httpHeader.getName(), httpHeader.getValue()));
}
final EndpointStatus.Builder healthBuilder = EndpointStatus.forEndpoint(rule.api(), endpoint.getName()).on(System.currentTimeMillis());
long startTime = System.currentTimeMillis();
Request request = new Request();
request.setMethod(step.getRequest().getMethod());
request.setUri(hcRequestUri.toString());
healthRequest.handler(response -> response.bodyHandler(buffer -> {
long endTime = System.currentTimeMillis();
logger.debug("Health-check endpoint returns a response with a {} status code", response.statusCode());
String body = buffer.toString();
EndpointStatus.StepBuilder stepBuilder = validateAssertions(step, new EvaluableHttpResponse(response, body));
stepBuilder.request(request);
stepBuilder.responseTime(endTime - startTime);
Response healthResponse = new Response();
healthResponse.setStatus(response.statusCode());
// If validation fail, store request and response data
if (!stepBuilder.isSuccess()) {
request.setBody(step.getRequest().getBody());
if (step.getRequest().getHeaders() != null) {
HttpHeaders reqHeaders = new HttpHeaders();
step.getRequest().getHeaders().forEach(httpHeader -> reqHeaders.put(httpHeader.getName(), Collections.singletonList(httpHeader.getValue())));
request.setHeaders(reqHeaders);
}
// Extract headers
HttpHeaders headers = new HttpHeaders();
response.headers().names().forEach(headerName -> headers.put(headerName, response.headers().getAll(headerName)));
healthResponse.setHeaders(headers);
// Store body
healthResponse.setBody(body);
}
stepBuilder.response(healthResponse);
// Append step stepBuilder
healthBuilder.step(stepBuilder.build());
report(healthBuilder.build());
// Close client
httpClient.close();
}));
healthRequest.exceptionHandler(event -> {
long endTime = System.currentTimeMillis();
EndpointStatus.StepBuilder stepBuilder = EndpointStatus.forStep(step.getName());
stepBuilder.fail(event.getMessage());
Response healthResponse = new Response();
// Extract request information
request.setBody(step.getRequest().getBody());
if (step.getRequest().getHeaders() != null) {
HttpHeaders reqHeaders = new HttpHeaders();
step.getRequest().getHeaders().forEach(httpHeader -> reqHeaders.put(httpHeader.getName(), Collections.singletonList(httpHeader.getValue())));
request.setHeaders(reqHeaders);
}
if (event instanceof ConnectTimeoutException) {
stepBuilder.fail(event.getMessage());
healthResponse.setStatus(HttpStatusCode.REQUEST_TIMEOUT_408);
} else {
healthResponse.setStatus(HttpStatusCode.SERVICE_UNAVAILABLE_503);
}
Step result = stepBuilder.build();
result.setResponse(healthResponse);
result.setRequest(request);
result.setResponseTime(endTime - startTime);
// Append step result
healthBuilder.step(result);
report(healthBuilder.build());
try {
// Close client
httpClient.close();
} catch (IllegalStateException ise) {
// Do not take care about exception when closing client
}
});
// Send request
logger.debug("Execute health-check request: {}", healthRequest);
if (step.getRequest().getBody() != null && !step.getRequest().getBody().isEmpty()) {
healthRequest.end(step.getRequest().getBody());
} else {
healthRequest.end();
}
} catch (Exception ex) {
logger.error("An unexpected error occurs", ex);
}
}
}
Aggregations