Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2017-2024 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.http.server;
import io.micronaut.core.annotation.Internal;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.async.publisher.Publishers;
import io.micronaut.core.async.subscriber.LazySendingSubscriber;
import io.micronaut.core.convert.ConversionService;
import io.micronaut.core.execution.ExecutionFlow;
import io.micronaut.core.type.Argument;
import io.micronaut.http.ByteBodyHttpResponse;
import io.micronaut.http.ByteBodyHttpResponseWrapper;
import io.micronaut.http.HttpMethod;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.HttpResponseWrapper;
import io.micronaut.http.MediaType;
import io.micronaut.http.MutableHttpResponse;
import io.micronaut.http.body.ByteBody;
import io.micronaut.http.body.ByteBodyFactory;
import io.micronaut.http.body.CloseableByteBody;
import io.micronaut.http.body.ConcatenatingSubscriber;
import io.micronaut.http.body.MediaTypeProvider;
import io.micronaut.http.body.MessageBodyHandlerRegistry;
import io.micronaut.http.body.MessageBodyWriter;
import io.micronaut.http.body.ResponseBodyWriter;
import io.micronaut.http.codec.CodecException;
import io.micronaut.http.exceptions.HttpStatusException;
import io.micronaut.http.reactive.execution.ReactiveExecutionFlow;
import io.micronaut.web.router.DefaultUrlRouteInfo;
import io.micronaut.web.router.RouteAttributes;
import io.micronaut.web.router.RouteInfo;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;
/**
* This class handles encoding of the HTTP response in a server-agnostic way. Note that while this
* class is internal, it is used from servlet and must not be broken.
*
* @since 4.8.0
* @author Jonas Konrad
*/
@Internal
public abstract class ResponseLifecycle {
private final RouteExecutor routeExecutor;
private final MessageBodyHandlerRegistry messageBodyHandlerRegistry;
private final ConversionService conversionService;
private final ByteBodyFactory byteBodyFactory;
public ResponseLifecycle(RouteExecutor routeExecutor,
MessageBodyHandlerRegistry messageBodyHandlerRegistry,
ConversionService conversionService,
ByteBodyFactory byteBodyFactory) {
this.routeExecutor = routeExecutor;
this.messageBodyHandlerRegistry = messageBodyHandlerRegistry;
this.conversionService = conversionService;
this.byteBodyFactory = byteBodyFactory;
}
/**
* The IO executor for blocking writers.
*
* @return The blocking executor
*/
@NonNull
protected abstract Executor ioExecutor();
/**
* Transform the given writer into a {@link ResponseBodyWriter}.
*
* @param messageBodyWriter The writer
* @return The response writer
* @param The writer type
*/
@NonNull
protected ResponseBodyWriter wrap(@NonNull MessageBodyWriter messageBodyWriter) {
return ResponseBodyWriter.wrap(messageBodyWriter);
}
/**
* Encode the response.
*
* @param httpRequest The request that triggered this response
* @param response The unencoded response
* @return The encoded response
*/
@NonNull
public final ExecutionFlow extends ByteBodyHttpResponse>> encodeHttpResponseSafe(@NonNull HttpRequest> httpRequest, @NonNull HttpResponse> response) {
try {
return encodeHttpResponse(
httpRequest,
response,
response.body()
);
} catch (Throwable e) {
try {
response = routeExecutor.createDefaultErrorResponse(httpRequest, e);
return encodeHttpResponse(
httpRequest,
response,
response.body()
);
} catch (Throwable f) {
f.addSuppressed(e);
return ExecutionFlow.error(f);
}
}
}
@SuppressWarnings("unchecked")
private ExecutionFlow extends ByteBodyHttpResponse>> encodeHttpResponse(
HttpRequest> nettyRequest,
HttpResponse> httpResponse,
Object body) {
MutableHttpResponse> response = httpResponse.toMutableResponse();
if (nettyRequest.getMethod() != HttpMethod.HEAD && body != null) {
Object routeInfoO = RouteAttributes.getRouteInfo(response).orElse(null);
// usually this is a UriRouteInfo, avoid scalability issues here
@SuppressWarnings("unchecked") final RouteInfo