package com.bekwam.examples.javafx.nettyinaction.ch12; import java.io.File; import java.io.RandomAccessFile; import java.net.URISyntaxException; import java.net.URL; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.DefaultFileRegion; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.DefaultFullHttpResponse; 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.HttpHeaders; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.codec.http.LastHttpContent; import io.netty.handler.ssl.SslHandler; import io.netty.handler.stream.ChunkedNioFile; /** * Handles HTTP traffic for server process including WebSocket upgrade * * Returns web page (index.html) if contacting root context path. If ending * in /ws, pass along to next handler (a WebSocket handler). * * Based on "Netty in Action" example in Ch 12 * * @author carlwalker * */ public class EchoServerHttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> { private Logger logger = LoggerFactory.getLogger( EchoServerHttpRequestHandler.class ); private final String wsURI; private File indexHTML; public EchoServerHttpRequestHandler(String wsURI) throws URISyntaxException { this.wsURI = wsURI; String path = null; URL url = EchoServerHttpRequestHandler.class.getResource("/index.html"); path = url.getPath(); indexHTML = new File(path); } @Override protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { if( wsURI.equalsIgnoreCase(request.getUri()) ) { ctx.fireChannelRead(request.retain()); } else { if( HttpHeaders.is100ContinueExpected(request) ) { send100Continue(ctx); } try ( RandomAccessFile rFile = new RandomAccessFile(indexHTML, "r") ) { HttpResponse response = new DefaultHttpResponse( request.getProtocolVersion(), HttpResponseStatus.OK ); response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/html; charset=UTF-8"); boolean keepAlive = HttpHeaders.isKeepAlive(request); if( keepAlive ) { response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, rFile.length()); response.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE); } ctx.write(response); if( ctx.pipeline().get(SslHandler.class) == null ) { ctx.write(new DefaultFileRegion(rFile.getChannel(), 0, rFile.length())); } else { ctx.write(new ChunkedNioFile(rFile.getChannel())); } ChannelFuture future = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); if( !keepAlive ) { future.addListener(ChannelFutureListener.CLOSE); } } } } private void send100Continue(ChannelHandlerContext ctx) { FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE); ctx.writeAndFlush( response ); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { logger.error("error processing http", cause); ctx.close(); } }