use of io.micronaut.core.io.buffer.ByteBuffer in project micronaut-core by micronaut-projects.
the class TextStreamCodec method encode.
@SuppressWarnings("MagicNumber")
@Override
public <T, B> ByteBuffer<B> encode(T object, ByteBufferFactory<?, B> allocator) {
Event<Object> event;
if (object instanceof Event) {
event = (Event<Object>) object;
} else {
event = Event.of(object);
}
Object data = event.getData();
ByteBuffer body;
if (data instanceof CharSequence) {
body = allocator.copiedBuffer(data.toString().getBytes(defaultCharset));
} else {
MediaTypeCodec jsonCodec = resolveMediaTypeCodecRegistry().findCodec(MediaType.APPLICATION_JSON_TYPE).orElseThrow(() -> new CodecException("No possible JSON encoders found!"));
body = jsonCodec.encode(data, allocator);
}
ByteBuffer eventData = allocator.buffer(body.readableBytes() + 10);
writeAttribute(eventData, COMMENT_PREFIX, event.getComment());
writeAttribute(eventData, ID_PREFIX, event.getId());
writeAttribute(eventData, EVENT_PREFIX, event.getName());
Duration retry = event.getRetry();
if (retry != null) {
writeAttribute(eventData, RETRY_PREFIX, String.valueOf(retry.toMillis()));
}
// Write the data
int idx = body.indexOf((byte) '\n');
while (idx > -1) {
int length = idx + 1;
byte[] line = new byte[length];
body.read(line, 0, length);
eventData.write(DATA_PREFIX).write(line);
idx = body.indexOf((byte) '\n');
}
if (body.readableBytes() > 0) {
int length = body.readableBytes();
byte[] line = new byte[length];
body.read(line, 0, length);
eventData.write(DATA_PREFIX).write(line);
}
// Write new lines for event separation
eventData.write(NEWLINE).write(NEWLINE);
return eventData;
}
use of io.micronaut.core.io.buffer.ByteBuffer in project micronaut-core by micronaut-projects.
the class RoutingInBoundHandler method mapToHttpContent.
private Flux<HttpContent> mapToHttpContent(NettyHttpRequest<?> request, MutableHttpResponse<?> response, Object body, ChannelHandlerContext context) {
final RouteInfo<?> routeInfo = response.getAttribute(HttpAttributes.ROUTE_INFO, RouteInfo.class).orElse(null);
final boolean hasRouteInfo = routeInfo != null;
MediaType mediaType = response.getContentType().orElse(null);
if (mediaType == null && hasRouteInfo) {
mediaType = routeExecutor.resolveDefaultResponseContentType(request, routeInfo);
}
boolean isJson = mediaType != null && mediaType.getExtension().equals(MediaType.EXTENSION_JSON) && isJsonFormattable(hasRouteInfo ? routeInfo.getBodyType() : null);
NettyByteBufferFactory byteBufferFactory = new NettyByteBufferFactory(context.alloc());
Flux<Object> bodyPublisher = Flux.from(Publishers.convertPublisher(body, Publisher.class));
MediaType finalMediaType = mediaType;
Flux<HttpContent> httpContentPublisher = bodyPublisher.map(message -> {
HttpContent httpContent;
if (message instanceof ByteBuf) {
httpContent = new DefaultHttpContent((ByteBuf) message);
} else if (message instanceof ByteBuffer) {
ByteBuffer<?> byteBuffer = (ByteBuffer<?>) message;
Object nativeBuffer = byteBuffer.asNativeBuffer();
if (nativeBuffer instanceof ByteBuf) {
httpContent = new DefaultHttpContent((ByteBuf) nativeBuffer);
} else {
httpContent = new DefaultHttpContent(Unpooled.copiedBuffer(byteBuffer.asNioBuffer()));
}
} else if (message instanceof byte[]) {
httpContent = new DefaultHttpContent(Unpooled.copiedBuffer((byte[]) message));
} else if (message instanceof HttpContent) {
httpContent = (HttpContent) message;
} else {
MediaTypeCodec codec = mediaTypeCodecRegistry.findCodec(finalMediaType, message.getClass()).orElse(new TextPlainCodec(serverConfiguration.getDefaultCharset()));
if (LOG.isTraceEnabled()) {
LOG.trace("Encoding emitted response object [{}] using codec: {}", message, codec);
}
ByteBuffer<ByteBuf> encoded;
if (hasRouteInfo) {
// noinspection unchecked
final Argument<Object> bodyType = (Argument<Object>) routeInfo.getBodyType();
if (bodyType.isInstance(message)) {
encoded = codec.encode(bodyType, message, byteBufferFactory);
} else {
encoded = codec.encode(message, byteBufferFactory);
}
} else {
encoded = codec.encode(message, byteBufferFactory);
}
httpContent = new DefaultHttpContent(encoded.asNativeBuffer());
}
return httpContent;
});
if (isJson) {
// if the Publisher is returning JSON then in order for it to be valid JSON for each emitted element
// we must wrap the JSON in array and delimit the emitted items
httpContentPublisher = JsonSubscriber.lift(httpContentPublisher);
}
httpContentPublisher = httpContentPublisher.contextWrite(reactorContext -> reactorContext.put(ServerRequestContext.KEY, request)).doOnNext(httpContent -> context.read()).doAfterTerminate(() -> cleanupRequest(context, request));
return httpContentPublisher;
}
use of io.micronaut.core.io.buffer.ByteBuffer in project micronaut-core by micronaut-projects.
the class RoutingInBoundHandler method encodeResponseBody.
private void encodeResponseBody(ChannelHandlerContext context, HttpRequest<?> request, MutableHttpResponse<?> message, @Nullable Argument<Object> bodyType, Object body) {
if (body == null) {
return;
}
Optional<NettyCustomizableResponseTypeHandler> typeHandler = customizableResponseTypeHandlerRegistry.findTypeHandler(body.getClass());
if (typeHandler.isPresent()) {
NettyCustomizableResponseTypeHandler th = typeHandler.get();
setBodyContent(message, new NettyCustomizableResponseTypeHandlerInvoker(th, body));
} else {
MediaType mediaType = message.getContentType().orElse(null);
if (mediaType == null) {
mediaType = message.getAttribute(HttpAttributes.ROUTE_INFO, RouteInfo.class).map(routeInfo -> routeExecutor.resolveDefaultResponseContentType(request, routeInfo)).orElse(MediaType.APPLICATION_JSON_TYPE);
message.contentType(mediaType);
}
if (body instanceof CharSequence) {
ByteBuf byteBuf = Unpooled.wrappedBuffer(body.toString().getBytes(message.getCharacterEncoding()));
setResponseBody(message, byteBuf);
} else if (body instanceof byte[]) {
ByteBuf byteBuf = Unpooled.wrappedBuffer((byte[]) body);
setResponseBody(message, byteBuf);
} else if (body instanceof ByteBuffer) {
ByteBuffer<?> byteBuffer = (ByteBuffer) body;
Object nativeBuffer = byteBuffer.asNativeBuffer();
if (nativeBuffer instanceof ByteBuf) {
setResponseBody(message, (ByteBuf) nativeBuffer);
} else if (nativeBuffer instanceof java.nio.ByteBuffer) {
ByteBuf byteBuf = Unpooled.wrappedBuffer((java.nio.ByteBuffer) nativeBuffer);
setResponseBody(message, byteBuf);
}
} else if (body instanceof ByteBuf) {
setResponseBody(message, (ByteBuf) body);
} else {
Optional<MediaTypeCodec> registeredCodec = mediaTypeCodecRegistry.findCodec(mediaType, body.getClass());
if (registeredCodec.isPresent()) {
MediaTypeCodec codec = registeredCodec.get();
encodeBodyWithCodec(message, bodyType, body, codec, context, request);
} else {
MediaTypeCodec defaultCodec = new TextPlainCodec(serverConfiguration.getDefaultCharset());
encodeBodyWithCodec(message, bodyType, body, defaultCodec, context, request);
}
}
}
}
use of io.micronaut.core.io.buffer.ByteBuffer in project micronaut-core by micronaut-projects.
the class DefaultHttpClient method buildDataStreamPublisher.
/**
* @param request The request
* @param errorType The error type
* @param <I> The input type
* @return A {@link Function}
*/
protected <I> Function<URI, Publisher<ByteBuffer<?>>> buildDataStreamPublisher(@NonNull io.micronaut.http.HttpRequest<I> request, @NonNull Argument<?> errorType) {
final io.micronaut.http.HttpRequest<Object> parentRequest = ServerRequestContext.currentRequest().orElse(null);
return requestURI -> {
Flux<io.micronaut.http.HttpResponse<Object>> streamResponsePublisher = Flux.from(buildStreamExchange(parentRequest, request, requestURI, errorType));
Function<HttpContent, ByteBuffer<?>> contentMapper = message -> {
ByteBuf byteBuf = message.content();
return byteBufferFactory.wrap(byteBuf);
};
return streamResponsePublisher.switchMap(response -> {
if (!(response instanceof NettyStreamedHttpResponse)) {
throw new IllegalStateException("Response has been wrapped in non streaming type. Do not wrap the response in client filters for stream requests");
}
NettyStreamedHttpResponse nettyStreamedHttpResponse = (NettyStreamedHttpResponse) response;
Flux<HttpContent> httpContentReactiveSequence = Flux.from(nettyStreamedHttpResponse.getNettyResponse());
return httpContentReactiveSequence.filter(message -> !(message.content() instanceof EmptyByteBuf)).map(contentMapper);
}).doOnTerminate(() -> {
final Object o = request.getAttribute(NettyClientHttpRequest.CHANNEL).orElse(null);
if (o instanceof Channel) {
final Channel c = (Channel) o;
if (c.isOpen()) {
c.close();
}
}
});
};
}
Aggregations