package core.framework.impl.web; import core.framework.api.util.Charsets; import core.framework.impl.web.request.RequestBodyReader; import io.undertow.server.HttpHandler; import io.undertow.server.HttpServerExchange; import io.undertow.server.handlers.form.FormDataParser; import io.undertow.server.handlers.form.FormParserFactory; import io.undertow.util.HttpString; import io.undertow.util.Methods; import org.xnio.channels.StreamSourceChannel; /** * @author neo */ class HTTPServerIOHandler implements HttpHandler { private final FormParserFactory formParserFactory; private final HTTPServerHandler handler; HTTPServerIOHandler(HTTPServerHandler handler) { this.handler = handler; FormParserFactory.Builder builder = FormParserFactory.builder(); builder.setDefaultCharset(Charsets.UTF_8.name()); formParserFactory = builder.build(); } @Override public void handleRequest(HttpServerExchange exchange) throws Exception { if (hasBody(exchange)) { // parse body early, not process until body is read (e.g. for chunked), to save one blocking thread during read FormDataParser parser = formParserFactory.createParser(exchange); if (parser != null) { parser.parse(handler); return; } RequestBodyReader reader = new RequestBodyReader(exchange, handler); StreamSourceChannel channel = exchange.getRequestChannel(); reader.read(channel); // channel will be null if getRequestChannel() is already called, but here should not be that case if (!reader.complete()) { channel.getReadSetter().set(reader); channel.resumeReads(); return; } } exchange.dispatch(handler); } private boolean hasBody(HttpServerExchange exchange) { int length = (int) exchange.getRequestContentLength(); if (length == 0) return false; // if body is empty, skip reading HttpString method = exchange.getRequestMethod(); return Methods.POST.equals(method) || Methods.PUT.equals(method); } }