use of io.micronaut.http.server.netty.NettyHttpRequest in project micronaut-core by micronaut-projects.
the class HttpRequestDecoder method decode.
@Override
protected void decode(ChannelHandlerContext ctx, HttpRequest msg, List<Object> out) {
if (LOG.isTraceEnabled()) {
LOG.trace("Server {}:{} Received Request: {} {}", embeddedServer.getHost(), embeddedServer.getPort(), msg.method(), msg.uri());
}
try {
NettyHttpRequest<Object> request = new NettyHttpRequest<>(msg, ctx, conversionService, configuration);
if (httpRequestReceivedEventPublisher != ApplicationEventPublisher.NO_OP) {
try {
ctx.executor().execute(() -> {
try {
httpRequestReceivedEventPublisher.publishEvent(new HttpRequestReceivedEvent(request));
} catch (Exception e) {
if (LOG.isErrorEnabled()) {
LOG.error("Error publishing Http request received event: " + e.getMessage(), e);
}
}
});
} catch (Exception e) {
if (LOG.isErrorEnabled()) {
LOG.error("Error publishing Http request received event: " + e.getMessage(), e);
}
}
}
out.add(request);
} catch (IllegalArgumentException e) {
// this configured the request in the channel as an attribute
new NettyHttpRequest<>(new DefaultHttpRequest(msg.protocolVersion(), msg.method(), "/"), ctx, conversionService, configuration);
final Throwable cause = e.getCause();
ctx.fireExceptionCaught(cause != null ? cause : e);
if (msg instanceof StreamedHttpRequest) {
// discard any data that may come in
((StreamedHttpRequest) msg).closeIfNoSubscriber();
}
}
}
use of io.micronaut.http.server.netty.NettyHttpRequest in project micronaut-core by micronaut-projects.
the class CompletableFutureBodyBinder method bind.
@Override
public BindingResult<CompletableFuture> bind(ArgumentConversionContext<CompletableFuture> context, HttpRequest<?> source) {
if (source instanceof NettyHttpRequest) {
NettyHttpRequest nettyHttpRequest = (NettyHttpRequest) source;
io.netty.handler.codec.http.HttpRequest nativeRequest = ((NettyHttpRequest) source).getNativeRequest();
if (nativeRequest instanceof StreamedHttpRequest) {
CompletableFuture future = new CompletableFuture();
Argument<?> targetType = context.getFirstTypeVariable().orElse(Argument.OBJECT_ARGUMENT);
HttpContentProcessor<?> processor = httpContentProcessorResolver.resolve(nettyHttpRequest, targetType);
processor.subscribe(new CompletionAwareSubscriber<Object>() {
@Override
protected void doOnSubscribe(Subscription subscription) {
subscription.request(1);
}
@Override
protected void doOnNext(Object message) {
if (message instanceof ByteBufHolder) {
nettyHttpRequest.addContent((ByteBufHolder) message);
} else {
nettyHttpRequest.setBody(message);
}
subscription.request(1);
}
@Override
protected void doOnError(Throwable t) {
future.completeExceptionally(t);
}
@Override
protected void doOnComplete() {
Optional<Argument<?>> firstTypeParameter = context.getFirstTypeVariable();
if (firstTypeParameter.isPresent()) {
Argument<?> arg = firstTypeParameter.get();
Optional converted = nettyHttpRequest.getBody(arg);
if (converted.isPresent()) {
future.complete(converted.get());
} else {
future.completeExceptionally(new IllegalArgumentException("Cannot bind body to argument type: " + arg.getType().getName()));
}
} else {
future.complete(nettyHttpRequest.getBody().orElse(null));
}
}
});
return () -> Optional.of(future);
} else {
return BindingResult.EMPTY;
}
} else {
return BindingResult.EMPTY;
}
}
use of io.micronaut.http.server.netty.NettyHttpRequest in project micronaut-core by micronaut-projects.
the class NettyStreamedCustomizableResponseType method write.
@Override
default void write(HttpRequest<?> request, MutableHttpResponse<?> response, ChannelHandlerContext context) {
if (response instanceof NettyMutableHttpResponse) {
NettyMutableHttpResponse nettyResponse = ((NettyMutableHttpResponse) response);
// Write the request data
final DefaultHttpResponse finalResponse = new DefaultHttpResponse(nettyResponse.getNettyHttpVersion(), nettyResponse.getNettyHttpStatus(), nettyResponse.getNettyHeaders());
final io.micronaut.http.HttpVersion httpVersion = request.getHttpVersion();
final boolean isHttp2 = httpVersion == io.micronaut.http.HttpVersion.HTTP_2_0;
if (request instanceof NettyHttpRequest) {
((NettyHttpRequest<?>) request).prepareHttp2ResponseIfNecessary(finalResponse);
}
InputStream inputStream = getInputStream();
// can be null if the stream was closed
context.write(finalResponse, context.voidPromise());
if (inputStream != null) {
ChannelFutureListener closeListener = (future) -> {
try {
inputStream.close();
} catch (IOException e) {
LOG.warn("An error occurred closing an input stream", e);
}
};
final HttpChunkedInput chunkedInput = new HttpChunkedInput(new ChunkedStream(inputStream));
context.writeAndFlush(chunkedInput).addListener(closeListener);
} else {
context.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
}
} else {
throw new IllegalArgumentException("Unsupported response type. Not a Netty response: " + response);
}
}
use of io.micronaut.http.server.netty.NettyHttpRequest in project micronaut-core by micronaut-projects.
the class FileTypeHandler method handle.
@SuppressWarnings("MagicNumber")
@Override
public void handle(Object obj, HttpRequest<?> request, MutableHttpResponse<?> response, ChannelHandlerContext context) {
NettyFileCustomizableResponseType type;
if (obj instanceof File) {
type = new NettySystemFileCustomizableResponseType((File) obj);
} else if (obj instanceof NettyFileCustomizableResponseType) {
type = (NettyFileCustomizableResponseType) obj;
} else if (obj instanceof StreamedFile) {
type = new NettyStreamedFileCustomizableResponseType((StreamedFile) obj);
} else if (obj instanceof SystemFile) {
type = new NettySystemFileCustomizableResponseType((SystemFile) obj);
} else {
throw new CustomizableResponseTypeException("FileTypeHandler only supports File or FileCustomizableResponseType types");
}
long lastModified = type.getLastModified();
// Cache Validation
ZonedDateTime ifModifiedSince = request.getHeaders().getDate(HttpHeaders.IF_MODIFIED_SINCE);
if (ifModifiedSince != null) {
// Only compare up to the second because the datetime format we send to the client
// does not have milliseconds
long ifModifiedSinceDateSeconds = ifModifiedSince.toEpochSecond();
long fileLastModifiedSeconds = lastModified / 1000;
if (ifModifiedSinceDateSeconds == fileLastModifiedSeconds) {
FullHttpResponse nettyResponse = notModified(response);
if (request instanceof NettyHttpRequest) {
((NettyHttpRequest<?>) request).prepareHttp2ResponseIfNecessary(nettyResponse);
}
context.writeAndFlush(nettyResponse);
return;
}
}
if (!response.getHeaders().contains(HttpHeaders.CONTENT_TYPE)) {
response.header(HttpHeaders.CONTENT_TYPE, type.getMediaType().toString());
}
setDateAndCacheHeaders(response, lastModified);
type.process(response);
type.write(request, response, context);
context.read();
}
use of io.micronaut.http.server.netty.NettyHttpRequest in project micronaut-core by micronaut-projects.
the class HttpRequestTest method testForEach2.
public void testForEach2() {
final DefaultFullHttpRequest nettyRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, io.netty.handler.codec.http.HttpMethod.GET, "/test");
nettyRequest.headers().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
nettyRequest.headers().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML);
HttpRequest<?> request = new NettyHttpRequest(nettyRequest, new DetachedMockFactory().Mock(ChannelHandlerContext.class), ConversionService.SHARED, new HttpServerConfiguration());
final HttpHeaders headers = request.getHeaders();
headers.forEach((name, values) -> {
assertEquals(HttpHeaders.CONTENT_TYPE, name);
assertEquals(2, values.size());
assertTrue(values.contains(MediaType.APPLICATION_JSON));
assertTrue(values.contains(MediaType.APPLICATION_XML));
});
AtomicInteger integer = new AtomicInteger(0);
headers.forEachValue((s, s2) -> integer.incrementAndGet());
assertEquals(2, integer.get());
}
Aggregations