Search in sources :

Example 1 with Action

use of ratpack.func.Action 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);
        }
    });
}
Also used : AttributeKey(io.netty.util.AttributeKey) DescribingHandlers(ratpack.handling.internal.DescribingHandlers) LoggerFactory(org.slf4j.LoggerFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Unpooled(io.netty.buffer.Unpooled) ByteBuf(io.netty.buffer.ByteBuf) MutableHeaders(ratpack.http.MutableHeaders) ServerConfig(ratpack.server.ServerConfig) Registry(ratpack.registry.Registry) CharsetUtil(io.netty.util.CharsetUtil) DefaultRenderController(ratpack.render.internal.DefaultRenderController) io.netty.channel(io.netty.channel) DefaultContext(ratpack.handling.internal.DefaultContext) Logger(org.slf4j.Logger) CharBuffer(java.nio.CharBuffer) ClosedChannelException(java.nio.channels.ClosedChannelException) ratpack.http.internal(ratpack.http.internal) ChainHandler(ratpack.handling.internal.ChainHandler) IOException(java.io.IOException) DescribingHandler(ratpack.handling.internal.DescribingHandler) Instant(java.time.Instant) InetSocketAddress(java.net.InetSocketAddress) ByteBufUtil(io.netty.buffer.ByteBufUtil) io.netty.handler.codec.http(io.netty.handler.codec.http) Response(ratpack.http.Response) Headers(ratpack.http.Headers) Action(ratpack.func.Action) Handler(ratpack.handling.Handler) Handlers(ratpack.handling.Handlers) ExecController(ratpack.exec.ExecController) Action(ratpack.func.Action) MutableHeaders(ratpack.http.MutableHeaders) Headers(ratpack.http.Headers) InetSocketAddress(java.net.InetSocketAddress) CharBuffer(java.nio.CharBuffer) ByteBuf(io.netty.buffer.ByteBuf) ServerConfig(ratpack.server.ServerConfig) MutableHeaders(ratpack.http.MutableHeaders) DescribingHandler(ratpack.handling.internal.DescribingHandler) ChainHandler(ratpack.handling.internal.ChainHandler) DescribingHandler(ratpack.handling.internal.DescribingHandler) Handler(ratpack.handling.Handler) Response(ratpack.http.Response) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) DefaultContext(ratpack.handling.internal.DefaultContext)

Example 2 with Action

use of ratpack.func.Action in project ratpack by ratpack.

the class Guice method buildInjector.

static Injector buildInjector(Registry baseRegistry, Action<? super BindingsSpec> bindingsAction, Function<? super Module, ? extends Injector> injectorFactory) throws Exception {
    List<Action<? super Binder>> binderActions = Lists.newLinkedList();
    List<Module> modules = Lists.newLinkedList();
    ServerConfig serverConfig = baseRegistry.get(ServerConfig.class);
    BindingsSpec bindings = new DefaultBindingsSpec(serverConfig, binderActions, modules);
    bindings.module(new RatpackBaseRegistryModule(baseRegistry));
    try {
        bindingsAction.execute(bindings);
    } catch (Exception e) {
        throw uncheck(e);
    }
    modules.add(new AdHocModule(binderActions));
    modules.add(new ConfigModule(serverConfig.getRequiredConfig()));
    Optional<BindingsImposition> bindingsImposition = Impositions.current().get(BindingsImposition.class);
    if (bindingsImposition.isPresent()) {
        BindingsImposition imposition = bindingsImposition.get();
        List<Action<? super Binder>> imposedBinderActions = Lists.newLinkedList();
        List<Module> imposedModules = Lists.newLinkedList();
        BindingsSpec imposedBindings = new DefaultBindingsSpec(serverConfig, imposedBinderActions, imposedModules);
        imposition.getBindings().execute(imposedBindings);
        imposedModules.add(new AdHocModule(imposedBinderActions));
        Module imposedModule = imposedModules.stream().reduce((acc, next) -> Modules.override(acc).with(next)).get();
        modules.add(imposedModule);
    }
    Module masterModule = modules.stream().reduce((acc, next) -> Modules.override(acc).with(next)).get();
    return injectorFactory.apply(masterModule);
}
Also used : Function(ratpack.func.Function) Module(com.google.inject.Module) RatpackBaseRegistryModule(ratpack.guice.internal.RatpackBaseRegistryModule) Context(ratpack.handling.Context) Modules(com.google.inject.util.Modules) Guice.createInjector(com.google.inject.Guice.createInjector) Exceptions.uncheck(ratpack.util.Exceptions.uncheck) Injector(com.google.inject.Injector) Stage(com.google.inject.Stage) Chain(ratpack.handling.Chain) ConfigObject(ratpack.config.ConfigObject) List(java.util.List) Lists(com.google.common.collect.Lists) Binder(com.google.inject.Binder) Impositions(ratpack.impose.Impositions) GuiceUtil(ratpack.guice.internal.GuiceUtil) InjectorRegistryBacking(ratpack.guice.internal.InjectorRegistryBacking) Action(ratpack.func.Action) Handler(ratpack.handling.Handler) ServerConfig(ratpack.server.ServerConfig) Registry(ratpack.registry.Registry) Optional(java.util.Optional) DefaultBindingsSpec(ratpack.guice.internal.DefaultBindingsSpec) Action(ratpack.func.Action) DefaultBindingsSpec(ratpack.guice.internal.DefaultBindingsSpec) DefaultBindingsSpec(ratpack.guice.internal.DefaultBindingsSpec) Binder(com.google.inject.Binder) ServerConfig(ratpack.server.ServerConfig) RatpackBaseRegistryModule(ratpack.guice.internal.RatpackBaseRegistryModule) Module(com.google.inject.Module) RatpackBaseRegistryModule(ratpack.guice.internal.RatpackBaseRegistryModule)

Example 3 with Action

use of ratpack.func.Action in project ratpack by ratpack.

the class DefaultExecHarness method run.

@Override
public void run(Action<? super RegistrySpec> registry, Action<? super Execution> action) throws Exception {
    final AtomicReference<Throwable> thrown = new AtomicReference<>();
    final CountDownLatch latch = new CountDownLatch(1);
    controller.fork().onError(thrown::set).register(registry).onComplete(e -> latch.countDown()).start(action::execute);
    latch.await();
    Throwable throwable = thrown.get();
    if (throwable != null) {
        throw Exceptions.toException(throwable);
    }
}
Also used : Function(ratpack.func.Function) CountDownLatch(java.util.concurrent.CountDownLatch) RegistrySpec(ratpack.registry.RegistrySpec) ratpack.exec(ratpack.exec) Action(ratpack.func.Action) ExecHarness(ratpack.test.exec.ExecHarness) Exceptions(ratpack.util.Exceptions) ResultBackedExecResult(ratpack.exec.internal.ResultBackedExecResult) AtomicReference(java.util.concurrent.atomic.AtomicReference) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch)

Example 4 with Action

use of ratpack.func.Action in project ratpack by ratpack.

the class DefaultExecHarness method yield.

@Override
public <T> ExecResult<T> yield(Action<? super RegistrySpec> registry, final Function<? super Execution, ? extends Promise<T>> func) throws Exception {
    AtomicReference<ExecResult<T>> reference = new AtomicReference<>();
    CountDownLatch latch = new CountDownLatch(1);
    controller.fork().register(registry).onError(throwable -> reference.set(new ResultBackedExecResult<>(Result.<T>error(throwable)))).onComplete(exec -> latch.countDown()).start(execution -> {
        reference.set(ExecResult.complete());
        Promise<T> promise = func.apply(execution);
        if (promise == null) {
            reference.set(null);
        } else {
            promise.then(t -> reference.set(new ResultBackedExecResult<>(Result.success(t))));
        }
    });
    latch.await();
    return reference.get();
}
Also used : Function(ratpack.func.Function) CountDownLatch(java.util.concurrent.CountDownLatch) RegistrySpec(ratpack.registry.RegistrySpec) ratpack.exec(ratpack.exec) Action(ratpack.func.Action) ExecHarness(ratpack.test.exec.ExecHarness) Exceptions(ratpack.util.Exceptions) ResultBackedExecResult(ratpack.exec.internal.ResultBackedExecResult) AtomicReference(java.util.concurrent.atomic.AtomicReference) ResultBackedExecResult(ratpack.exec.internal.ResultBackedExecResult) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch) ResultBackedExecResult(ratpack.exec.internal.ResultBackedExecResult)

Example 5 with Action

use of ratpack.func.Action in project ratpack by ratpack.

the class RequestActionSupport method addCommonResponseHandlers.

private void addCommonResponseHandlers(ChannelPipeline p, Downstream<? super T> downstream) throws Exception {
    if (channelKey.ssl && p.get(SSL_HANDLER_NAME) == null) {
        //this is added once because netty is not able to properly replace this handler on
        //pooled channels from request to request. Because a pool is unique to a uri,
        //doing this works, as subsequent requests would be passing in the same certs.
        p.addLast(SSL_HANDLER_NAME, createSslHandler());
    }
    p.addLast(CLIENT_CODEC_HANDLER_NAME, new HttpClientCodec(4096, 8192, 8192, false));
    p.addLast(READ_TIMEOUT_HANDLER_NAME, new ReadTimeoutHandler(requestConfig.readTimeout.toNanos(), TimeUnit.NANOSECONDS));
    p.addLast(REDIRECT_HANDLER_NAME, new SimpleChannelInboundHandler<HttpObject>(false) {

        boolean redirected;

        HttpResponse response;

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            forceDispose(ctx.pipeline());
            if (cause instanceof ReadTimeoutException) {
                cause = new HttpClientReadTimeoutException("Read timeout (" + requestConfig.readTimeout + ") waiting on HTTP server at " + requestConfig.uri);
            }
            error(downstream, cause);
        }

        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            Exception e = new PrematureChannelClosureException("Server " + requestConfig.uri + " closed the connection prematurely");
            error(downstream, e);
        }

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
            if (msg instanceof HttpResponse) {
                this.response = (HttpResponse) msg;
                int maxRedirects = requestConfig.maxRedirects;
                int status = response.status().code();
                String locationValue = response.headers().getAsString(HttpHeaderConstants.LOCATION);
                Action<? super RequestSpec> redirectConfigurer = RequestActionSupport.this.requestConfigurer;
                if (isRedirect(status) && redirectCount < maxRedirects && locationValue != null) {
                    final Function<? super ReceivedResponse, Action<? super RequestSpec>> onRedirect = requestConfig.onRedirect;
                    if (onRedirect != null) {
                        final Action<? super RequestSpec> onRedirectResult = onRedirect.apply(toReceivedResponse(response));
                        if (onRedirectResult == null) {
                            redirectConfigurer = null;
                        } else {
                            redirectConfigurer = redirectConfigurer.append(onRedirectResult);
                        }
                    }
                    if (redirectConfigurer != null) {
                        Action<? super RequestSpec> redirectRequestConfig = s -> {
                            if (status == 301 || status == 302) {
                                s.get();
                            }
                        };
                        redirectRequestConfig = redirectRequestConfig.append(redirectConfigurer);
                        URI locationUrl;
                        if (ABSOLUTE_PATTERN.matcher(locationValue).matches()) {
                            locationUrl = new URI(locationValue);
                        } else {
                            locationUrl = new URI(channelKey.ssl ? "https" : "http", null, channelKey.host, channelKey.port, locationValue, null, null);
                        }
                        onRedirect(locationUrl, redirectCount + 1, redirectRequestConfig).connect(downstream);
                        redirected = true;
                        dispose(ctx.pipeline(), response);
                    }
                }
            }
            if (!redirected) {
                ctx.fireChannelRead(msg);
            }
        }
    });
    if (requestConfig.decompressResponse) {
        p.addLast(DECOMPRESS_HANDLER_NAME, new HttpContentDecompressor());
    }
    addResponseHandlers(p, downstream);
}
Also used : Action(ratpack.func.Action) ReadTimeoutException(io.netty.handler.timeout.ReadTimeoutException) HttpClientReadTimeoutException(ratpack.http.client.HttpClientReadTimeoutException) HttpClientReadTimeoutException(ratpack.http.client.HttpClientReadTimeoutException) PrematureChannelClosureException(io.netty.handler.codec.PrematureChannelClosureException) ReceivedResponse(ratpack.http.client.ReceivedResponse) URI(java.net.URI) PrematureChannelClosureException(io.netty.handler.codec.PrematureChannelClosureException) ReadTimeoutException(io.netty.handler.timeout.ReadTimeoutException) HttpClientReadTimeoutException(ratpack.http.client.HttpClientReadTimeoutException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) Function(ratpack.func.Function) ReadTimeoutHandler(io.netty.handler.timeout.ReadTimeoutHandler) RequestSpec(ratpack.http.client.RequestSpec)

Aggregations

Action (ratpack.func.Action)7 Function (ratpack.func.Function)5 Lists (com.google.common.collect.Lists)2 Instant (java.time.Instant)2 CountDownLatch (java.util.concurrent.CountDownLatch)2 AtomicReference (java.util.concurrent.atomic.AtomicReference)2 Logger (org.slf4j.Logger)2 LoggerFactory (org.slf4j.LoggerFactory)2 ratpack.exec (ratpack.exec)2 ExecController (ratpack.exec.ExecController)2 ResultBackedExecResult (ratpack.exec.internal.ResultBackedExecResult)2 Handler (ratpack.handling.Handler)2 Registry (ratpack.registry.Registry)2 RegistrySpec (ratpack.registry.RegistrySpec)2 ServerConfig (ratpack.server.ServerConfig)2 ExecHarness (ratpack.test.exec.ExecHarness)2 Exceptions (ratpack.util.Exceptions)2 Throwables.getStackTraceAsString (com.google.common.base.Throwables.getStackTraceAsString)1 Maps (com.google.common.collect.Maps)1 TypeToken (com.google.common.reflect.TypeToken)1