reactor.io.net.impl.netty.http.NettyHttpServer.java Source code

Java tutorial

Introduction

Here is the source code for reactor.io.net.impl.netty.http.NettyHttpServer.java

Source

/*
 * Copyright (c) 2011-2015 Pivotal Software Inc, All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package reactor.io.net.impl.netty.http;

import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.handler.logging.LoggingHandler;
import org.reactivestreams.Publisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.Environment;
import reactor.core.Dispatcher;
import reactor.io.buffer.Buffer;
import reactor.io.codec.Codec;
import reactor.io.net.ChannelStream;
import reactor.io.net.ReactorChannelHandler;
import reactor.io.net.config.ServerSocketOptions;
import reactor.io.net.config.SslOptions;
import reactor.io.net.http.HttpChannel;
import reactor.io.net.http.HttpServer;
import reactor.io.net.impl.netty.NettyChannelStream;
import reactor.io.net.impl.netty.tcp.NettyTcpServer;
import reactor.io.net.tcp.TcpServer;
import reactor.rx.Promise;
import reactor.rx.Streams;

import java.net.InetSocketAddress;

/**
 * A Netty-based {@code TcpServer} implementation
 *
 * @param <IN>  The type that will be received by this server
 * @param <OUT> The type that will be sent by this server
 * @author Jon Brisbin
 * @author Stephane Maldini
 */
public class NettyHttpServer<IN, OUT> extends HttpServer<IN, OUT> {

    private static final Logger log = LoggerFactory.getLogger(NettyHttpServer.class);

    protected final TcpServer<IN, OUT> server;

    protected NettyHttpServer(final Environment env, final Dispatcher dispatcher,
            final InetSocketAddress listenAddress, final ServerSocketOptions options, final SslOptions sslOptions,
            final Codec<Buffer, IN, OUT> codec) {

        super(env, dispatcher, codec);

        this.server = new NettyTcpServer<IN, OUT>(env, dispatcher, listenAddress, options, sslOptions, codec) {

            @Override
            protected void bindChannel(ReactorChannelHandler<IN, OUT, ChannelStream<IN, OUT>> handler,
                    SocketChannel nativeChannel) {
                NettyHttpServer.this.bindChannel(handler, nativeChannel);
            }
        };
    }

    @Override
    public InetSocketAddress getListenAddress() {
        return this.server.getListenAddress();
    }

    @Override
    protected Promise<Void> doStart(final ReactorChannelHandler<IN, OUT, HttpChannel<IN, OUT>> handler) {
        return server.start(new ReactorChannelHandler<IN, OUT, ChannelStream<IN, OUT>>() {
            @Override
            public Publisher<Void> apply(ChannelStream<IN, OUT> ch) {
                NettyHttpChannel<IN, OUT> request = (NettyHttpChannel<IN, OUT>) ch;

                if (handler != null) {
                    handler.apply(request);
                }

                Iterable<? extends Publisher<Void>> handlers = routeChannel(request);

                //404
                if (handlers == null) {
                    if (request.checkHeader()) {
                        request.delegate().writeAndFlush(
                                new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND));
                    }

                    return Streams.empty();
                }
                return Streams.concat(handlers);
            }
        });
    }

    @Override
    protected Iterable<? extends Publisher<Void>> routeChannel(HttpChannel<IN, OUT> ch) {
        Iterable<? extends Publisher<Void>> handlers = super.routeChannel(ch);
        if (!handlers.iterator().hasNext()) {
            return null;
        } else {
            return handlers;
        }
    }

    @Override
    protected void onWebsocket(HttpChannel<IN, OUT> next) {
        ChannelPipeline pipeline = ((SocketChannel) next.delegate()).pipeline();
        pipeline.addLast(pipeline.remove(NettyHttpServerHandler.class).withWebsocketSupport(next.uri(), null));

    }

    @Override
    protected final Promise<Void> doShutdown() {
        return server.shutdown();
    }

    protected void bindChannel(ReactorChannelHandler<IN, OUT, ChannelStream<IN, OUT>> handler,
            SocketChannel nativeChannel) {

        NettyChannelStream<IN, OUT> netChannel = new NettyChannelStream<IN, OUT>(getDefaultEnvironment(),
                getDefaultCodec(), getDefaultPrefetchSize(), getDefaultDispatcher(), nativeChannel);

        ChannelPipeline pipeline = nativeChannel.pipeline();

        if (log.isDebugEnabled()) {
            pipeline.addLast(new LoggingHandler(NettyHttpServer.class));
        }

        pipeline.addLast(new HttpServerCodec());

        if (hasWebsocketEndpoints()) {
            pipeline.addLast(new HttpObjectAggregator(65536));
        }

        pipeline.addLast(new NettyHttpServerHandler<IN, OUT>(handler, netChannel));

    }
}