From 84fa43e61081f4277dfc9d922b7699e73d25e486 Mon Sep 17 00:00:00 2001 From: yawkat Date: Mon, 8 Jan 2024 14:28:12 +0100 Subject: [PATCH] Make NettyJsonHandler implement NettyBodyWriter This leads to a slight speedup in #10131 but can be merged without the rest of the PR. Not sure if this has impact outside of #10131. --- .../http/netty/body/NettyJsonHandler.java | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/http-netty/src/main/java/io/micronaut/http/netty/body/NettyJsonHandler.java b/http-netty/src/main/java/io/micronaut/http/netty/body/NettyJsonHandler.java index e139d06a880..5c546191818 100644 --- a/http-netty/src/main/java/io/micronaut/http/netty/body/NettyJsonHandler.java +++ b/http-netty/src/main/java/io/micronaut/http/netty/body/NettyJsonHandler.java @@ -19,26 +19,38 @@ import io.micronaut.context.annotation.Replaces; import io.micronaut.context.annotation.Requires; import io.micronaut.core.annotation.Internal; +import io.micronaut.core.annotation.NonNull; import io.micronaut.core.io.buffer.ByteBuffer; import io.micronaut.core.io.buffer.ByteBufferFactory; import io.micronaut.core.type.Argument; import io.micronaut.core.type.Headers; import io.micronaut.core.type.MutableHeaders; +import io.micronaut.http.HttpHeaders; +import io.micronaut.http.HttpRequest; import io.micronaut.http.MediaType; +import io.micronaut.http.MutableHttpResponse; import io.micronaut.http.annotation.Consumes; import io.micronaut.http.annotation.Produces; import io.micronaut.http.body.ChunkedMessageBodyReader; import io.micronaut.http.body.MessageBodyHandler; import io.micronaut.http.body.MessageBodyWriter; import io.micronaut.http.codec.CodecException; +import io.micronaut.http.netty.NettyHttpHeaders; import io.micronaut.json.JsonFeatures; import io.micronaut.json.JsonMapper; import io.micronaut.json.body.JsonMessageHandler; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.EmptyHttpHeaders; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; import jakarta.inject.Singleton; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -73,7 +85,7 @@ }) @BootstrapContextCompatible @Requires(beans = JsonMapper.class) -public final class NettyJsonHandler implements MessageBodyHandler, ChunkedMessageBodyReader, CustomizableNettyJsonHandler { +public final class NettyJsonHandler implements MessageBodyHandler, ChunkedMessageBodyReader, CustomizableNettyJsonHandler, NettyBodyWriter { private final JsonMessageHandler jsonMessageHandler; public NettyJsonHandler(JsonMapper jsonMapper) { @@ -137,6 +149,23 @@ public ByteBuffer writeTo(Argument type, MediaType mediaType, T object, Mu return jsonMessageHandler.writeTo(type, mediaType, object, outgoingHeaders, bufferFactory); } + @Override + public @NonNull void writeTo(@NonNull HttpRequest request, @NonNull MutableHttpResponse outgoingResponse, @NonNull Argument type, @NonNull MediaType mediaType, @NonNull T object, @NonNull NettyWriteContext nettyContext) throws CodecException { + NettyHttpHeaders nettyHttpHeaders = (NettyHttpHeaders) outgoingResponse.getHeaders(); + if (!nettyHttpHeaders.contains(HttpHeaders.CONTENT_TYPE)) { + nettyHttpHeaders.set(HttpHeaderNames.CONTENT_TYPE, mediaType); + } + ByteBuf buffer = nettyContext.alloc().buffer(); + JsonMapper jsonMapper = jsonMessageHandler.getJsonMapper(); + try { + jsonMapper.writeValue(new ByteBufOutputStream(buffer), object); + } catch (IOException e) { + buffer.release(); + throw new CodecException("Error encoding object [" + object + "] to JSON: " + e.getMessage(), e); + } + nettyContext.writeFull(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf(outgoingResponse.code(), outgoingResponse.reason()), buffer, nettyHttpHeaders.getNettyHeaders(), EmptyHttpHeaders.INSTANCE)); + } + @Override public MessageBodyWriter createSpecific(Argument type) { return new NettyJsonHandler<>((JsonMessageHandler) jsonMessageHandler.createSpecific(type));