use of ratpack.http.Response in project ratpack by ratpack.
the class NettyHandlerAdapter method newRequest.
private void newRequest(final ChannelHandlerContext ctx, final HttpRequest nettyRequest) throws Exception {
if (!nettyRequest.decoderResult().isSuccess()) {
sendError(ctx, HttpResponseStatus.BAD_REQUEST);
return;
}
Headers requestHeaders = new NettyHeadersBackedHeaders(nettyRequest.headers());
//Find the content length we will use this as an indicator of a body
Long contentLength = HttpUtil.getContentLength(nettyRequest, -1L);
String transferEncoding = requestHeaders.get(HttpHeaderNames.TRANSFER_ENCODING);
//If there is a content length or transfer encoding that indicates there is a body
boolean hasBody = (contentLength > 0) || (transferEncoding != null);
RequestBody requestBody = hasBody ? new RequestBody(contentLength, nettyRequest, ctx) : null;
final Channel channel = ctx.channel();
if (requestBody != null) {
channel.attr(BODY_ACCUMULATOR_KEY).set(requestBody);
}
InetSocketAddress remoteAddress = (InetSocketAddress) channel.remoteAddress();
InetSocketAddress socketAddress = (InetSocketAddress) channel.localAddress();
final DefaultRequest request = new DefaultRequest(Instant.now(), requestHeaders, nettyRequest.method(), nettyRequest.protocolVersion(), nettyRequest.uri(), remoteAddress, socketAddress, serverRegistry.get(ServerConfig.class), requestBody);
final HttpHeaders nettyHeaders = new DefaultHttpHeaders(false);
final MutableHeaders responseHeaders = new NettyHeadersBackedMutableHeaders(nettyHeaders);
final AtomicBoolean transmitted = new AtomicBoolean(false);
final DefaultResponseTransmitter responseTransmitter = new DefaultResponseTransmitter(transmitted, channel, nettyRequest, request, nettyHeaders, requestBody);
ctx.channel().attr(DefaultResponseTransmitter.ATTRIBUTE_KEY).set(responseTransmitter);
Action<Action<Object>> subscribeHandler = thing -> {
transmitted.set(true);
ctx.channel().attr(CHANNEL_SUBSCRIBER_ATTRIBUTE_KEY).set(thing);
};
final DefaultContext.RequestConstants requestConstants = new DefaultContext.RequestConstants(applicationConstants, request, channel, responseTransmitter, subscribeHandler);
final Response response = new DefaultResponse(responseHeaders, ctx.alloc(), responseTransmitter);
requestConstants.response = response;
DefaultContext.start(channel.eventLoop(), requestConstants, serverRegistry, handlers, execution -> {
if (requestBody != null) {
requestBody.close();
channel.attr(BODY_ACCUMULATOR_KEY).set(null);
}
if (!transmitted.get()) {
Handler lastHandler = requestConstants.handler;
StringBuilder description = new StringBuilder();
description.append("No response sent for ").append(request.getMethod().getName()).append(" request to ").append(request.getUri());
if (lastHandler != null) {
description.append(" (last handler: ");
if (lastHandler instanceof DescribingHandler) {
((DescribingHandler) lastHandler).describeTo(description);
} else {
DescribingHandlers.describeTo(lastHandler, description);
}
description.append(")");
}
String message = description.toString();
LOGGER.warn(message);
response.getHeaders().clear();
ByteBuf body;
if (development) {
CharBuffer charBuffer = CharBuffer.wrap(message);
body = ByteBufUtil.encodeString(ctx.alloc(), charBuffer, CharsetUtil.UTF_8);
response.contentType(HttpHeaderConstants.PLAIN_TEXT_UTF8);
} else {
body = Unpooled.EMPTY_BUFFER;
}
response.getHeaders().set(HttpHeaderConstants.CONTENT_LENGTH, body.readableBytes());
responseTransmitter.transmit(HttpResponseStatus.INTERNAL_SERVER_ERROR, body);
}
});
}
use of ratpack.http.Response in project ratpack by ratpack.
the class FileRenderer method sendFile.
public static void sendFile(Context context, Path file, BasicFileAttributes attributes) {
Date date = new Date(attributes.lastModifiedTime().toMillis());
context.lastModified(date, () -> {
final String ifNoneMatch = context.getRequest().getHeaders().get(HttpHeaderNames.IF_NONE_MATCH);
Response response = context.getResponse();
if (ifNoneMatch != null && ifNoneMatch.trim().equals("*")) {
response.status(NOT_MODIFIED.code()).send();
return;
}
response.contentTypeIfNotSet(() -> context.get(MimeTypes.class).getContentType(file.getFileName().toString()));
response.getHeaders().set(HttpHeaderConstants.CONTENT_LENGTH, Long.toString(attributes.size()));
try {
response.sendFile(file);
} catch (Exception e) {
throw Exceptions.uncheck(e);
}
});
}
use of ratpack.http.Response in project ratpack by ratpack.
the class ServerSentEvents method render.
/**
* {@inheritDoc}
*/
@Override
public void render(Context context) throws Exception {
ByteBufAllocator bufferAllocator = context.get(ByteBufAllocator.class);
Response response = context.getResponse();
response.getHeaders().add(HttpHeaderConstants.CONTENT_TYPE, HttpHeaderConstants.TEXT_EVENT_STREAM_CHARSET_UTF_8);
response.getHeaders().add(HttpHeaderConstants.TRANSFER_ENCODING, HttpHeaderConstants.CHUNKED);
response.getHeaders().add(HttpHeaderConstants.CACHE_CONTROL, HttpHeaderConstants.NO_CACHE_FULL);
response.getHeaders().add(HttpHeaderConstants.PRAGMA, HttpHeaderConstants.NO_CACHE);
response.sendStream(Streams.map(publisher, i -> ServerSentEventEncoder.INSTANCE.encode(i, bufferAllocator)));
}
use of ratpack.http.Response in project ratpack by ratpack.
the class ResponseTimer method handle.
/**
* Adds the number of milliseconds of elapsed time between {@link Request#getTimestamp()} and when the response is ready to be sent.
* <p>
* The timer is stopped, and the header added, by {@link Response#beforeSend(ratpack.func.Action)}.
* This means that the time value is the elapsed time, commonly referred to as wall clock time, and not CPU time.
* Similarly, it does not include the time to actually start sending data out over the socket.
* It effectively times the application processing.
* <p>
* The value is in milliseconds, accurate to 5 decimal places.
*
* @param ctx the handling context.
*/
@Override
public void handle(Context ctx) {
Response response = ctx.getResponse();
response.beforeSend(m -> {
Clock clock = ctx.get(Clock.class);
Instant start = ctx.getRequest().getTimestamp();
long nanos = start.until(Instant.now(clock), ChronoUnit.NANOS);
BigDecimal diffNanos = new BigDecimal(nanos);
BigDecimal diffMillis = diffNanos.divide(NANOS_IN_MILLIS, 5, RoundingMode.UP);
m.getHeaders().set(HEADER_NAME, diffMillis.toString());
});
ctx.next();
}
use of ratpack.http.Response in project ratpack by ratpack.
the class DefaultContext method onErrorHandlerError.
private void onErrorHandlerError(ServerErrorHandler serverErrorHandler, Throwable original, Throwable errorHandlerThrowable) {
String msg = "Throwable thrown by error handler " + serverErrorHandler + " while handling throwable\n" + "Original throwable: " + getStackTraceAsString(original) + "\n" + "Error handler throwable: " + getStackTraceAsString(errorHandlerThrowable);
LOGGER.error(msg);
Response response = requestConstants.response.status(500);
if (getServerConfig().isDevelopment()) {
response.send(msg);
} else {
response.send();
}
}
Aggregations