diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/HttpRequestHandler.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/HttpRequestHandler.java index cce72e2c..7240910a 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/HttpRequestHandler.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/HttpRequestHandler.java @@ -28,6 +28,8 @@ import fun.asgc.neutrino.core.annotation.NonIntercept; import fun.asgc.neutrino.core.constant.MetaDataConstant; import fun.asgc.neutrino.core.context.ApplicationConfig; import fun.asgc.neutrino.core.util.*; +import fun.asgc.neutrino.core.web.param.HttpContextHolder; +import fun.asgc.neutrino.core.web.param.HttpRequestParser; import fun.asgc.neutrino.core.web.router.DefaultHttpRouter; import fun.asgc.neutrino.core.web.router.HttpRouteParam; import fun.asgc.neutrino.core.web.router.HttpRouteResult; @@ -37,6 +39,7 @@ import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.*; import lombok.extern.slf4j.Slf4j; +import org.checkerframework.checker.units.qual.C; import java.util.Date; @@ -55,12 +58,16 @@ public class HttpRequestHandler { private DefaultHttpRouter defaultHttpRouter; private static volatile String httpContextPath; - public void handle(ChannelHandlerContext context, FullHttpRequest request) { - String routePath = getRoutePath(request.uri()); - HttpMethod httpMethod = HttpMethod.of(request.method().name()); + public void handle() { + ChannelHandlerContext context = HttpContextHolder.getChannelHandlerContext(); + HttpRequestParser requestParser = HttpContextHolder.getHttpRequestParser(); + log.info("HttpRequest method:{} url:{} query:{}", requestParser.getMethod().name(), requestParser.getUrl(), requestParser.getQueryParamMap()); + + String routePath = getRoutePath(requestParser.getUrl()); + HttpMethod httpMethod = HttpMethod.of(requestParser.getMethod().name()); HttpRouteResult httpRouteResult = defaultHttpRouter.route(new HttpRouteParam().setMethod(httpMethod).setUrl(routePath)); if (null == httpRouteResult) { - HttpServerUtil.send404Response(context, request.uri()); + HttpServerUtil.send404Response(context, requestParser.getUrl()); return; } if (HttpRouterType.METHOD == httpRouteResult.getType()) { @@ -92,7 +99,7 @@ public class HttpRequestHandler { return; } else { // TODO - HttpServerUtil.send404Response(context, request.uri()); + HttpServerUtil.send404Response(context, requestParser.getUrl()); return; } } diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/WebApplicationServer.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/WebApplicationServer.java index 21433e1b..b068cb97 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/WebApplicationServer.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/WebApplicationServer.java @@ -28,6 +28,7 @@ import fun.asgc.neutrino.core.annotation.Init; import fun.asgc.neutrino.core.context.ApplicationConfig; import fun.asgc.neutrino.core.context.ApplicationRunner; import fun.asgc.neutrino.core.util.*; +import fun.asgc.neutrino.core.web.param.HttpContextHolder; import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.Unpooled; import io.netty.channel.*; @@ -89,10 +90,12 @@ public class WebApplicationServer implements ApplicationRunner { pipeline.addLast(new SimpleChannelInboundHandler() { @Override protected void channelRead0(ChannelHandlerContext context, FullHttpRequest request) throws Exception { + HttpContextHolder.init(context, request); + String uri = request.uri(); log.debug("http request: {}", uri); if (uri.startsWith(http.getContextPath() + "/") || uri.equals(http.getContextPath())) { - httpRequestHandler.handle(context, request); + httpRequestHandler.handle(); } else if (uri.equals("/favicon.ico") && null != faviconBytes) { FullHttpResponse fullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(faviconBytes)); fullHttpResponse.headers().add(HttpHeaderNames.CONTENT_TYPE, "image/x-icon"); diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/param/HttpContextHolder.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/param/HttpContextHolder.java new file mode 100644 index 00000000..6586ee6f --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/param/HttpContextHolder.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.web.param; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.FullHttpRequest; + +/** + * + * @author: aoshiguchen + * @date: 2022/7/22 + */ +public abstract class HttpContextHolder { + private static final ThreadLocal httpRequestParserHolder = new ThreadLocal<>(); + private static ThreadLocal fullHttpRequestHolder = new ThreadLocal<>(); + private static ThreadLocal channelHandlerContextHolder = new ThreadLocal<>(); + + public static void remove() { + httpRequestParserHolder.remove(); + fullHttpRequestHolder.remove(); + channelHandlerContextHolder.remove(); + } + + public static void setFullHttpRequest(FullHttpRequest request) { + fullHttpRequestHolder.set(request); + httpRequestParserHolder.set(HttpRequestParser.create(request)); + } + + public static void setChannelHandlerContext(ChannelHandlerContext context) { + channelHandlerContextHolder.set(context); + } + + public static HttpRequestParser getHttpRequestParser() { + return httpRequestParserHolder.get(); + } + + public static FullHttpRequest getFullHttpRequest() { + return fullHttpRequestHolder.get(); + } + + public static ChannelHandlerContext getChannelHandlerContext() { + return channelHandlerContextHolder.get(); + } + + public static void init(ChannelHandlerContext context, FullHttpRequest request) { + setChannelHandlerContext(context); + setFullHttpRequest(request); + } +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/param/HttpRequestParser.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/param/HttpRequestParser.java new file mode 100644 index 00000000..9af6cb5a --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/param/HttpRequestParser.java @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.web.param; + +import fun.asgc.neutrino.core.util.LockUtil; +import fun.asgc.neutrino.core.util.StringUtil; +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.util.CharsetUtil; + +import java.util.HashMap; +import java.util.Map; + +/** + * Http请求解析器 + * @author: aoshiguchen + * @date: 2022/7/22 + */ +public class HttpRequestParser { + private FullHttpRequest request; + private String url; + private String queryString; + private Map queryParamMap = null; + + private HttpRequestParser(FullHttpRequest request) { + this.request = request; + this.url = request.uri(); + this.queryString = ""; + + int index = url.indexOf("?"); + if (index >= 0) { + if (index < url.length() - 1) { + this.queryString = url.substring(index + 1); + } + url = getUrl().substring(0, index); + } + } + + public static HttpRequestParser create(FullHttpRequest request) { + return new HttpRequestParser(request); + } + + public String getUrl() { + return url; + } + + public String getQueryString() { + return queryString; + } + + public Map getQueryParamMap() { + return LockUtil.doubleCheckProcessForNoException( + () -> null == queryParamMap, + this, + () -> { + queryParamMap = new HashMap<>(); + if (StringUtil.isEmpty(queryString)) { + return; + } + String[] params = queryString.split("&"); + for (String param : params) { + int index2 = param.indexOf("="); + String key = ""; + String val = ""; + if (index2 > 0) { + key = param.substring(0, index2); + if (index2 < param.length() - 1) { + val = param.substring(index2 + 1); + } + queryParamMap.put(key, val); + } + } + }, + () -> queryParamMap + ); + } + + public HttpMethod getMethod() { + return request.method(); + } + + public ByteBuf getContent() { + return request.content(); + } + + public String getContentAsString() { + return getContent().toString(CharsetUtil.UTF_8); + } +}