Search in sources :

Example 16 with HttpResponse

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);
}
Also used : HttpResponseProvider(io.micronaut.http.HttpResponseProvider) HttpResponse(io.micronaut.http.HttpResponse) Tag(io.micrometer.core.instrument.Tag)

Example 17 with HttpResponse

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");
}
Also used : ServerStartupEvent(io.micronaut.runtime.server.event.ServerStartupEvent) Parameter(io.micronaut.context.annotation.Parameter) Collection(java.util.Collection) DisabledBeanException(io.micronaut.context.exceptions.DisabledBeanException) StaticServiceInstanceList(io.micronaut.discovery.StaticServiceInstanceList) Internal(io.micronaut.core.annotation.Internal) Flux(reactor.core.publisher.Flux) List(java.util.List) EachBean(io.micronaut.context.annotation.EachBean) Factory(io.micronaut.context.annotation.Factory) HttpStatus(io.micronaut.http.HttpStatus) BeanProvider(io.micronaut.context.BeanProvider) Duration(java.time.Duration) Map(java.util.Map) Requires(io.micronaut.context.annotation.Requires) ByteBuffer(io.micronaut.core.io.buffer.ByteBuffer) HttpResponse(io.micronaut.http.HttpResponse) HttpClientResponseException(io.micronaut.http.client.exceptions.HttpClientResponseException) TaskScheduler(io.micronaut.scheduling.TaskScheduler) HttpRequest(io.micronaut.http.HttpRequest) URI(java.net.URI) ApplicationEventListener(io.micronaut.context.event.ApplicationEventListener) Collections(java.util.Collections) ConcurrentLinkedQueue(java.util.concurrent.ConcurrentLinkedQueue) HttpClientResponseException(io.micronaut.http.client.exceptions.HttpClientResponseException) HttpStatus(io.micronaut.http.HttpStatus) Collection(java.util.Collection) StaticServiceInstanceList(io.micronaut.discovery.StaticServiceInstanceList) List(java.util.List) Duration(java.time.Duration) URI(java.net.URI) ByteBuffer(io.micronaut.core.io.buffer.ByteBuffer) Map(java.util.Map) DisabledBeanException(io.micronaut.context.exceptions.DisabledBeanException) Requires(io.micronaut.context.annotation.Requires) EachBean(io.micronaut.context.annotation.EachBean)

Example 18 with HttpResponse

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);
    });
}
Also used : Publishers(io.micronaut.core.async.publisher.Publishers) ServerFilterChain(io.micronaut.http.filter.ServerFilterChain) BeanContext(io.micronaut.context.BeanContext) KotlinExecutableMethodUtils.isKotlinFunctionReturnTypeUnit(io.micronaut.inject.util.KotlinExecutableMethodUtils.isKotlinFunctionReturnTypeUnit) LoggerFactory(org.slf4j.LoggerFactory) HttpHeaders(io.micronaut.http.HttpHeaders) Internal(io.micronaut.core.annotation.Internal) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) HttpStatus(io.micronaut.http.HttpStatus) MediaType(io.micronaut.http.MediaType) ReferenceCounted(io.micronaut.core.io.buffer.ReferenceCounted) HttpResponse(io.micronaut.http.HttpResponse) MethodReference(io.micronaut.inject.MethodReference) MethodBasedRouteMatch(io.micronaut.web.router.MethodBasedRouteMatch) MutableHttpResponse(io.micronaut.http.MutableHttpResponse) Qualifiers(io.micronaut.inject.qualifiers.Qualifiers) Singleton(jakarta.inject.Singleton) MutableHttpHeaders(io.micronaut.http.MutableHttpHeaders) CompletionException(java.util.concurrent.CompletionException) HttpFilter(io.micronaut.http.filter.HttpFilter) RequestArgumentSatisfier(io.micronaut.http.server.binding.RequestArgumentSatisfier) List(java.util.List) RouteInfo(io.micronaut.web.router.RouteInfo) BeanCreationException(io.micronaut.context.exceptions.BeanCreationException) Optional(java.util.Optional) HttpAttributes(io.micronaut.http.HttpAttributes) Pattern(java.util.regex.Pattern) RouteMatch(io.micronaut.web.router.RouteMatch) UnsatisfiedRouteException(io.micronaut.web.router.exceptions.UnsatisfiedRouteException) LocalDateTime(java.time.LocalDateTime) CompletableFuture(java.util.concurrent.CompletableFuture) Scheduler(reactor.core.scheduler.Scheduler) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) Supplier(java.util.function.Supplier) ExceptionHandler(io.micronaut.http.server.exceptions.ExceptionHandler) ExecutableMethod(io.micronaut.inject.ExecutableMethod) ArrayList(java.util.ArrayList) ErrorContext(io.micronaut.http.server.exceptions.response.ErrorContext) Nullable(io.micronaut.core.annotation.Nullable) ReturnType(io.micronaut.core.type.ReturnType) Schedulers(reactor.core.scheduler.Schedulers) Argument(io.micronaut.core.type.Argument) HttpRequest(io.micronaut.http.HttpRequest) ServerRequestContext(io.micronaut.http.context.ServerRequestContext) ErrorResponseProcessor(io.micronaut.http.server.exceptions.response.ErrorResponseProcessor) ExecutorService(java.util.concurrent.ExecutorService) HttpStatusException(io.micronaut.http.exceptions.HttpStatusException) HttpMethod(io.micronaut.http.HttpMethod) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) ExecutorSelector(io.micronaut.scheduling.executor.ExecutorSelector) Publisher(org.reactivestreams.Publisher) Mono(reactor.core.publisher.Mono) IOException(java.io.IOException) BeanType(io.micronaut.inject.BeanType) ExecutionException(java.util.concurrent.ExecutionException) NonNull(io.micronaut.core.annotation.NonNull) Flux(reactor.core.publisher.Flux) ContinuationArgumentBinder(io.micronaut.http.bind.binders.ContinuationArgumentBinder) KotlinUtils.isKotlinCoroutineSuspended(io.micronaut.core.util.KotlinUtils.isKotlinCoroutineSuspended) BeanDefinition(io.micronaut.inject.BeanDefinition) Router(io.micronaut.web.router.Router) Collections(java.util.Collections) MutableHttpResponse(io.micronaut.http.MutableHttpResponse) Optional(java.util.Optional) Argument(io.micronaut.core.type.Argument) HttpStatus(io.micronaut.http.HttpStatus) MethodBasedRouteMatch(io.micronaut.web.router.MethodBasedRouteMatch) Mono(reactor.core.publisher.Mono) Flux(reactor.core.publisher.Flux) HttpResponse(io.micronaut.http.HttpResponse) MutableHttpResponse(io.micronaut.http.MutableHttpResponse) Publisher(org.reactivestreams.Publisher) MethodBasedRouteMatch(io.micronaut.web.router.MethodBasedRouteMatch) RouteMatch(io.micronaut.web.router.RouteMatch) Supplier(java.util.function.Supplier) ReferenceCounted(io.micronaut.core.io.buffer.ReferenceCounted)

Example 19 with HttpResponse

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());
}
Also used : MultipartBody(io.micronaut.http.client.multipart.MultipartBody) HttpResponse(io.micronaut.http.HttpResponse) Test(org.junit.Test)

Example 20 with HttpResponse

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());
}
Also used : MultipartBody(io.micronaut.http.client.multipart.MultipartBody) HttpResponse(io.micronaut.http.HttpResponse) Test(org.junit.Test)

Aggregations

HttpResponse (io.micronaut.http.HttpResponse)36 Test (org.junit.Test)18 MultipartBody (io.micronaut.http.client.multipart.MultipartBody)11 Map (java.util.Map)10 HttpClientResponseException (io.micronaut.http.client.exceptions.HttpClientResponseException)9 Test (org.junit.jupiter.api.Test)9 Nullable (io.micronaut.core.annotation.Nullable)6 HttpClient (io.micronaut.http.client.HttpClient)6 MemberProfile (com.objectcomputing.checkins.services.memberprofile.MemberProfile)5 MediaType (io.micronaut.http.MediaType)5 MutableHttpResponse (io.micronaut.http.MutableHttpResponse)5 EmbeddedServer (io.micronaut.runtime.server.EmbeddedServer)5 List (java.util.List)5 IOException (java.io.IOException)4 Publisher (org.reactivestreams.Publisher)4 Flux (reactor.core.publisher.Flux)4 Internal (io.micronaut.core.annotation.Internal)3 HttpRequest (io.micronaut.http.HttpRequest)3 URI (java.net.URI)3 Publishers (io.micronaut.core.async.publisher.Publishers)2