All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.dreamhead.moco.internal.MocoHandler Maven / Gradle / Ivy

Go to download

Moco is an easy setup stub framework, mainly focusing on testing and integration.

There is a newer version: 1.5.0
Show newest version
package com.github.dreamhead.moco.internal;

import com.github.dreamhead.moco.util.Strings;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;

import static com.google.common.net.HttpHeaders.UPGRADE;
import static io.netty.channel.ChannelHandler.Sharable;
import static io.netty.handler.codec.http.HttpUtil.isKeepAlive;

@Sharable
public final class MocoHandler extends SimpleChannelInboundHandler {
    private final ActualHttpServer server;
    private final HttpHandler httpHandler;
    private final WebSocketHandler websocketHandler;

    public MocoHandler(final ActualHttpServer server) {
        this.server = server;
        this.httpHandler = new HttpHandler(server);
        this.websocketHandler = new WebSocketHandler(server.getWebsocketServer());
    }

    @Override
    public void channelInactive(final ChannelHandlerContext ctx) {
        websocketHandler.disconnect(ctx);
    }

    @Override
    protected void channelRead0(final ChannelHandlerContext ctx, final Object message) {
        if (message instanceof FullHttpRequest) {
            handleHttpRequest(ctx, (FullHttpRequest) message);
            return;
        }

        if (message instanceof WebSocketFrame) {
            websocketHandler.handleFrame(ctx, (WebSocketFrame) message);
        }
    }

    private void handleHttpRequest(final ChannelHandlerContext ctx, final FullHttpRequest request) {
        if (!request.decoderResult().isSuccess()) {
            ctx.writeAndFlush(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));
            return;
        }

        if (!upgradeWebsocket(request)) {
            FullHttpResponse response = httpHandler.handleRequest(request);
            closeIfNotKeepAlive(request, ctx.write(response));
            return;
        }

        websocketHandler.connect(ctx, request);
    }

    private boolean upgradeWebsocket(final FullHttpRequest request) {
        if (io.netty.handler.codec.http.HttpMethod.GET.equals(request.method())) {
            String upgrade = request.headers().get(UPGRADE);
            return "websocket".equals(Strings.strip(upgrade));
        }

        return false;
    }

    @Override
    public void channelReadComplete(final ChannelHandlerContext ctx) {
        ctx.flush();
    }

    private void closeIfNotKeepAlive(final FullHttpRequest request, final ChannelFuture future) {
        if (!isKeepAlive(request)) {
            future.addListener(ChannelFutureListener.CLOSE);
        }
    }

    @Override
    public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) {
        server.onException(cause);
    }
}