处理options请求,解决跨域问题

This commit is contained in:
aoshiguchen
2022-07-30 15:55:57 +08:00
parent af3012478b
commit 4eb344fe94
29 changed files with 347 additions and 92 deletions
@@ -12,12 +12,11 @@
*/
package fun.asgc.neutrino.core.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import fun.asgc.neutrino.core.web.HttpResponseEntry;
import fun.asgc.neutrino.core.web.context.HttpContextHolder;
import fun.asgc.neutrino.core.web.context.HttpResponseWrapper;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.*;
import org.apache.commons.lang3.exception.ExceptionUtils;
@@ -28,28 +27,38 @@ import org.apache.commons.lang3.exception.ExceptionUtils;
*/
public class HttpServerUtil {
public static void send404Response(ChannelHandlerContext context, String url) {
public static void sendResponse(HttpResponseStatus status) {
sendResponse(status, null);
}
public static void sendResponse(HttpResponseStatus status, ByteBuf content) {
HttpResponseWrapper httpResponseWrapper = HttpContextHolder.getHttpResponseWrapper();
httpResponseWrapper.setStatus(status);
if (null != content) {
httpResponseWrapper.setContent(content);
}
httpResponseWrapper.writeAndFlush();
}
public static void send404Response(String url) {
String res = String.format("404 未找到指定资源: %s", url);
FullHttpResponse fullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND, Unpooled.wrappedBuffer(res.getBytes()));
fullHttpResponse.headers().add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON);
context.writeAndFlush(fullHttpResponse).addListener(ChannelFutureListener.CLOSE);
sendResponse(HttpResponseStatus.NOT_FOUND, Unpooled.wrappedBuffer(res.getBytes()));
}
public static void send500Response(ChannelHandlerContext context, Throwable throwable) {
public static void send500Response(Throwable throwable) {
String res = String.format("500 服务异常: %s", ExceptionUtils.getStackTrace(throwable));
FullHttpResponse fullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR, Unpooled.wrappedBuffer(res.getBytes()));
fullHttpResponse.headers().add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON);
context.writeAndFlush(fullHttpResponse).addListener(ChannelFutureListener.CLOSE);
sendResponse(HttpResponseStatus.INTERNAL_SERVER_ERROR, Unpooled.wrappedBuffer(res.getBytes()));
}
public static void send200Response(ChannelHandlerContext context, Object o) {
public static void send200Response(Object o) {
String res = String.valueOf(o);
if (null != o && !TypeUtil.isNormalBasicType(o.getClass())) {
res = JSONObject.toJSONString(o);
}
FullHttpResponse fullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(res.getBytes()));
fullHttpResponse.headers().add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON);
context.writeAndFlush(fullHttpResponse).addListener(ChannelFutureListener.CLOSE);
HttpResponseWrapper httpResponseWrapper = HttpContextHolder.getHttpResponseWrapper();
httpResponseWrapper.setContent(Unpooled.wrappedBuffer(res.getBytes()));
httpResponseWrapper.headers().add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON);
httpResponseWrapper.writeAndFlush();
}
}
@@ -29,7 +29,7 @@ import fun.asgc.neutrino.core.util.StringUtil;
* @date: 2022/7/15
*/
public enum HttpMethod {
GET,POST;
GET,POST,OPTIONS;
public static HttpMethod of(String method) {
if (StringUtil.isEmpty(method)) {
@@ -31,7 +31,8 @@ import fun.asgc.neutrino.core.util.*;
import fun.asgc.neutrino.core.web.annotation.RequestBody;
import fun.asgc.neutrino.core.web.annotation.RequestParam;
import fun.asgc.neutrino.core.web.context.HttpContextHolder;
import fun.asgc.neutrino.core.web.context.HttpRequestParser;
import fun.asgc.neutrino.core.web.context.HttpRequestWrapper;
import fun.asgc.neutrino.core.web.context.HttpResponseWrapper;
import fun.asgc.neutrino.core.web.context.WebContextHolder;
import fun.asgc.neutrino.core.web.interceptor.*;
import fun.asgc.neutrino.core.web.router.DefaultHttpRouter;
@@ -70,21 +71,26 @@ public class HttpRequestHandler {
public void handle() {
ChannelHandlerContext context = HttpContextHolder.getChannelHandlerContext();
HttpRequestParser requestParser = HttpContextHolder.getHttpRequestParser();
HttpRequestWrapper requestParser = HttpContextHolder.getHttpRequestWrapper();
log.info("HttpRequest method:{} url:{} query:{}", requestParser.getMethod().name(), requestParser.getUrl(), requestParser.getQueryParamMap());
try {
String routePath = requestParser.getRoutePath();
HttpMethod httpMethod = HttpMethod.of(requestParser.getMethod().name());
if (httpMethod == HttpMethod.OPTIONS) {
HttpServerUtil.sendResponse(HttpResponseStatus.OK);
return;
}
HttpRouteResult httpRouteResult = defaultHttpRouter.route(new HttpRouteParam().setMethod(httpMethod).setUrl(routePath));
if (null == httpRouteResult) {
HttpServerUtil.send404Response(context, requestParser.getUrl());
HttpServerUtil.send404Response(requestParser.getUrl());
return;
}
HttpContextHolder.setInterceptorList(getInterceptorsForPath(httpRouteResult.getPageRoute()));
if (HttpRouterType.METHOD == httpRouteResult.getType()) {
if (!preHandle(context, requestParser, httpRouteResult.getPageRoute(), httpRouteResult.getMethod())) {
if (!preHandle(httpRouteResult.getPageRoute(), httpRouteResult.getMethod())) {
HttpServerUtil.sendResponse(HttpResponseStatus.UNAUTHORIZED);
return;
}
@@ -98,14 +104,16 @@ public class HttpRequestHandler {
if (null != invokeResult && !TypeUtil.isNormalBasicType(invokeResult.getClass())) {
res = JSONObject.toJSONString(invokeResult);
}
FullHttpResponse fullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(res.getBytes()));
fullHttpResponse.headers().add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON);
context.writeAndFlush(fullHttpResponse).addListener(ChannelFutureListener.CLOSE);
postHandle(context, requestParser, httpRouteResult.getPageRoute(), httpRouteResult.getMethod());
postHandle(httpRouteResult.getPageRoute(), httpRouteResult.getMethod());
HttpResponseWrapper httpResponseWrapper = HttpContextHolder.getHttpResponseWrapper();
httpResponseWrapper.setContent(Unpooled.wrappedBuffer(res.getBytes()));
httpResponseWrapper.headers().add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON);
httpResponseWrapper.writeAndFlush();
return;
} else if(HttpRouterType.PAGE == httpRouteResult.getType()) {
if (!preHandle(context, requestParser, httpRouteResult.getPageRoute(), null)) {
if (!preHandle(httpRouteResult.getPageRoute(), null)) {
return;
}
@@ -114,33 +122,35 @@ public class HttpRequestHandler {
if (mimeType.startsWith("text/")) {
mimeType += ";charset=utf-8";
}
FullHttpResponse fullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(FileUtil.readBytes(httpRouteResult.getPageLocation())));
fullHttpResponse.headers().add(HttpHeaderNames.CONTENT_TYPE, mimeType);
fullHttpResponse.headers().add(HttpHeaderNames.CONTENT_LANGUAGE, "zh-CN");
fullHttpResponse.headers().add(HttpHeaderNames.SERVER, MetaDataConstant.SERVER_VS);
fullHttpResponse.headers().add(HttpHeaderNames.DATE, new Date());
context.writeAndFlush(fullHttpResponse).addListener(ChannelFutureListener.CLOSE);
postHandle(context, requestParser, httpRouteResult.getPageRoute(), null);
postHandle(httpRouteResult.getPageRoute(), null);
HttpResponseWrapper httpResponseWrapper = HttpContextHolder.getHttpResponseWrapper();
httpResponseWrapper.setContent(Unpooled.wrappedBuffer(FileUtil.readBytes(httpRouteResult.getPageLocation())));
httpResponseWrapper.headers().add(HttpHeaderNames.CONTENT_TYPE, mimeType);
httpResponseWrapper.headers().add(HttpHeaderNames.CONTENT_LANGUAGE, "zh-CN");
httpResponseWrapper.headers().add(HttpHeaderNames.SERVER, MetaDataConstant.SERVER_VS);
httpResponseWrapper.headers().add(HttpHeaderNames.DATE, new Date());
httpResponseWrapper.writeAndFlush();
return;
} else {
HttpServerUtil.send404Response(context, requestParser.getUrl());
HttpServerUtil.send404Response(requestParser.getUrl());
return;
}
} catch (Throwable e) {
Object res = exceptionHandler(e);
if (null != res) {
HttpServerUtil.send200Response(context, res);
HttpServerUtil.send200Response(res);
}
} finally {
release();
}
}
private boolean preHandle(ChannelHandlerContext context, HttpRequestParser requestParser, String route, Method targetMethod) throws Exception {
private boolean preHandle(String route, Method targetMethod) throws Exception {
if (!CollectionUtil.isEmpty(HttpContextHolder.getInterceptorList())) {
for (HandlerInterceptor handlerInterceptor : HttpContextHolder.getInterceptorList()) {
if (!handlerInterceptor.preHandle(context, requestParser, route, targetMethod)) {
if (!handlerInterceptor.preHandle(HttpContextHolder.getHttpRequestWrapper(), HttpContextHolder.getHttpResponseWrapper(), route, targetMethod)) {
return Boolean.FALSE;
}
}
@@ -148,10 +158,18 @@ public class HttpRequestHandler {
return Boolean.TRUE;
}
private void postHandle(ChannelHandlerContext context, HttpRequestParser requestParser, String route, Method targetMethod) throws Exception {
private void postHandle(String route, Method targetMethod) throws Exception {
if (!CollectionUtil.isEmpty(HttpContextHolder.getInterceptorList())) {
for (HandlerInterceptor handlerInterceptor : HttpContextHolder.getInterceptorList()) {
handlerInterceptor.postHandle(context, requestParser, route, targetMethod);
handlerInterceptor.postHandle(HttpContextHolder.getHttpRequestWrapper(), HttpContextHolder.getHttpResponseWrapper(), route, targetMethod);
}
}
}
private void afterCompletion(String route, Method targetMethod) {
if (!CollectionUtil.isEmpty(HttpContextHolder.getInterceptorList())) {
for (HandlerInterceptor handlerInterceptor : HttpContextHolder.getInterceptorList()) {
handlerInterceptor.afterCompletion(HttpContextHolder.getHttpRequestWrapper(), HttpContextHolder.getHttpResponseWrapper(), route, targetMethod);
}
}
}
@@ -179,16 +197,16 @@ public class HttpRequestHandler {
ExceptionHandlerRegistry exceptionHandlerRegistry = WebContextHolder.getExceptionHandlerRegistry();
if (CollectionUtil.isEmpty(exceptionHandlerRegistry.getExceptionHandlerList())) {
log.error("Http处理异常", e);
HttpServerUtil.send500Response(HttpContextHolder.getChannelHandlerContext(), e);
HttpServerUtil.send500Response(e);
return null;
}
for (RestControllerExceptionHandler exceptionHandler : exceptionHandlerRegistry.getExceptionHandlerList()) {
if (exceptionHandler.support(e)) {
return exceptionHandler.handle(HttpContextHolder.getChannelHandlerContext(), HttpContextHolder.getHttpRequestParser(), e);
return exceptionHandler.handle(HttpContextHolder.getHttpRequestWrapper(), HttpContextHolder.getHttpResponseWrapper(), e);
}
}
log.error("Http处理异常", e);
HttpServerUtil.send500Response(HttpContextHolder.getChannelHandlerContext(), e);
HttpServerUtil.send500Response(e);
return null;
}
@@ -199,12 +217,12 @@ public class HttpRequestHandler {
Parameter parameter = method.getParameters()[i];
if (FullHttpRequest.class.isAssignableFrom(parameter.getType())) {
params[i] = HttpContextHolder.getFullHttpRequest();
} else if (HttpRequestParser.class.isAssignableFrom(parameter.getType())) {
params[i] = HttpContextHolder.getHttpRequestParser();
} else if (HttpRequestWrapper.class.isAssignableFrom(parameter.getType())) {
params[i] = HttpContextHolder.getHttpRequestWrapper();
} else if (ChannelHandlerContext.class.isAssignableFrom(parameter.getType())) {
params[i] = HttpContextHolder.getChannelHandlerContext();
} else if (parameter.isAnnotationPresent(RequestBody.class)) {
String bodyString = HttpContextHolder.getHttpRequestParser().getContentAsString();
String bodyString = HttpContextHolder.getHttpRequestWrapper().getContentAsString();
if (TypeUtil.isNormalBasicType(parameter.getType())) {
params[i] = TypeUtil.conversion(bodyString, parameter.getType());
} else {
@@ -215,7 +233,7 @@ public class HttpRequestHandler {
if (StringUtil.isEmpty(requestParam.value())) {
throw new RuntimeException(String.format("类:%s 方法:%s @RequestParam必须指定参数名称" ));
}
String val = HttpContextHolder.getHttpRequestParser().getParameter(requestParam.value());
String val = HttpContextHolder.getHttpRequestWrapper().getParameter(requestParam.value());
if (StringUtil.isEmpty(val)) {
if (requestParam.required()) {
throw new RuntimeException(String.format("类:%s 方法:%s 参数:%s 未指定" ));
@@ -231,7 +249,7 @@ public class HttpRequestHandler {
Object obj = parameter.getType().newInstance();
for (Field field : fields) {
String name = field.getName();
Object value = TypeUtil.conversion(HttpContextHolder.getHttpRequestParser().getParameter(name), field.getType());
Object value = TypeUtil.conversion(HttpContextHolder.getHttpRequestWrapper().getParameter(name), field.getType());
ReflectUtil.setFieldValue(field, obj, value);
}
params[i] = obj;
@@ -93,7 +93,7 @@ public class WebApplicationServer implements ApplicationRunner {
fullHttpResponse.headers().add(HttpHeaderNames.CONTENT_TYPE, "image/x-icon");
context.writeAndFlush(fullHttpResponse).addListener(ChannelFutureListener.CLOSE);
} else {
HttpServerUtil.send404Response(context, uri);
HttpServerUtil.send404Response(uri);
}
}
});
@@ -22,8 +22,9 @@
package fun.asgc.neutrino.core.web.context;
import fun.asgc.neutrino.core.web.interceptor.HandlerInterceptor;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.*;
import java.util.List;
@@ -33,13 +34,14 @@ import java.util.List;
* @date: 2022/7/22
*/
public abstract class HttpContextHolder {
private static final ThreadLocal<HttpRequestParser> httpRequestParserHolder = new ThreadLocal<>();
private static final ThreadLocal<HttpRequestWrapper> httpRequestWrapperHolder = new ThreadLocal<>();
private static final ThreadLocal<HttpResponseWrapper> httpResponseWrapperHolder = new ThreadLocal<>();
private static ThreadLocal<FullHttpRequest> fullHttpRequestHolder = new ThreadLocal<>();
private static ThreadLocal<ChannelHandlerContext> channelHandlerContextHolder = new ThreadLocal<>();
private static ThreadLocal<List<HandlerInterceptor>> interceptorListHolder = new ThreadLocal<>();
public static void remove() {
httpRequestParserHolder.remove();
httpRequestWrapperHolder.remove();
fullHttpRequestHolder.remove();
channelHandlerContextHolder.remove();
interceptorListHolder.remove();
@@ -47,7 +49,11 @@ public abstract class HttpContextHolder {
public static void setFullHttpRequest(FullHttpRequest request) {
fullHttpRequestHolder.set(request);
httpRequestParserHolder.set(HttpRequestParser.create(request));
httpRequestWrapperHolder.set(HttpRequestWrapper.create(request));
}
public static void setFullHttpResponseWrapper() {
httpResponseWrapperHolder.set(HttpResponseWrapper.create());
}
public static void setChannelHandlerContext(ChannelHandlerContext context) {
@@ -62,8 +68,12 @@ public abstract class HttpContextHolder {
return interceptorListHolder.get();
}
public static HttpRequestParser getHttpRequestParser() {
return httpRequestParserHolder.get();
public static HttpRequestWrapper getHttpRequestWrapper() {
return httpRequestWrapperHolder.get();
}
public static HttpResponseWrapper getHttpResponseWrapper() {
return httpResponseWrapperHolder.get();
}
public static FullHttpRequest getFullHttpRequest() {
@@ -77,5 +87,6 @@ public abstract class HttpContextHolder {
public static void init(ChannelHandlerContext context, FullHttpRequest request) {
setChannelHandlerContext(context);
setFullHttpRequest(request);
setFullHttpResponseWrapper();
}
}
@@ -39,14 +39,14 @@ import java.util.function.Function;
* @author: aoshiguchen
* @date: 2022/7/22
*/
public class HttpRequestParser {
public class HttpRequestWrapper {
private FullHttpRequest request;
private String url;
private String queryString;
private Map<String, String> queryParamMap = null;
private String routePath;
private HttpRequestParser(FullHttpRequest request) {
private HttpRequestWrapper(FullHttpRequest request) {
this.request = request;
this.url = request.uri();
this.queryString = "";
@@ -61,8 +61,8 @@ public class HttpRequestParser {
this.routePath = getRoutePath(url);
}
public static HttpRequestParser create(FullHttpRequest request) {
return new HttpRequestParser(request);
public static HttpRequestWrapper create(FullHttpRequest request) {
return new HttpRequestWrapper(request);
}
public String getUrl() {
@@ -0,0 +1,70 @@
/**
* 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.context;
import fun.asgc.neutrino.core.util.Assert;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.handler.codec.http.*;
/**
*
* @author: aoshiguchen
* @date: 2022/7/30
*/
public class HttpResponseWrapper {
private HttpResponseStatus status;
private HttpHeaders httpHeaders;
private ByteBuf content;
private HttpResponseWrapper() {
this.status = HttpResponseStatus.OK;
this.httpHeaders = new DefaultHttpHeaders();
this.content = Unpooled.EMPTY_BUFFER;
}
public HttpHeaders headers() {
return httpHeaders;
}
public void setContent(ByteBuf content) {
this.content = content;
}
public void setStatus(HttpResponseStatus status) {
Assert.notNull(status, "http响应状态码不能为空!");
this.status = status;
}
public void writeAndFlush() {
FullHttpResponse fullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, content);
fullHttpResponse.headers().add(httpHeaders);
HttpContextHolder.getChannelHandlerContext().writeAndFlush(fullHttpResponse).addListener(ChannelFutureListener.CLOSE);
}
public static HttpResponseWrapper create() {
return new HttpResponseWrapper();
}
}
@@ -21,7 +21,8 @@
*/
package fun.asgc.neutrino.core.web.interceptor;
import fun.asgc.neutrino.core.web.context.HttpRequestParser;
import fun.asgc.neutrino.core.web.context.HttpRequestWrapper;
import fun.asgc.neutrino.core.web.context.HttpResponseWrapper;
import io.netty.channel.ChannelHandlerContext;
import java.lang.reflect.Method;
@@ -32,10 +33,13 @@ import java.lang.reflect.Method;
* @date: 2022/7/27
*/
public interface HandlerInterceptor {
default boolean preHandle(ChannelHandlerContext context, HttpRequestParser requestParser, String route, Method targetMethod) throws Exception {
default boolean preHandle(HttpRequestWrapper requestParser, HttpResponseWrapper responseWrapper, String route, Method targetMethod) throws Exception {
return true;
}
default void postHandle(ChannelHandlerContext context, HttpRequestParser requestParser, String route, Method targetMethod) throws Exception {
default void postHandle(HttpRequestWrapper requestParser, HttpResponseWrapper responseWrapper, String route, Method targetMethod) throws Exception {
}
default void afterCompletion(HttpRequestWrapper requestParser, HttpResponseWrapper responseWrapper, String route, Method targetMethod) {
}
}
@@ -22,7 +22,8 @@
package fun.asgc.neutrino.core.web.interceptor;
import fun.asgc.neutrino.core.web.PathMatcher;
import fun.asgc.neutrino.core.web.context.HttpRequestParser;
import fun.asgc.neutrino.core.web.context.HttpRequestWrapper;
import fun.asgc.neutrino.core.web.context.HttpResponseWrapper;
import io.netty.channel.ChannelHandlerContext;
import org.apache.commons.lang3.ObjectUtils;
@@ -100,11 +101,11 @@ public class MappedInterceptor {
}
}
public boolean preHandle(ChannelHandlerContext context, HttpRequestParser requestParser, String route, Method targetMethod) throws Exception {
return this.interceptor.preHandle(context, requestParser, route, targetMethod);
public boolean preHandle(HttpRequestWrapper requestParser, HttpResponseWrapper responseWrapper, String route, Method targetMethod) throws Exception {
return this.interceptor.preHandle(requestParser, responseWrapper, route, targetMethod);
}
public void postHandle(ChannelHandlerContext context, HttpRequestParser requestParser, String route, Method targetMethod) throws Exception {
this.interceptor.postHandle(context, requestParser, route, targetMethod);
public void postHandle(HttpRequestWrapper requestParser, HttpResponseWrapper responseWrapper, String route, Method targetMethod) throws Exception {
this.interceptor.postHandle(requestParser, responseWrapper, route, targetMethod);
}
}
@@ -21,7 +21,7 @@
*/
package fun.asgc.neutrino.core.web.interceptor;
import fun.asgc.neutrino.core.web.context.HttpRequestParser;
import fun.asgc.neutrino.core.web.context.HttpRequestWrapper;
import io.netty.channel.ChannelHandlerContext;
import java.lang.reflect.Method;
@@ -41,5 +41,5 @@ public interface RestControllerAdviceHandler {
* @param res
* @return
*/
Object advice(ChannelHandlerContext context, HttpRequestParser requestParser, String route, Method targetMethod, Object res);
Object advice(ChannelHandlerContext context, HttpRequestWrapper requestParser, String route, Method targetMethod, Object res);
}
@@ -21,7 +21,8 @@
*/
package fun.asgc.neutrino.core.web.interceptor;
import fun.asgc.neutrino.core.web.context.HttpRequestParser;
import fun.asgc.neutrino.core.web.context.HttpRequestWrapper;
import fun.asgc.neutrino.core.web.context.HttpResponseWrapper;
import io.netty.channel.ChannelHandlerContext;
/**
@@ -44,5 +45,5 @@ public interface RestControllerExceptionHandler {
* @param e
* @return
*/
Object handle(ChannelHandlerContext context, HttpRequestParser requestParser, Throwable e);
Object handle(HttpRequestWrapper requestParser, HttpResponseWrapper responseWrapper, Throwable e);
}
@@ -21,7 +21,8 @@
*/
package fun.asgc.neutrino.core.web.test1;
import fun.asgc.neutrino.core.web.context.HttpRequestParser;
import fun.asgc.neutrino.core.web.context.HttpRequestWrapper;
import fun.asgc.neutrino.core.web.context.HttpResponseWrapper;
import fun.asgc.neutrino.core.web.interceptor.HandlerInterceptor;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
@@ -38,15 +39,15 @@ public class BaseAuthInterceptor implements HandlerInterceptor {
/**
* 登录验证
* @param context
* @param requestParser
* @param responseWrapper
* @param route
* @param targetMethod
* @return
* @throws Exception
*/
@Override
public boolean preHandle(ChannelHandlerContext context, HttpRequestParser requestParser, String route, Method targetMethod) throws Exception {
public boolean preHandle(HttpRequestWrapper requestParser, HttpResponseWrapper responseWrapper, String route, Method targetMethod) throws Exception {
// 登录验证
String authorize = requestParser.getHeaderValue("Authorize");
if (!"123abc".equals(authorize)) {
@@ -56,7 +57,7 @@ public class BaseAuthInterceptor implements HandlerInterceptor {
}
@Override
public void postHandle(ChannelHandlerContext context, HttpRequestParser requestParser, String route, Method targetMethod) throws Exception {
public void postHandle(HttpRequestWrapper requestParser, HttpResponseWrapper responseWrapper, String route, Method targetMethod) throws Exception {
}
}
@@ -21,7 +21,7 @@
*/
package fun.asgc.neutrino.core.web.test1;
import fun.asgc.neutrino.core.web.context.HttpRequestParser;
import fun.asgc.neutrino.core.web.context.HttpRequestWrapper;
import fun.asgc.neutrino.core.web.interceptor.RestControllerAdviceHandler;
import io.netty.channel.ChannelHandlerContext;
@@ -35,7 +35,7 @@ import java.lang.reflect.Method;
public class GlobalAdviceHandler implements RestControllerAdviceHandler {
@Override
public Object advice(ChannelHandlerContext context, HttpRequestParser requestParser, String route, Method targetMethod, Object res) {
public Object advice(ChannelHandlerContext context, HttpRequestWrapper requestParser, String route, Method targetMethod, Object res) {
if (res instanceof JsonResult) {
return res;
}
@@ -21,7 +21,8 @@
*/
package fun.asgc.neutrino.core.web.test1;
import fun.asgc.neutrino.core.web.context.HttpRequestParser;
import fun.asgc.neutrino.core.web.context.HttpRequestWrapper;
import fun.asgc.neutrino.core.web.context.HttpResponseWrapper;
import fun.asgc.neutrino.core.web.interceptor.RestControllerExceptionHandler;
import io.netty.channel.ChannelHandlerContext;
import org.apache.commons.lang3.exception.ExceptionUtils;
@@ -34,7 +35,7 @@ import org.apache.commons.lang3.exception.ExceptionUtils;
public class GlobalExceptionHandler implements RestControllerExceptionHandler {
@Override
public Object handle(ChannelHandlerContext context, HttpRequestParser requestParser, Throwable e) {
public Object handle(HttpRequestWrapper requestParser, HttpResponseWrapper responseWrapper, Throwable e) {
if (e instanceof UserNotLoginException) {
return new JsonResult<>()
.setCode(101)
@@ -45,13 +45,13 @@ public class TestController {
@GetMapping("hello")
public String hello() {
System.out.println("拿到参数 a = " + HttpContextHolder.getHttpRequestParser().getParameterForInteger("a"));
System.out.println("拿到参数 a = " + HttpContextHolder.getHttpRequestWrapper().getParameterForInteger("a"));
return testService.hello();
}
@GetMapping("add")
public Integer add(@RequestParam("x") int x, @RequestParam("y") int y, Param1 p) {
log.info("另一种取参方式 msg:{}", HttpContextHolder.getHttpRequestParser().getParameterForString("msg"));
log.info("另一种取参方式 msg:{}", HttpContextHolder.getHttpRequestWrapper().getParameterForString("msg"));
log.info("p : {}", JSONObject.toJSONString(p));
return x + y;
}
+1 -1
View File
@@ -1,5 +1,5 @@
module.exports = {
NODE_ENV: '"development"',
ENV_CONFIG: '"dev"',
BASE_API: '"https://api-dev"'
BASE_API: '"http://localhost:8080"'
}
+1
View File
@@ -7,6 +7,7 @@
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"build:dev": "cross-env NODE_ENV=dev env_config=dev node build/build.js",
"build:prod": "cross-env NODE_ENV=production env_config=prod node build/build.js",
"build:sit": "cross-env NODE_ENV=production env_config=sit node build/build.js",
"lint": "eslint --ext .js,.vue src",
+7
View File
@@ -30,3 +30,10 @@ export function updateUser(data) {
data
})
}
export function hello() {
return request({
url: '/test1/hello',
method: 'GET'
})
}
@@ -85,7 +85,7 @@
</template>
<script>
import { fetchList, createUser, updateUser } from '@/api/user'
import { fetchList, createUser, updateUser, hello } from '@/api/user'
import waves from '@/directive/waves' // 水波纹指令
import { parseTime } from '@/utils'
@@ -175,6 +175,7 @@
methods: {
getList() {
this.listLoading = true
hello()
fetchList(this.listQuery).then(response => {
this.list = response.data.items
this.total = response.data.total
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package fun.asgc.neutrino.proxy.server.config;
package fun.asgc.neutrino.proxy.server.base.proxy;
import fun.asgc.neutrino.core.annotation.Configuration;
import fun.asgc.neutrino.core.annotation.Value;
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package fun.asgc.neutrino.proxy.server.config;
package fun.asgc.neutrino.proxy.server.base.proxy;
import fun.asgc.neutrino.proxy.core.ProxyClientConfig;
import lombok.Data;
@@ -0,0 +1,42 @@
/**
* 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.proxy.server.base.rest;
import fun.asgc.neutrino.core.web.context.HttpRequestWrapper;
import fun.asgc.neutrino.core.web.context.HttpResponseWrapper;
import fun.asgc.neutrino.core.web.interceptor.HandlerInterceptor;
import java.lang.reflect.Method;
/**
* 鉴权拦截器
* @author: aoshiguchen
* @date: 2022/7/30
*/
public class BaseAuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpRequestWrapper requestParser, HttpResponseWrapper responseWrapper, String route, Method targetMethod) throws Exception {
return true;
}
}
@@ -0,0 +1,47 @@
/**
* 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.proxy.server.base.rest;
import fun.asgc.neutrino.core.web.context.HttpRequestWrapper;
import fun.asgc.neutrino.core.web.context.HttpResponseWrapper;
import fun.asgc.neutrino.core.web.interceptor.HandlerInterceptor;
import java.lang.reflect.Method;
/**
* 处理跨域问题
* @author: aoshiguchen
* @date: 2022/7/30
*/
public class CorsInterceptor implements HandlerInterceptor {
@Override
public void postHandle(HttpRequestWrapper requestParser, HttpResponseWrapper responseWrapper, String route, Method targetMethod) throws Exception {
responseWrapper.headers().add("Access-Control-Allow-Origin", "*");
responseWrapper.headers().add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
responseWrapper.headers().add("Access-Control-Max-Age", "86400");
responseWrapper.headers().add("Access-Control-Allow-Headers", "*");
responseWrapper.headers().add("Access-Control-Allow-Credentials", "true");
responseWrapper.headers().add("XDomainRequestAllowed", "1");
}
}
@@ -0,0 +1,42 @@
/**
* 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.proxy.server.base.rest;
import fun.asgc.neutrino.core.annotation.Configuration;
import fun.asgc.neutrino.core.web.config.WebMvcConfigurer;
import fun.asgc.neutrino.core.web.interceptor.InterceptorRegistry;
/**
*
* @author: aoshiguchen
* @date: 2022/7/30
*/
@Configuration
public class WebConfigurerAdapter implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new BaseAuthInterceptor())
.addPathPatterns("/**").excludePathPatterns("/**/*.html", "/**/*.js", "/**/*.ico");
registry.addInterceptor(new CorsInterceptor());
}
}
@@ -41,8 +41,8 @@ public class Test1Controller {
@GetMapping("hello")
public String hello() {
System.out.println("拿到参数 a = " + HttpContextHolder.getHttpRequestParser().getParameter("a"));
if ("aaa".equals(HttpContextHolder.getHttpRequestParser().getParameter("a"))) {
System.out.println("拿到参数 a = " + HttpContextHolder.getHttpRequestWrapper().getParameter("a"));
if ("aaa".equals(HttpContextHolder.getHttpRequestWrapper().getParameter("a"))) {
throw new RuntimeException("hhhh 异常了!");
}
return test1Service.hello();
@@ -31,7 +31,7 @@ import fun.asgc.neutrino.core.util.FileUtil;
import fun.asgc.neutrino.proxy.core.IdleCheckHandler;
import fun.asgc.neutrino.proxy.core.ProxyMessageDecoder;
import fun.asgc.neutrino.proxy.core.ProxyMessageEncoder;
import fun.asgc.neutrino.proxy.server.config.ProxyConfig;
import fun.asgc.neutrino.proxy.server.base.proxy.ProxyConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
@@ -24,7 +24,7 @@ package fun.asgc.neutrino.proxy.server.core;
import fun.asgc.neutrino.proxy.core.Constants;
import fun.asgc.neutrino.proxy.core.ProxyMessage;
import fun.asgc.neutrino.proxy.server.config.ProxyServerConfig;
import fun.asgc.neutrino.proxy.server.base.proxy.ProxyServerConfig;
import fun.asgc.neutrino.proxy.server.util.ProxyChannelManager;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
@@ -27,10 +27,9 @@ import fun.asgc.neutrino.core.annotation.Autowired;
import fun.asgc.neutrino.core.annotation.Component;
import fun.asgc.neutrino.core.annotation.Match;
import fun.asgc.neutrino.core.annotation.NonIntercept;
import fun.asgc.neutrino.core.util.BeanManager;
import fun.asgc.neutrino.proxy.core.*;
import fun.asgc.neutrino.proxy.server.config.ProxyConfig;
import fun.asgc.neutrino.proxy.server.config.ProxyServerConfig;
import fun.asgc.neutrino.proxy.server.base.proxy.ProxyConfig;
import fun.asgc.neutrino.proxy.server.base.proxy.ProxyServerConfig;
import fun.asgc.neutrino.proxy.server.core.BytesMetricsHandler;
import fun.asgc.neutrino.proxy.server.core.UserChannelHandler;
import fun.asgc.neutrino.proxy.server.util.ProxyChannelManager;
@@ -23,7 +23,7 @@
package fun.asgc.neutrino.proxy.server.util;
import fun.asgc.neutrino.proxy.core.Constants;
import fun.asgc.neutrino.proxy.server.config.ProxyServerConfig;
import fun.asgc.neutrino.proxy.server.base.proxy.ProxyServerConfig;
import io.netty.channel.Channel;
import io.netty.util.AttributeKey;