package org.caudexorigo.http.netty; import java.nio.charset.Charset; import org.caudexorigo.ErrorAnalyser; import org.caudexorigo.http.netty.reporting.ResponseFormatter; import org.caudexorigo.http.netty.reporting.StandardResponseFormatter; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelFutureListener; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.handler.codec.http.HttpHeaders; import org.jboss.netty.handler.codec.http.HttpRequest; import org.jboss.netty.handler.codec.http.HttpResponse; import org.jboss.netty.handler.codec.http.HttpResponseStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class HttpAction { private static Logger log = LoggerFactory.getLogger(HttpAction.class); public abstract void service(ChannelHandlerContext ctx, HttpRequest request, HttpResponse response); private HttpRequest request = null; private ResponseFormatter defaultRspFmt = new StandardResponseFormatter(false); public HttpAction() { super(); } protected final void process(ChannelHandlerContext ctx, HttpRequest request, HttpResponse response) { request = (this.request != null) ? this.request : request; if (this instanceof StaticFileAction) { try { service(ctx, request, response); } catch (Throwable ex) { handleError(ctx, request, response, ex); commitResponse(ctx, response, false); } } else { boolean is_keep_alive = HttpHeaders.isKeepAlive(request); if (!is_keep_alive) { response.headers().set(HttpHeaders.Names.CONNECTION, "Close"); } try { HttpRequestWrapper hrw = null; if (request instanceof HttpRequestWrapper) { hrw = (HttpRequestWrapper) request; } else { hrw = new HttpRequestWrapper(request, getCharset()); } service(ctx, hrw, response); } catch (Throwable ex) { handleError(ctx ,request, response, ex); } finally { commitResponse(ctx, response, is_keep_alive); } } } private void handleError(ChannelHandlerContext ctx, HttpRequest request, HttpResponse response, Throwable ex) { request = (this.request != null) ? this.request : request; response.headers().clear(); Throwable rootCause = ErrorAnalyser.findRootCause(ex); if (ex instanceof WebException) { WebException w_ex = (WebException) ex; response.setStatus(HttpResponseStatus.valueOf(w_ex.getHttpStatusCode())); } if (log.isDebugEnabled()) { log.error(rootCause.getMessage(), rootCause); } else { log.error("http.netty.error: {}; path: {}", rootCause.getMessage(), request.getUri()); } writeStandardResponse(ctx, request, response, rootCause); } private void commitResponse(ChannelHandlerContext ctx, HttpResponse response, boolean is_keep_alive) { response.headers().set(HttpHeaders.Names.DATE, HttpDateFormat.getCurrentHttpDate()); response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(response.getContent().writerIndex())); Channel channel = ctx.getChannel(); ChannelFuture future = channel.write(response); if (!is_keep_alive) { future.addListener(ChannelFutureListener.CLOSE); } } private void writeStandardResponse(ChannelHandlerContext ctx, HttpRequest request, HttpResponse response, Throwable rootCause) { request = (this.request != null) ? this.request : request; ResponseFormatter rspFrm = getResponseFormatter(); if (rootCause != null) { try { if (response.getStatus().getCode() < 400) { response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR); } rspFrm.formatResponse(ctx, request, response, rootCause); } catch (Throwable e) { log.error(e.getMessage(), e); } } } public void setRequest(HttpRequest request) { this.request = request; } public Charset getCharset() { return null; } protected ResponseFormatter getResponseFormatter() { return defaultRspFmt; } }