package core.framework.impl.web; import core.framework.api.web.Response; import core.framework.api.web.ResponseImpl; import core.framework.impl.log.ActionLog; import core.framework.impl.log.LogManager; import core.framework.impl.web.request.RequestImpl; import core.framework.impl.web.request.RequestParser; import core.framework.impl.web.response.ResponseHandler; import core.framework.impl.web.route.Route; import core.framework.impl.web.session.SessionManager; import core.framework.impl.web.site.SiteManager; import io.undertow.server.HttpHandler; import io.undertow.server.HttpServerExchange; import io.undertow.util.HeaderMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author neo */ public class HTTPServerHandler implements HttpHandler { public static final String HEADER_REF_ID = "ref-id"; public static final String HEADER_TRACE = "trace"; public static final String HEADER_CLIENT = "client"; public final BeanValidator validator = new BeanValidator(); public final Route route = new Route(); public final Interceptors interceptors = new Interceptors(); public final WebContextImpl webContext = new WebContextImpl(); public final HTTPServerErrorHandler errorHandler; private final Logger logger = LoggerFactory.getLogger(HTTPServerHandler.class); private final RequestParser requestParser = new RequestParser(); private final LogManager logManager; private final SessionManager sessionManager; private final ResponseHandler responseHandler; public HTTPServerHandler(LogManager logManager, SiteManager siteManager) { this.logManager = logManager; sessionManager = siteManager.sessionManager; responseHandler = new ResponseHandler(validator, siteManager.templateManager); errorHandler = new HTTPServerErrorHandler(responseHandler); } @Override public void handleRequest(HttpServerExchange exchange) throws Exception { if (exchange.isInIoThread()) { exchange.dispatch(this); return; } logManager.begin("=== http transaction begin ==="); RequestImpl request = new RequestImpl(exchange, validator); try { webContext.initialize(request); // initialize webContext at beginning, the customerErrorHandler in errorHandler may use it if any exception ActionLog actionLog = logManager.currentActionLog(); requestParser.parse(request, exchange, actionLog); request.session = sessionManager.load(request); HeaderMap headers = exchange.getRequestHeaders(); String client = headers.getFirst(HTTPServerHandler.HEADER_CLIENT); if (client != null) actionLog.context("client", client); actionLog.refId(headers.getFirst(HTTPServerHandler.HEADER_REF_ID)); ControllerHolder controller = route.get(request.path(), request.method(), request.pathParams, actionLog); actionLog.action(controller.action); actionLog.context("controller", controller.controllerInfo); logger.debug("controllerClass={}", controller.controller.getClass().getCanonicalName()); // trigger trace after action is determined due to trace log use action as part of path, is there better way? if ("true".equals(headers.getFirst(HEADER_TRACE))) { actionLog.trace = true; } Response response = new InvocationImpl(controller, interceptors, request, webContext).proceed(); sessionManager.save(request, response); responseHandler.handle((ResponseImpl) response, exchange, request); } catch (Throwable e) { logManager.logError(e); errorHandler.handleError(e, exchange, request); } finally { webContext.cleanup(); logManager.end("=== http transaction end ==="); } } }