Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

router plugins support springboot3 & fix an issue where inputstream is sometimes lost. #1691

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (C) 2023-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -32,7 +32,7 @@ public class LaneTestEntity implements Serializable {
private final boolean enabled;

/**
* 构造方法
* constructor
*
* @param id id
* @param enabled enabled
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (C) 2023-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -53,7 +53,7 @@ public class LaneTest {
private final boolean isExecuteSpringTest;

/**
* 构造方法
* constructor
*/
public LaneTest() {
baseUrl = "http://127.0.0.1:" + System.getProperty("controller.port", "28019") + "/controller/getLaneBy";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (C) 2022-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -41,7 +41,7 @@ public class ConsumerTest {
private final String dubboVersion;

/**
* 构造方法
* constructor
*/
public ConsumerTest() {
dubboVersion = System.getProperty("dubbo.running.version");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (C) 2022-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -38,7 +38,7 @@ public class SpringAndDubboTest {
private final String baseUrl;

/**
* 构造方法
* constructor
*/
public SpringAndDubboTest() {
baseUrl = "http://127.0.0.1:" + System.getProperty("controller.port", "28020") + "/consumer/";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022-2023 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (C) 2022-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -60,7 +60,7 @@ public class RouterTest {
private final boolean isExecuteSpringTest;

/**
* 构造方法
* constructor
*/
public RouterTest() throws InterruptedException {
testTagRouterBaseUrl =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (C) 2023-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -90,7 +90,7 @@ public class LaneTest {
private final boolean shouldTestWebclient;

/**
* 构造方法
* constructor
*/
public LaneTest() {
springCloudVersion = Optional.ofNullable(System.getenv("SPRING_CLOUD_VERSION")).orElse("Hoxton.RELEASE");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022-2023 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (C) 2022-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -92,7 +92,7 @@ public class TagRouterTest {
private final String springCloudVersion;

/**
* 构造方法
* constructor
*/
public TagRouterTest() throws InterruptedException {
springCloudVersion = Optional.ofNullable(System.getenv("SPRING_CLOUD_VERSION")).orElse("Hoxton.RELEASE");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2022 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (C) 2022-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,17 +18,23 @@

import io.sermant.core.plugin.agent.entity.ExecuteContext;
import io.sermant.core.utils.LogUtils;
import io.sermant.core.utils.ReflectUtils;
import io.sermant.flowcontrol.common.config.ConfigConst;
import io.sermant.flowcontrol.common.entity.FlowControlResult;
import io.sermant.flowcontrol.common.entity.HttpRequestEntity;
import io.sermant.flowcontrol.common.entity.RequestEntity.RequestType;
import io.sermant.flowcontrol.service.InterceptorSupporter;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
Expand All @@ -42,6 +48,28 @@
public class DispatcherServletInterceptor extends InterceptorSupporter {
private final String className = DispatcherServletInterceptor.class.getName();

private Function<Object, String> getRequestUri;

private Function<Object, String> getPathInfo;

private Function<Object, String> getMethod;

private Function<Object, Enumeration<String>> getHeaderNames;

private BiFunction<Object, String, String> getHeader;

private Function<Object, PrintWriter> getWriter;

private BiConsumer<Object, Integer> setStatus;

/**
* constructor
*/
public DispatcherServletInterceptor() {
super();
initFunction();
}

/**
* http request data conversion adapts to plugin -> service data transfer Note that this method is not
* extractable,Because host dependencies can only be loaded by this interceptor, pulling out results in classes not
Expand All @@ -50,18 +78,18 @@ public class DispatcherServletInterceptor extends InterceptorSupporter {
* @param request request
* @return HttpRequestEntity
*/
private Optional<HttpRequestEntity> convertToHttpEntity(HttpServletRequest request) {
private Optional<HttpRequestEntity> convertToHttpEntity(Object request) {
if (request == null) {
return Optional.empty();
}
String uri = request.getRequestURI();
String uri = getRequestUri.apply(request);
return Optional.of(new HttpRequestEntity.Builder()
.setRequestType(RequestType.SERVER)
.setPathInfo(request.getPathInfo())
.setPathInfo(getPathInfo.apply(request))
.setServletPath(uri)
.setHeaders(getHeaders(request))
.setMethod(request.getMethod())
.setServiceName(request.getHeader(ConfigConst.FLOW_REMOTE_SERVICE_NAME_HEADER_KEY))
.setMethod(getMethod.apply(request))
.setServiceName(getHeader.apply(request, ConfigConst.FLOW_REMOTE_SERVICE_NAME_HEADER_KEY))
.build());
}

Expand All @@ -71,12 +99,12 @@ private Optional<HttpRequestEntity> convertToHttpEntity(HttpServletRequest reque
* @param request request information
* @return headers
*/
private Map<String, String> getHeaders(HttpServletRequest request) {
final Enumeration<String> headerNames = request.getHeaderNames();
private Map<String, String> getHeaders(Object request) {
final Enumeration<String> headerNames = getHeaderNames.apply(request);
final Map<String, String> headers = new HashMap<>();
while (headerNames.hasMoreElements()) {
final String headerName = headerNames.nextElement();
headers.put(headerName, request.getHeader(headerName));
headers.put(headerName, getHeader.apply(request, headerName));
}
return Collections.unmodifiableMap(headers);
}
Expand All @@ -85,19 +113,19 @@ private Map<String, String> getHeaders(HttpServletRequest request) {
protected final ExecuteContext doBefore(ExecuteContext context) throws Exception {
LogUtils.printHttpRequestBeforePoint(context);
final Object[] allArguments = context.getArguments();
final HttpServletRequest argument = (HttpServletRequest) allArguments[0];
final Object request = allArguments[0];
final FlowControlResult result = new FlowControlResult();
final Optional<HttpRequestEntity> httpRequestEntity = convertToHttpEntity(argument);
final Optional<HttpRequestEntity> httpRequestEntity = convertToHttpEntity(request);
if (!httpRequestEntity.isPresent()) {
return context;
}
chooseHttpService().onBefore(className, httpRequestEntity.get(), result);
if (result.isSkip()) {
context.skip(null);
final HttpServletResponse response = (HttpServletResponse) allArguments[1];
final Object response = allArguments[1];
if (response != null) {
response.setStatus(result.getResponse().getCode());
response.getWriter().print(result.buildResponseMsg());
setStatus.accept(response, result.getResponse().getCode());
getWriter.apply(response).print(result.buildResponseMsg());
}
}
return context;
Expand All @@ -116,4 +144,75 @@ protected final ExecuteContext doThrow(ExecuteContext context) {
LogUtils.printHttpRequestOnThrowPoint(context);
return context;
}

private String getRequestUri(Object httpServletRequest) {
return getString(httpServletRequest, "getRequestURI");
}

private String getPathInfo(Object httpServletRequest) {
return getString(httpServletRequest, "getPathInfo");
}

private String getMethod(Object httpServletRequest) {
return getString(httpServletRequest, "getMethod");
}

private Enumeration<String> getHeaderNames(Object httpServletRequest) {
return (Enumeration<String>) ReflectUtils.invokeMethodWithNoneParameter(httpServletRequest, "getHeaderNames")
.orElse(null);
}

private String getHeader(Object httpServletRequest, String key) {
return (String) ReflectUtils.invokeMethod(httpServletRequest, "getHeader", new Class[]{String.class},
new Object[]{key}).orElse(null);
}

private PrintWriter getWriter(Object httpServletRequest) {
return (PrintWriter) ReflectUtils.invokeMethodWithNoneParameter(httpServletRequest, "getWriter")
.orElse(null);
}

private void setStatus(Object httpServletResponse, int code) {
ReflectUtils.invokeMethod(httpServletResponse, "setStatus", new Class[]{int.class}, new Object[]{code});
}

private String getString(Object object, String method) {
return (String) ReflectUtils.invokeMethodWithNoneParameter(object, method).orElse(null);
}

private void initFunction() {
boolean canLoadLowVersion = canLoadLowVersion();
if (canLoadLowVersion) {
getRequestUri = obj -> ((HttpServletRequest) obj).getRequestURI();
getPathInfo = obj -> ((HttpServletRequest) obj).getPathInfo();
getMethod = obj -> ((HttpServletRequest) obj).getMethod();
getHeaderNames = obj -> ((HttpServletRequest) obj).getHeaderNames();
getHeader = (obj, key) -> ((HttpServletRequest) obj).getHeader(key);
getWriter = obj -> {
try {
return ((HttpServletResponse) obj).getWriter();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
};
setStatus = (obj, code) -> ((HttpServletResponse) obj).setStatus(code);
} else {
getRequestUri = this::getRequestUri;
getPathInfo = this::getPathInfo;
getMethod = this::getMethod;
getHeaderNames = this::getHeaderNames;
getHeader = this::getHeader;
getWriter = this::getWriter;
setStatus = this::setStatus;
}
}

private boolean canLoadLowVersion() {
try {
Class.forName(HttpServletRequest.class.getCanonicalName());
} catch (NoClassDefFoundError | ClassNotFoundException error) {
return false;
}
return true;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (C) 2022-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -66,7 +66,7 @@ public class UrlInterceptor extends AbstractInterceptor {
private Set<String> supportRules;

/**
* 构造方法
* constructor
*/
public UrlInterceptor() {
config = PluginConfigManager.getPluginConfig(LoadbalancerConfig.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (C) 2022-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -32,7 +32,7 @@ public class ClientFactoryDeclarer extends AbstractDeclarer {
private static final String METHOD_NAME = "getInstance";

/**
* 构造方法
* constructor
*/
public ClientFactoryDeclarer() {
super(ENHANCE_CLASS, INTERCEPT_CLASS, METHOD_NAME);
Expand Down
Loading
Loading