package rfx.server.http;
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.FullHttpResponse;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.handler.codec.http.QueryStringDecoder;
import java.util.List;
import java.util.Map;
import rfx.server.http.common.NettyHttpUtil;
import rfx.server.http.data.HttpRequestEvent;
/**
* the private handler for all Netty's message, transform to HttpRequestEvent and routing all matched processors
*
* @author trieu
*/
public class PrivateHttpProcessorRoutingHandler extends SimpleChannelInboundHandler<Object> {
private static Map<String, HttpProcessorManager> handlers;
public static final int PATTERN_INDEX = 2;
public static int DEFAULT_MAX_POOL_SIZE = 20;
public PrivateHttpProcessorRoutingHandler(){}
public static void init(String classpath, int processorPoolSize) throws Exception{
handlers = HttpProcessorManager.initProcessorPool(classpath, HttpProcessorConfig.PRIVATE_ACCESS, processorPoolSize);
}
public static void init(String classpath) throws Exception{
init(classpath, DEFAULT_MAX_POOL_SIZE);
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof HttpRequest) {
HttpRequest request = (HttpRequest) msg;
String uri = request.getUri();
String remoteIp = NettyHttpUtil.getRemoteIP(ctx, request);
String localIp = NettyHttpUtil.getLocalIP(ctx);
if (uri.equalsIgnoreCase(NettyHttpUtil.FAVICON_URI)) {
NettyHttpUtil.response1pxGifImage(ctx);
} else {
FullHttpResponse response = null;
//response = NettyHttpUtil.theHttpContent("Delivery Server OK");
//TODO access log
// try {
// AccessLogUtil.logAccess(request, ipAddress, uri);
// response = UriMapper.buildHttpResponse(ipAddress,ctx,request , uri);
// } catch (Exception e) {
// e.printStackTrace();
// LogUtil.error("HttpLogChannelHandler", e.getMessage());
// }
QueryStringDecoder qDecoder = new QueryStringDecoder(uri);
Map<String, List<String>> params = qDecoder.parameters();
HttpProcessorManager processorManager = HttpProcessorManager.routingForUriPath(handlers,qDecoder);
HttpRequestEvent requestEvent = null;
if(processorManager != null){
requestEvent = new HttpRequestEvent(localIp,remoteIp, uri, params, request);
response = processorManager.doProcessing(requestEvent);
} else {
processorManager = HttpProcessorManager.routingForUriPattern(handlers,qDecoder, PATTERN_INDEX);
if(processorManager != null){
requestEvent = new HttpRequestEvent(localIp, remoteIp, uri, params, request);
response = processorManager.doProcessing(requestEvent);
} else {
String s = "Not found HttpProcessor for URI: "+uri;
response = NettyHttpUtil.theHttpContent(s, HttpResponseStatus.NOT_FOUND);
}
}
//set version to response header
response.headers().add("Server", HttpServer.SERVER_INFO_VERSION);
// Write the response.
ChannelFuture future = ctx.write(response);
ctx.flush().close();
//callback and free resources
// if(requestEvent != null){
// requestEvent.clear();
// }
//Close the non-keep-alive connection after the write operation is done.
future.addListener(ChannelFutureListener.CLOSE);
}
}
if (msg instanceof HttpContent) {
if (msg instanceof LastHttpContent) {
NettyHttpUtil.response1pxGifImage(ctx);
}
}
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
ctx.flush().close();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
cause.printStackTrace();
ctx.flush().close();
}
}