use of io.micronaut.http.HttpResponse in project micronaut-micrometer by micronaut-projects.
the class WebMetricsPublisher method error.
/**
* Method to register the error timer for a web request when an exception occurs.
*
* @param start the start time of the request
* @param httpMethod the name of the http method (GET, POST, etc)
* @param requestPath the uri of the reuqest
* @param throwable exception that occurred
*/
private void error(long start, String httpMethod, String requestPath, Throwable throwable, String host) {
HttpResponse response = null;
if (throwable instanceof HttpResponseProvider) {
response = ((HttpResponseProvider) throwable).getResponse();
}
Iterable<Tag> tags = getTags(response, httpMethod, requestPath, throwable, host);
this.meterRegistry.timer(metricName, tags).record(System.nanoTime() - start, TimeUnit.NANOSECONDS);
}
use of io.micronaut.http.HttpResponse in project micronaut-core by micronaut-projects.
the class ServiceHttpClientFactory method healthCheckStarter.
/**
* Creates a {@link ApplicationEventListener} that listens to {@link ServerStartupEvent} for each configured HTTP client
* in order to register a health check if necessary.
*
* @param configuration The configuration
* @param instanceList The instance list
* @return The event listener
*/
@EachBean(ServiceHttpClientConfiguration.class)
@Requires(condition = ServiceHttpClientCondition.class)
ApplicationEventListener<ServerStartupEvent> healthCheckStarter(@Parameter ServiceHttpClientConfiguration configuration, @Parameter StaticServiceInstanceList instanceList) {
if (configuration.isHealthCheck()) {
return event -> {
final List<URI> originalURLs = configuration.getUrls();
Collection<URI> loadBalancedURIs = instanceList.getLoadBalancedURIs();
final HttpClient httpClient = clientFactory.get().getClient(configuration.getHttpVersion(), configuration.getServiceId(), configuration.getPath().orElse(null));
final Duration initialDelay = configuration.getHealthCheckInterval();
Duration delay = configuration.getHealthCheckInterval();
taskScheduler.scheduleWithFixedDelay(initialDelay, delay, () -> Flux.fromIterable(originalURLs).flatMap(originalURI -> {
URI healthCheckURI = originalURI.resolve(configuration.getHealthCheckUri());
return Flux.from(httpClient.exchange(HttpRequest.GET(healthCheckURI))).onErrorResume(throwable -> {
if (throwable instanceof HttpClientResponseException) {
HttpClientResponseException responseException = (HttpClientResponseException) throwable;
return Flux.just((HttpResponse<ByteBuffer>) responseException.getResponse());
}
return Flux.just(HttpResponse.serverError());
}).map(response -> Collections.singletonMap(originalURI, response.getStatus()));
}).subscribe(uriToStatusMap -> {
Map.Entry<URI, HttpStatus> entry = uriToStatusMap.entrySet().iterator().next();
URI uri = entry.getKey();
HttpStatus status = entry.getValue();
if (status.getCode() >= 300) {
loadBalancedURIs.remove(uri);
} else if (!loadBalancedURIs.contains(uri)) {
loadBalancedURIs.add(uri);
}
}));
};
}
throw new DisabledBeanException("HTTP Client Health Check not enabled");
}
use of io.micronaut.http.HttpResponse in project micronaut-core by micronaut-projects.
the class RouteExecutor method createResponseForBody.
private Flux<MutableHttpResponse<?>> createResponseForBody(HttpRequest<?> request, Object body, RouteInfo<?> routeInfo) {
return Flux.<MutableHttpResponse<?>>defer(() -> {
Mono<MutableHttpResponse<?>> outgoingResponse;
if (body == null) {
if (routeInfo.isVoid()) {
MutableHttpResponse<Object> data = forStatus(routeInfo);
if (HttpMethod.permitsRequestBody(request.getMethod())) {
data.header(HttpHeaders.CONTENT_LENGTH, "0");
}
outgoingResponse = Mono.just(data);
} else {
outgoingResponse = Mono.just(newNotFoundError(request));
}
} else {
HttpStatus defaultHttpStatus = routeInfo.isErrorRoute() ? HttpStatus.INTERNAL_SERVER_ERROR : HttpStatus.OK;
boolean isReactive = routeInfo.isAsyncOrReactive() || Publishers.isConvertibleToPublisher(body);
if (isReactive) {
Class<?> bodyClass = body.getClass();
boolean isSingle = isSingle(routeInfo, bodyClass);
boolean isCompletable = !isSingle && routeInfo.isVoid() && Publishers.isCompletable(bodyClass);
if (isSingle || isCompletable) {
// full response case
Publisher<Object> publisher = Publishers.convertPublisher(body, Publisher.class);
Supplier<MutableHttpResponse<?>> emptyResponse = () -> {
MutableHttpResponse<?> singleResponse;
if (isCompletable || routeInfo.isVoid()) {
singleResponse = forStatus(routeInfo, HttpStatus.OK).header(HttpHeaders.CONTENT_LENGTH, "0");
} else {
singleResponse = newNotFoundError(request);
}
return singleResponse;
};
return Flux.from(publisher).flatMap(o -> {
MutableHttpResponse<?> singleResponse;
if (o instanceof Optional) {
Optional optional = (Optional) o;
if (optional.isPresent()) {
o = ((Optional<?>) o).get();
} else {
return Flux.just(emptyResponse.get());
}
}
if (o instanceof HttpResponse) {
singleResponse = toMutableResponse((HttpResponse<?>) o);
final Argument<?> bodyArgument = // Mono
routeInfo.getReturnType().getFirstTypeVariable().orElse(// HttpResponse
Argument.OBJECT_ARGUMENT).getFirstTypeVariable().orElse(// Mono
Argument.OBJECT_ARGUMENT);
if (bodyArgument.isAsyncOrReactive()) {
return processPublisherBody(request, singleResponse, routeInfo);
}
} else if (o instanceof HttpStatus) {
singleResponse = forStatus(routeInfo, (HttpStatus) o);
} else {
singleResponse = forStatus(routeInfo, defaultHttpStatus).body(o);
}
return Flux.just(singleResponse);
}).switchIfEmpty(Mono.fromSupplier(emptyResponse));
} else {
// streaming case
Argument<?> typeArgument = routeInfo.getReturnType().getFirstTypeVariable().orElse(Argument.OBJECT_ARGUMENT);
if (HttpResponse.class.isAssignableFrom(typeArgument.getType())) {
// a response stream
Publisher<HttpResponse<?>> bodyPublisher = Publishers.convertPublisher(body, Publisher.class);
Flux<MutableHttpResponse<?>> response = Flux.from(bodyPublisher).map(this::toMutableResponse);
Argument<?> bodyArgument = typeArgument.getFirstTypeVariable().orElse(Argument.OBJECT_ARGUMENT);
if (bodyArgument.isAsyncOrReactive()) {
return response.flatMap((resp) -> processPublisherBody(request, resp, routeInfo));
}
return response;
} else {
MutableHttpResponse<?> response = forStatus(routeInfo, defaultHttpStatus).body(body);
return processPublisherBody(request, response, routeInfo);
}
}
}
// now we have the raw result, transform it as necessary
if (body instanceof HttpStatus) {
outgoingResponse = Mono.just(HttpResponse.status((HttpStatus) body));
} else {
if (routeInfo.isSuspended()) {
boolean isKotlinFunctionReturnTypeUnit = routeInfo instanceof MethodBasedRouteMatch && isKotlinFunctionReturnTypeUnit(((MethodBasedRouteMatch) routeInfo).getExecutableMethod());
final Supplier<CompletableFuture<?>> supplier = ContinuationArgumentBinder.extractContinuationCompletableFutureSupplier(request);
if (isKotlinCoroutineSuspended(body)) {
return Mono.fromCompletionStage(supplier).<MutableHttpResponse<?>>flatMap(obj -> {
MutableHttpResponse<?> response;
if (obj instanceof HttpResponse) {
response = toMutableResponse((HttpResponse<?>) obj);
final Argument<?> bodyArgument = routeInfo.getReturnType().getFirstTypeVariable().orElse(Argument.OBJECT_ARGUMENT);
if (bodyArgument.isAsyncOrReactive()) {
return processPublisherBody(request, response, routeInfo);
}
} else {
response = forStatus(routeInfo, defaultHttpStatus);
if (!isKotlinFunctionReturnTypeUnit) {
response = response.body(obj);
}
}
return Mono.just(response);
}).switchIfEmpty(createNotFoundErrorResponsePublisher(request));
} else {
Object suspendedBody;
if (isKotlinFunctionReturnTypeUnit) {
suspendedBody = Mono.empty();
} else {
suspendedBody = body;
}
outgoingResponse = toMutableResponse(request, routeInfo, defaultHttpStatus, suspendedBody);
}
} else {
outgoingResponse = toMutableResponse(request, routeInfo, defaultHttpStatus, body);
}
}
}
// for head request we never emit the body
if (request != null && request.getMethod().equals(HttpMethod.HEAD)) {
outgoingResponse = outgoingResponse.map(r -> {
final Object o = r.getBody().orElse(null);
if (o instanceof ReferenceCounted) {
((ReferenceCounted) o).release();
}
r.body(null);
return r;
});
}
return outgoingResponse;
}).doOnNext((response) -> {
applyConfiguredHeaders(response.getHeaders());
if (routeInfo instanceof RouteMatch) {
response.setAttribute(HttpAttributes.ROUTE_MATCH, routeInfo);
}
response.setAttribute(HttpAttributes.ROUTE_INFO, routeInfo);
});
}
use of io.micronaut.http.HttpResponse in project micronaut-core by micronaut-projects.
the class UploadControllerSpec method testFileBytesUpload.
@Test
public void testFileBytesUpload() {
MultipartBody body = MultipartBody.builder().addPart("file", "file.json", MediaType.TEXT_PLAIN_TYPE, "some data".getBytes()).addPart("fileName", "bar").build();
Flux<HttpResponse<String>> flowable = Flux.from(client.exchange(HttpRequest.POST("/upload/bytes", body).contentType(MediaType.MULTIPART_FORM_DATA).accept(MediaType.TEXT_PLAIN_TYPE), String.class));
HttpResponse<String> response = flowable.blockFirst();
assertEquals(HttpStatus.OK.getCode(), response.code());
assertEquals("Uploaded", response.getBody().get());
}
use of io.micronaut.http.HttpResponse in project micronaut-core by micronaut-projects.
the class UploadControllerSpec method testFileUploadOutputStream.
@Test
public void testFileUploadOutputStream() {
MultipartBody body = MultipartBody.builder().addPart("file", "file.json", MediaType.APPLICATION_JSON_TYPE, "{\"title\":\"Foo\"}".getBytes()).build();
Flux<HttpResponse<String>> flowable = Flux.from(client.exchange(HttpRequest.POST("/upload/outputStream", body).contentType(MediaType.MULTIPART_FORM_DATA).accept(MediaType.TEXT_PLAIN_TYPE), String.class));
HttpResponse<String> response = flowable.blockFirst();
assertEquals(HttpStatus.OK.getCode(), response.code());
assertEquals("Uploaded", response.getBody().get());
}
Aggregations