Develop refactor request context (#12331)
* Add RequestContext and RequestContextHolder. * build RequestContext when request start. * Refactor ClientAttributesFilter with RequestContext. * InstanceController get client ip from request context. * SubscribeServiceRequestHandler get app from requestcontext. * config http api support use request context get user, app and source ip. * Rename nacos request context filter. * Unified naming request get source ip by request context. * For checkstyle.
This commit is contained in:
parent
2aa9fc51bc
commit
2233e6556c
@ -18,6 +18,9 @@ package com.alibaba.nacos.config.server.utils;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.core.context.RequestContextHolder;
|
||||
import com.alibaba.nacos.core.utils.WebUtils;
|
||||
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@ -28,30 +31,24 @@ import javax.servlet.http.HttpServletRequest;
|
||||
*/
|
||||
public class RequestUtil {
|
||||
|
||||
private static final String X_REAL_IP = "X-Real-IP";
|
||||
|
||||
private static final String X_FORWARDED_FOR = "X-Forwarded-For";
|
||||
|
||||
private static final String X_FORWARDED_FOR_SPLIT_SYMBOL = ",";
|
||||
|
||||
public static final String CLIENT_APPNAME_HEADER = "Client-AppName";
|
||||
|
||||
/**
|
||||
* get real client ip
|
||||
*
|
||||
* <p>first use X-Forwarded-For header https://zh.wikipedia.org/wiki/X-Forwarded-For next nginx X-Real-IP last
|
||||
* {@link HttpServletRequest#getRemoteAddr()}
|
||||
* Get real client ip from context first, if no value, use
|
||||
* {@link com.alibaba.nacos.core.utils.WebUtils#getRemoteIp(HttpServletRequest)}.
|
||||
*
|
||||
* @param request {@link HttpServletRequest}
|
||||
* @return remote ip address.
|
||||
*/
|
||||
public static String getRemoteIp(HttpServletRequest request) {
|
||||
String xForwardedFor = request.getHeader(X_FORWARDED_FOR);
|
||||
if (!StringUtils.isBlank(xForwardedFor)) {
|
||||
return xForwardedFor.split(X_FORWARDED_FOR_SPLIT_SYMBOL)[0].trim();
|
||||
String remoteIp = RequestContextHolder.getContext().getBasicContext().getAddressContext().getSourceIp();
|
||||
if (StringUtils.isBlank(remoteIp)) {
|
||||
remoteIp = RequestContextHolder.getContext().getBasicContext().getAddressContext().getRemoteIp();
|
||||
}
|
||||
String nginxHeader = request.getHeader(X_REAL_IP);
|
||||
return StringUtils.isBlank(nginxHeader) ? request.getRemoteAddr() : nginxHeader;
|
||||
if (StringUtils.isBlank(remoteIp)) {
|
||||
remoteIp = WebUtils.getRemoteIp(request);
|
||||
}
|
||||
return remoteIp;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -61,7 +58,12 @@ public class RequestUtil {
|
||||
* @return may be return null
|
||||
*/
|
||||
public static String getAppName(HttpServletRequest request) {
|
||||
return request.getHeader(CLIENT_APPNAME_HEADER);
|
||||
String result = RequestContextHolder.getContext().getBasicContext().getApp();
|
||||
return isUnknownApp(result) ? request.getHeader(CLIENT_APPNAME_HEADER) : result;
|
||||
}
|
||||
|
||||
private static boolean isUnknownApp(String appName) {
|
||||
return StringUtils.isBlank(appName) || StringUtils.equalsIgnoreCase("unknown", appName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,8 +73,12 @@ public class RequestUtil {
|
||||
* @return may be return null
|
||||
*/
|
||||
public static String getSrcUserName(HttpServletRequest request) {
|
||||
String result = (String) request.getSession()
|
||||
.getAttribute(com.alibaba.nacos.plugin.auth.constant.Constants.Identity.IDENTITY_ID);
|
||||
IdentityContext identityContext = RequestContextHolder.getContext().getAuthContext().getIdentityContext();
|
||||
String result = StringUtils.EMPTY;
|
||||
if (null != identityContext) {
|
||||
result = (String) identityContext.getParameter(
|
||||
com.alibaba.nacos.plugin.auth.constant.Constants.Identity.IDENTITY_ID);
|
||||
}
|
||||
// If auth is disabled, get username from parameters by agreed key
|
||||
return StringUtils.isBlank(result) ? request.getParameter(Constants.USERNAME) : result;
|
||||
}
|
||||
|
@ -17,11 +17,13 @@
|
||||
package com.alibaba.nacos.config.server.utils;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.core.context.RequestContextHolder;
|
||||
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@ -32,8 +34,13 @@ class RequestUtilTest {
|
||||
|
||||
private static final String X_FORWARDED_FOR = "X-Forwarded-For";
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
RequestContextHolder.removeContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetRemoteIp() {
|
||||
void testGetRemoteIpFromRequest() {
|
||||
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
|
||||
|
||||
Mockito.when(request.getRemoteAddr()).thenReturn("127.0.0.1");
|
||||
@ -56,29 +63,33 @@ class RequestUtilTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetAppName() {
|
||||
void testGetAppNameFromContext() {
|
||||
RequestContextHolder.getContext().getBasicContext().setApp("contextApp");
|
||||
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
|
||||
Mockito.when(request.getHeader(eq(RequestUtil.CLIENT_APPNAME_HEADER))).thenReturn("test");
|
||||
assertEquals("contextApp", RequestUtil.getAppName(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetAppNameFromRequest() {
|
||||
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
|
||||
Mockito.when(request.getHeader(eq(RequestUtil.CLIENT_APPNAME_HEADER))).thenReturn("test");
|
||||
assertEquals("test", RequestUtil.getAppName(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetSrcUserNameV1() {
|
||||
void testGetSrcUserNameFromContext() {
|
||||
IdentityContext identityContext = new IdentityContext();
|
||||
identityContext.setParameter(com.alibaba.nacos.plugin.auth.constant.Constants.Identity.IDENTITY_ID, "test");
|
||||
RequestContextHolder.getContext().getAuthContext().setIdentityContext(identityContext);
|
||||
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
|
||||
HttpSession session = Mockito.mock(HttpSession.class);
|
||||
Mockito.when(request.getSession()).thenReturn(session);
|
||||
Mockito.when(session.getAttribute(eq(com.alibaba.nacos.plugin.auth.constant.Constants.Identity.IDENTITY_ID))).thenReturn("test");
|
||||
assertEquals("test", RequestUtil.getSrcUserName(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetSrcUserNameV2() {
|
||||
void testGetSrcUserNameFromRequest() {
|
||||
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
|
||||
HttpSession session = Mockito.mock(HttpSession.class);
|
||||
Mockito.when(request.getSession()).thenReturn(session);
|
||||
Mockito.when(session.getAttribute(eq(com.alibaba.nacos.plugin.auth.constant.Constants.Identity.IDENTITY_ID))).thenReturn(null);
|
||||
Mockito.when(request.getParameter(eq(Constants.USERNAME))).thenReturn("parameterName");
|
||||
assertEquals("parameterName", RequestUtil.getSrcUserName(request));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.common.utils.ExceptionUtil;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.core.code.ControllerMethodsCache;
|
||||
import com.alibaba.nacos.core.context.RequestContext;
|
||||
import com.alibaba.nacos.core.context.RequestContextHolder;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import com.alibaba.nacos.core.utils.WebUtils;
|
||||
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
|
||||
@ -120,11 +122,16 @@ public class AuthFilter implements Filter {
|
||||
Resource resource = protocolAuthService.parseResource(req, secured);
|
||||
IdentityContext identityContext = protocolAuthService.parseIdentity(req);
|
||||
boolean result = protocolAuthService.validateIdentity(identityContext, resource);
|
||||
RequestContext requestContext = RequestContextHolder.getContext();
|
||||
requestContext.getAuthContext().setIdentityContext(identityContext);
|
||||
requestContext.getAuthContext().setResource(resource);
|
||||
if (null == requestContext.getAuthContext().getAuthResult()) {
|
||||
requestContext.getAuthContext().setAuthResult(result);
|
||||
}
|
||||
if (!result) {
|
||||
// TODO Get reason of failure
|
||||
throw new AccessException("Validate Identity failed.");
|
||||
}
|
||||
injectIdentityId(req, identityContext);
|
||||
String action = secured.action().toString();
|
||||
result = protocolAuthService.validateAuthority(identityContext, new Permission(resource, action));
|
||||
if (!result) {
|
||||
@ -146,21 +153,4 @@ public class AuthFilter implements Filter {
|
||||
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Server failed, " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set identity id to request session, make sure some actual logic can get identity information.
|
||||
*
|
||||
* <p>May be replaced with whole identityContext.
|
||||
*
|
||||
* @param request http request
|
||||
* @param identityContext identity context
|
||||
*/
|
||||
private void injectIdentityId(HttpServletRequest request, IdentityContext identityContext) {
|
||||
String identityId = identityContext.getParameter(
|
||||
com.alibaba.nacos.plugin.auth.constant.Constants.Identity.IDENTITY_ID, StringUtils.EMPTY);
|
||||
request.getSession()
|
||||
.setAttribute(com.alibaba.nacos.plugin.auth.constant.Constants.Identity.IDENTITY_ID, identityId);
|
||||
request.getSession().setAttribute(com.alibaba.nacos.plugin.auth.constant.Constants.Identity.IDENTITY_CONTEXT,
|
||||
identityContext);
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ import com.alibaba.nacos.auth.GrpcProtocolAuthService;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.common.utils.ExceptionUtil;
|
||||
import com.alibaba.nacos.core.context.RequestContext;
|
||||
import com.alibaba.nacos.core.context.RequestContextHolder;
|
||||
import com.alibaba.nacos.core.remote.AbstractRequestFilter;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
|
||||
@ -75,6 +77,12 @@ public class RemoteRequestAuthFilter extends AbstractRequestFilter {
|
||||
Resource resource = protocolAuthService.parseResource(request, secured);
|
||||
IdentityContext identityContext = protocolAuthService.parseIdentity(request);
|
||||
boolean result = protocolAuthService.validateIdentity(identityContext, resource);
|
||||
RequestContext requestContext = RequestContextHolder.getContext();
|
||||
requestContext.getAuthContext().setIdentityContext(identityContext);
|
||||
requestContext.getAuthContext().setResource(resource);
|
||||
if (null == requestContext.getAuthContext().getAuthResult()) {
|
||||
requestContext.getAuthContext().setAuthResult(result);
|
||||
}
|
||||
if (!result) {
|
||||
// TODO Get reason of failure
|
||||
throw new AccessException("Validate Identity failed.");
|
||||
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.context;
|
||||
|
||||
import com.alibaba.nacos.core.context.addition.AuthContext;
|
||||
import com.alibaba.nacos.core.context.addition.BasicContext;
|
||||
import com.alibaba.nacos.core.context.addition.EngineContext;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Nacos request context.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public class RequestContext {
|
||||
|
||||
/**
|
||||
* Optional, the request id.
|
||||
* <ul>
|
||||
* <li>For HTTP request, the id not usage, will generate automatically.</li>
|
||||
* <li>For GRPC, the id is same with real request id.</li>
|
||||
* </ul>
|
||||
*/
|
||||
private String requestId;
|
||||
|
||||
/**
|
||||
* Request start timestamp.
|
||||
*/
|
||||
private final long requestTimestamp;
|
||||
|
||||
private final BasicContext basicContext;
|
||||
|
||||
private final EngineContext engineContext;
|
||||
|
||||
private final AuthContext authContext;
|
||||
|
||||
private final Map<String, Object> extensionContexts;
|
||||
|
||||
RequestContext(long requestTimestamp) {
|
||||
this.requestId = UUID.randomUUID().toString();
|
||||
this.requestTimestamp = requestTimestamp;
|
||||
this.basicContext = new BasicContext();
|
||||
this.engineContext = new EngineContext();
|
||||
this.authContext = new AuthContext();
|
||||
this.extensionContexts = new HashMap<>(1);
|
||||
}
|
||||
|
||||
public void setRequestId(String requestId) {
|
||||
this.requestId = requestId;
|
||||
}
|
||||
|
||||
public String getRequestId() {
|
||||
return requestId;
|
||||
}
|
||||
|
||||
public long getRequestTimestamp() {
|
||||
return requestTimestamp;
|
||||
}
|
||||
|
||||
public BasicContext getBasicContext() {
|
||||
return basicContext;
|
||||
}
|
||||
|
||||
public EngineContext getEngineContext() {
|
||||
return engineContext;
|
||||
}
|
||||
|
||||
public AuthContext getAuthContext() {
|
||||
return authContext;
|
||||
}
|
||||
|
||||
public Object getExtensionContext(String key) {
|
||||
return extensionContexts.get(key);
|
||||
}
|
||||
|
||||
public void addExtensionContext(String key, Object value) {
|
||||
extensionContexts.put(key, value);
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.context;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Holder for request context for each worker thread.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public class RequestContextHolder {
|
||||
|
||||
private static final Supplier<RequestContext> REQUEST_CONTEXT_FACTORY = () -> {
|
||||
long requestTimestamp = System.currentTimeMillis();
|
||||
return new RequestContext(requestTimestamp);
|
||||
};
|
||||
|
||||
private static final ThreadLocal<RequestContext> CONTEXT_HOLDER = ThreadLocal.withInitial(REQUEST_CONTEXT_FACTORY);
|
||||
|
||||
public static RequestContext getContext() {
|
||||
return CONTEXT_HOLDER.get();
|
||||
}
|
||||
|
||||
public static void removeContext() {
|
||||
CONTEXT_HOLDER.remove();
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.context.addition;
|
||||
|
||||
/**
|
||||
* Nacos request address information context.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public class AddressContext {
|
||||
|
||||
/**
|
||||
* Request source ip, it's the ip of the client, most situations are same with remoteIp.
|
||||
*/
|
||||
private String sourceIp;
|
||||
|
||||
/**
|
||||
* Request source port, it's the port of the client, most situations are same with remoteIp.
|
||||
*/
|
||||
private int sourcePort;
|
||||
|
||||
/**
|
||||
* Request connection ip, it should be got from the socket, which means the ip seen by nacos server.
|
||||
*/
|
||||
private String remoteIp;
|
||||
|
||||
/**
|
||||
* Request connection port, it should be got from the socket, which means the port seen by nacos server.
|
||||
*/
|
||||
private int remotePort;
|
||||
|
||||
/**
|
||||
* Request host, it's the host of the client, nullable when can't get it from request or connection.
|
||||
*/
|
||||
private String host;
|
||||
|
||||
public String getSourceIp() {
|
||||
return sourceIp;
|
||||
}
|
||||
|
||||
public void setSourceIp(String sourceIp) {
|
||||
this.sourceIp = sourceIp;
|
||||
}
|
||||
|
||||
public int getSourcePort() {
|
||||
return sourcePort;
|
||||
}
|
||||
|
||||
public void setSourcePort(int sourcePort) {
|
||||
this.sourcePort = sourcePort;
|
||||
}
|
||||
|
||||
public String getRemoteIp() {
|
||||
return remoteIp;
|
||||
}
|
||||
|
||||
public void setRemoteIp(String remoteIp) {
|
||||
this.remoteIp = remoteIp;
|
||||
}
|
||||
|
||||
public int getRemotePort() {
|
||||
return remotePort;
|
||||
}
|
||||
|
||||
public void setRemotePort(int remotePort) {
|
||||
this.remotePort = remotePort;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.context.addition;
|
||||
|
||||
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
|
||||
import com.alibaba.nacos.plugin.auth.api.Resource;
|
||||
|
||||
/**
|
||||
* Nacos auth context, store and transport some auth plugin information to handler or trace log.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public class AuthContext {
|
||||
|
||||
private IdentityContext identityContext;
|
||||
|
||||
private Resource resource;
|
||||
|
||||
/**
|
||||
* Auth result, default is {@code true} or {@code false}.
|
||||
*
|
||||
* <p>TODO with more auth result by auth plugin.
|
||||
*/
|
||||
private Object authResult;
|
||||
|
||||
public IdentityContext getIdentityContext() {
|
||||
return identityContext;
|
||||
}
|
||||
|
||||
public void setIdentityContext(IdentityContext identityContext) {
|
||||
this.identityContext = identityContext;
|
||||
}
|
||||
|
||||
public Resource getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
public void setResource(Resource resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public Object getAuthResult() {
|
||||
return authResult;
|
||||
}
|
||||
|
||||
public void setAuthResult(Object authResult) {
|
||||
this.authResult = authResult;
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.context.addition;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
|
||||
/**
|
||||
* Nacos request basic information context.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public class BasicContext {
|
||||
|
||||
private static final String DEFAULT_APP = "unknown";
|
||||
|
||||
public static final String HTTP_PROTOCOL = "HTTP";
|
||||
|
||||
public static final String GRPC_PROTOCOL = "GRPC";
|
||||
|
||||
private final AddressContext addressContext;
|
||||
|
||||
/**
|
||||
* Request user agent, such as Nacos-Java-client:v2.4.0
|
||||
*/
|
||||
private String userAgent;
|
||||
|
||||
/**
|
||||
* Request protocol type, HTTP or GRPC and so on.
|
||||
*/
|
||||
private String requestProtocol;
|
||||
|
||||
/**
|
||||
* Request target.
|
||||
* <ul>
|
||||
* <li>For HTTP protocol it should be `${Method} ${URI}`, such as `POST /v2/ns/instance`</li>
|
||||
* <li>For GRPC protocol, it should be `${requestClass}`, such as `InstanceRequest`</li>
|
||||
* </ul>
|
||||
*/
|
||||
private String requestTarget;
|
||||
|
||||
/**
|
||||
* Optional, mark the app name of the request from when client set app name, default `unknown`.
|
||||
*/
|
||||
private String app;
|
||||
|
||||
/**
|
||||
* Optional, mark the encoding of the request from when client set encoding, default `UTF-8`.
|
||||
*/
|
||||
private String encoding;
|
||||
|
||||
public BasicContext() {
|
||||
this.addressContext = new AddressContext();
|
||||
this.app = DEFAULT_APP;
|
||||
this.encoding = Constants.ENCODE;
|
||||
}
|
||||
|
||||
public AddressContext getAddressContext() {
|
||||
return addressContext;
|
||||
}
|
||||
|
||||
public String getUserAgent() {
|
||||
return userAgent;
|
||||
}
|
||||
|
||||
public void setUserAgent(String userAgent) {
|
||||
this.userAgent = userAgent;
|
||||
}
|
||||
|
||||
public String getRequestProtocol() {
|
||||
return requestProtocol;
|
||||
}
|
||||
|
||||
public void setRequestProtocol(String requestProtocol) {
|
||||
this.requestProtocol = requestProtocol;
|
||||
}
|
||||
|
||||
public String getRequestTarget() {
|
||||
return requestTarget;
|
||||
}
|
||||
|
||||
public void setRequestTarget(String requestTarget) {
|
||||
this.requestTarget = requestTarget;
|
||||
}
|
||||
|
||||
public String getApp() {
|
||||
return app;
|
||||
}
|
||||
|
||||
public void setApp(String app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
public String getEncoding() {
|
||||
return encoding;
|
||||
}
|
||||
|
||||
public void setEncoding(String encoding) {
|
||||
this.encoding = encoding;
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.context.addition;
|
||||
|
||||
import com.alibaba.nacos.common.utils.VersionUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Nacos engine context, to store some environment and engine information context. Such as version or system information.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public class EngineContext {
|
||||
|
||||
/**
|
||||
* Nacos server version, such as v2.4.0.
|
||||
*/
|
||||
private String version;
|
||||
|
||||
private final Map<String, String> contexts;
|
||||
|
||||
public EngineContext() {
|
||||
version = VersionUtils.version;
|
||||
contexts = new HashMap<>(1);
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getContext(String key) {
|
||||
return contexts.get(key);
|
||||
}
|
||||
|
||||
public String getContext(String key, String defaultValue) {
|
||||
return contexts.getOrDefault(key, defaultValue);
|
||||
}
|
||||
|
||||
public void setContext(String key, String value) {
|
||||
contexts.put(key, value);
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.context.remote;
|
||||
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Spring Configuration for request context of HTTP.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
@Configuration
|
||||
public class HttpRequestContextConfig {
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<HttpRequestContextFilter> requestContextFilterRegistration(
|
||||
HttpRequestContextFilter requestContextFilter) {
|
||||
FilterRegistrationBean<HttpRequestContextFilter> registration = new FilterRegistrationBean<>();
|
||||
registration.setFilter(requestContextFilter);
|
||||
registration.addUrlPatterns("/*");
|
||||
registration.setName("nacosRequestContextFilter");
|
||||
registration.setOrder(Integer.MIN_VALUE);
|
||||
return registration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HttpRequestContextFilter nacosRequestContextFilter() {
|
||||
return new HttpRequestContextFilter();
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.context.remote;
|
||||
|
||||
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.core.context.RequestContext;
|
||||
import com.alibaba.nacos.core.context.RequestContextHolder;
|
||||
import com.alibaba.nacos.core.context.addition.BasicContext;
|
||||
import com.alibaba.nacos.core.utils.WebUtils;
|
||||
import org.apache.http.HttpHeaders;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.alibaba.nacos.api.common.Constants.CLIENT_APPNAME_HEADER;
|
||||
|
||||
/**
|
||||
* The Filter to add request context for HTTP protocol.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public class HttpRequestContextFilter implements Filter {
|
||||
|
||||
private static final String PATTERN_REQUEST_TARGET = "%s %s";
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
RequestContext requestContext = RequestContextHolder.getContext();
|
||||
try {
|
||||
requestContext.getBasicContext().setRequestProtocol(BasicContext.HTTP_PROTOCOL);
|
||||
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
setRequestTarget(request, requestContext);
|
||||
setEncoding(request, requestContext);
|
||||
setAddressContext(request, requestContext);
|
||||
setOtherBasicContext(request, requestContext);
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
} finally {
|
||||
RequestContextHolder.removeContext();
|
||||
}
|
||||
}
|
||||
|
||||
private void setRequestTarget(HttpServletRequest request, RequestContext requestContext) {
|
||||
String uri = request.getRequestURI();
|
||||
String method = request.getMethod();
|
||||
requestContext.getBasicContext().setRequestTarget(String.format(PATTERN_REQUEST_TARGET, method, uri));
|
||||
}
|
||||
|
||||
private void setEncoding(HttpServletRequest request, RequestContext requestContext) {
|
||||
String encoding = request.getCharacterEncoding();
|
||||
if (StringUtils.isNotBlank(encoding)) {
|
||||
requestContext.getBasicContext().setEncoding(encoding);
|
||||
}
|
||||
}
|
||||
|
||||
private void setAddressContext(HttpServletRequest request, RequestContext requestContext) {
|
||||
String remoteAddress = request.getRemoteAddr();
|
||||
int remotePort = request.getRemotePort();
|
||||
String sourceIp = WebUtils.getRemoteIp(request);
|
||||
String host = request.getHeader(HttpHeaders.HOST);
|
||||
requestContext.getBasicContext().getAddressContext().setRemoteIp(remoteAddress);
|
||||
requestContext.getBasicContext().getAddressContext().setRemotePort(remotePort);
|
||||
requestContext.getBasicContext().getAddressContext().setSourceIp(sourceIp);
|
||||
requestContext.getBasicContext().getAddressContext().setHost(host);
|
||||
}
|
||||
|
||||
private void setOtherBasicContext(HttpServletRequest request, RequestContext requestContext) {
|
||||
String userAgent = WebUtils.getUserAgent(request);
|
||||
requestContext.getBasicContext().setUserAgent(userAgent);
|
||||
String app = getAppName(request);
|
||||
if (StringUtils.isNotBlank(app)) {
|
||||
requestContext.getBasicContext().setApp(app);
|
||||
}
|
||||
}
|
||||
|
||||
private String getAppName(HttpServletRequest request) {
|
||||
String app = request.getHeader(HttpHeaderConsts.APP_FILED);
|
||||
if (StringUtils.isBlank(app)) {
|
||||
app = request.getHeader(CLIENT_APPNAME_HEADER);
|
||||
}
|
||||
return app;
|
||||
}
|
||||
}
|
@ -35,7 +35,7 @@ public class CheckConfiguration {
|
||||
FilterRegistrationBean<ParamCheckerFilter> registration = new FilterRegistrationBean<>();
|
||||
registration.setFilter(checkerFilter);
|
||||
registration.addUrlPatterns("/*");
|
||||
registration.setName("checkerFilter");
|
||||
registration.setName("requestContextFilter");
|
||||
registration.setOrder(8);
|
||||
return registration;
|
||||
}
|
||||
|
@ -197,6 +197,24 @@ public class ConnectionMeta {
|
||||
this.clientIp = clientIp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter method for property <tt>remoteIp</tt>.
|
||||
*
|
||||
* @return property value of remoteIp
|
||||
*/
|
||||
public String getRemoteIp() {
|
||||
return remoteIp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter method for property <tt>remotePort</tt>.
|
||||
*
|
||||
* @return property value of remotePort
|
||||
*/
|
||||
public int getRemotePort() {
|
||||
return remotePort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter method for property <tt>connectionId</tt>.
|
||||
*
|
||||
|
@ -27,7 +27,12 @@ import com.alibaba.nacos.api.remote.response.ErrorResponse;
|
||||
import com.alibaba.nacos.api.remote.response.Response;
|
||||
import com.alibaba.nacos.api.remote.response.ResponseCode;
|
||||
import com.alibaba.nacos.api.remote.response.ServerCheckResponse;
|
||||
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
|
||||
import com.alibaba.nacos.common.remote.client.grpc.GrpcUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.core.context.RequestContext;
|
||||
import com.alibaba.nacos.core.context.RequestContextHolder;
|
||||
import com.alibaba.nacos.core.context.addition.BasicContext;
|
||||
import com.alibaba.nacos.core.monitor.MetricsMonitor;
|
||||
import com.alibaba.nacos.core.remote.Connection;
|
||||
import com.alibaba.nacos.core.remote.ConnectionManager;
|
||||
@ -186,6 +191,7 @@ public class GrpcRequestAcceptor extends RequestGrpc.RequestImplBase {
|
||||
requestMeta.setLabels(connection.getMetaInfo().getLabels());
|
||||
requestMeta.setAbilityTable(connection.getAbilityTable());
|
||||
connectionManager.refreshActiveTime(requestMeta.getConnectionId());
|
||||
prepareRequestContext(request, requestMeta, connection);
|
||||
Response response = requestHandler.handleRequest(request, requestMeta);
|
||||
Payload payloadResponse = GrpcUtils.convert(response);
|
||||
traceIfNecessary(payloadResponse, false);
|
||||
@ -212,8 +218,26 @@ public class GrpcRequestAcceptor extends RequestGrpc.RequestImplBase {
|
||||
responseObserver.onCompleted();
|
||||
MetricsMonitor.recordGrpcRequestEvent(type, false,
|
||||
ResponseCode.FAIL.getCode(), e.getClass().getSimpleName(), request.getModule(), System.nanoTime() - startTime);
|
||||
} finally {
|
||||
RequestContextHolder.removeContext();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void prepareRequestContext(Request request, RequestMeta requestMeta, Connection connection) {
|
||||
RequestContext requestContext = RequestContextHolder.getContext();
|
||||
requestContext.setRequestId(request.getRequestId());
|
||||
requestContext.getBasicContext().setUserAgent(requestMeta.getClientVersion());
|
||||
requestContext.getBasicContext().setRequestProtocol(BasicContext.GRPC_PROTOCOL);
|
||||
requestContext.getBasicContext().setRequestTarget(request.getClass().getSimpleName());
|
||||
String app = connection.getMetaInfo().getAppName();
|
||||
if (StringUtils.isBlank(app)) {
|
||||
app = request.getHeader(HttpHeaderConsts.APP_FILED, "unknown");
|
||||
}
|
||||
requestContext.getBasicContext().setApp(app);
|
||||
requestContext.getBasicContext().getAddressContext().setRemoteIp(connection.getMetaInfo().getRemoteIp());
|
||||
requestContext.getBasicContext().getAddressContext().setRemotePort(connection.getMetaInfo().getRemotePort());
|
||||
requestContext.getBasicContext().getAddressContext().setSourceIp(connection.getMetaInfo().getClientIp());
|
||||
}
|
||||
|
||||
}
|
@ -54,6 +54,12 @@ public class WebUtils {
|
||||
|
||||
private static final String TMP_SUFFIX = ".tmp";
|
||||
|
||||
private static final String X_REAL_IP = "X-Real-IP";
|
||||
|
||||
private static final String X_FORWARDED_FOR = "X-Forwarded-For";
|
||||
|
||||
private static final String X_FORWARDED_FOR_SPLIT_SYMBOL = ",";
|
||||
|
||||
/**
|
||||
* get target value from parameterMap, if not found will throw {@link IllegalArgumentException}.
|
||||
*
|
||||
@ -248,4 +254,22 @@ public class WebUtils {
|
||||
deferredResult.setResult(t);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* get real client ip
|
||||
*
|
||||
* <p>first use X-Forwarded-For header https://zh.wikipedia.org/wiki/X-Forwarded-For next nginx X-Real-IP last
|
||||
* {@link HttpServletRequest#getRemoteAddr()}
|
||||
*
|
||||
* @param request {@link HttpServletRequest}
|
||||
* @return remote ip address.
|
||||
*/
|
||||
public static String getRemoteIp(HttpServletRequest request) {
|
||||
String xForwardedFor = request.getHeader(X_FORWARDED_FOR);
|
||||
if (!StringUtils.isBlank(xForwardedFor)) {
|
||||
return xForwardedFor.split(X_FORWARDED_FOR_SPLIT_SYMBOL)[0].trim();
|
||||
}
|
||||
String nginxHeader = request.getHeader(X_REAL_IP);
|
||||
return StringUtils.isBlank(nginxHeader) ? request.getRemoteAddr() : nginxHeader;
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,9 @@ import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
|
||||
import com.alibaba.nacos.core.code.ControllerMethodsCache;
|
||||
import com.alibaba.nacos.core.context.RequestContextHolder;
|
||||
import com.alibaba.nacos.sys.env.Constants;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
@ -58,6 +60,11 @@ class AuthFilterTest {
|
||||
@Mock
|
||||
private ControllerMethodsCache methodsCache;
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
RequestContextHolder.removeContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDoFilter() {
|
||||
try {
|
||||
|
@ -24,7 +24,9 @@ import com.alibaba.nacos.api.remote.request.RequestMeta;
|
||||
import com.alibaba.nacos.api.remote.response.Response;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.core.context.RequestContextHolder;
|
||||
import com.alibaba.nacos.core.remote.RequestHandler;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
@ -50,6 +52,11 @@ class RemoteRequestAuthFilterTest {
|
||||
@Mock
|
||||
private AuthConfigs authConfigs;
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
RequestContextHolder.removeContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFilter() {
|
||||
Mockito.when(authConfigs.isAuthEnabled()).thenReturn(true);
|
||||
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.context;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class RequestContextHolderTest {
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
RequestContextHolder.removeContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetContext() {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
RequestContext requestContext = RequestContextHolder.getContext();
|
||||
assertNotNull(requestContext);
|
||||
assertNotNull(requestContext.getRequestId());
|
||||
assertTrue(requestContext.getRequestTimestamp() >= timestamp);
|
||||
assertNotNull(requestContext.getBasicContext());
|
||||
assertNotNull(requestContext.getEngineContext());
|
||||
assertNotNull(requestContext.getAuthContext());
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.context;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
class RequestContextTest {
|
||||
|
||||
long requestTimestamp;
|
||||
|
||||
RequestContext requestContext;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
requestTimestamp = System.currentTimeMillis();
|
||||
requestContext = new RequestContext(requestTimestamp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRequestId() {
|
||||
String requestId = requestContext.getRequestId();
|
||||
assertNotNull(requestId);
|
||||
assertNotNull(UUID.fromString(requestId));
|
||||
requestContext.setRequestId("testRequestId");
|
||||
assertEquals("testRequestId", requestContext.getRequestId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRequestTimestamp() {
|
||||
assertEquals(requestTimestamp, requestContext.getRequestTimestamp());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetExtensionContext() {
|
||||
assertNull(requestContext.getExtensionContext("testKey"));
|
||||
requestContext.addExtensionContext("testKey", "testValue");
|
||||
assertEquals("testValue", requestContext.getExtensionContext("testKey"));
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.context.addition;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
class AddressContextTest {
|
||||
|
||||
AddressContext addressContext;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
addressContext = new AddressContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetSourceIp() {
|
||||
assertNull(addressContext.getSourceIp());
|
||||
addressContext.setSourceIp("127.0.0.1");
|
||||
assertEquals("127.0.0.1", addressContext.getSourceIp());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetSourcePort() {
|
||||
assertEquals(0, addressContext.getSourcePort());
|
||||
addressContext.setSourcePort(8080);
|
||||
assertEquals(8080, addressContext.getSourcePort());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetRemoteIp() {
|
||||
assertNull(addressContext.getRemoteIp());
|
||||
addressContext.setRemoteIp("127.0.0.1");
|
||||
assertEquals("127.0.0.1", addressContext.getRemoteIp());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetRemotePort() {
|
||||
assertEquals(0, addressContext.getRemotePort());
|
||||
addressContext.setRemotePort(8080);
|
||||
assertEquals(8080, addressContext.getRemotePort());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetHost() {
|
||||
assertNull(addressContext.getHost());
|
||||
addressContext.setHost("127.0.0.1");
|
||||
assertEquals("127.0.0.1", addressContext.getHost());
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.context.addition;
|
||||
|
||||
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
|
||||
import com.alibaba.nacos.plugin.auth.api.Resource;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class AuthContextTest {
|
||||
|
||||
AuthContext authContext;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
authContext = new AuthContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetIdentityContext() {
|
||||
IdentityContext identityContext = new IdentityContext();
|
||||
assertNull(authContext.getIdentityContext());
|
||||
authContext.setIdentityContext(identityContext);
|
||||
assertSame(identityContext, authContext.getIdentityContext());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetResource() {
|
||||
Resource resource = new Resource("", "", "", "", new Properties());
|
||||
assertNull(authContext.getResource());
|
||||
authContext.setResource(resource);
|
||||
assertSame(resource, authContext.getResource());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetAuthResult() {
|
||||
assertNull(authContext.getAuthResult());
|
||||
authContext.setAuthResult(true);
|
||||
assertTrue((boolean) authContext.getAuthResult());
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.context.addition;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.naming.remote.request.InstanceRequest;
|
||||
import com.alibaba.nacos.common.utils.VersionUtils;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
class BasicContextTest {
|
||||
|
||||
BasicContext basicContext;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
basicContext = new BasicContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetAddressContext() {
|
||||
assertNotNull(basicContext.getAddressContext());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetUserAgent() {
|
||||
assertNull(basicContext.getUserAgent());
|
||||
basicContext.setUserAgent(VersionUtils.getFullClientVersion());
|
||||
assertEquals(VersionUtils.getFullClientVersion(), basicContext.getUserAgent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetRequestProtocol() {
|
||||
assertNull(basicContext.getRequestProtocol());
|
||||
basicContext.setRequestProtocol(BasicContext.HTTP_PROTOCOL);
|
||||
assertEquals(BasicContext.HTTP_PROTOCOL, basicContext.getRequestProtocol());
|
||||
basicContext.setRequestProtocol(BasicContext.GRPC_PROTOCOL);
|
||||
assertEquals(BasicContext.GRPC_PROTOCOL, basicContext.getRequestProtocol());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetRequestTarget() {
|
||||
assertNull(basicContext.getRequestTarget());
|
||||
basicContext.setRequestTarget("POST /v2/ns/instance");
|
||||
assertEquals("POST /v2/ns/instance", basicContext.getRequestTarget());
|
||||
basicContext.setRequestTarget(InstanceRequest.class.getSimpleName());
|
||||
assertEquals(InstanceRequest.class.getSimpleName(), basicContext.getRequestTarget());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetApp() {
|
||||
assertEquals("unknown", basicContext.getApp());
|
||||
basicContext.setApp("testApp");
|
||||
assertEquals("testApp", basicContext.getApp());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetEncoding() {
|
||||
assertEquals(Constants.ENCODE, basicContext.getEncoding());
|
||||
basicContext.setEncoding("GBK");
|
||||
assertEquals("GBK", basicContext.getEncoding());
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.context.addition;
|
||||
|
||||
import com.alibaba.nacos.common.utils.VersionUtils;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
class EngineContextTest {
|
||||
|
||||
EngineContext engineContext;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
engineContext = new EngineContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetVersion() {
|
||||
assertEquals(VersionUtils.version, engineContext.getVersion());
|
||||
engineContext.setVersion("testVersion");
|
||||
assertEquals("testVersion", engineContext.getVersion());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetContext() {
|
||||
assertNull(engineContext.getContext("test"));
|
||||
assertEquals("default", engineContext.getContext("test", "default"));
|
||||
engineContext.setContext("test", "testValue");
|
||||
assertEquals("testValue", engineContext.getContext("test"));
|
||||
assertEquals("testValue", engineContext.getContext("test", "default"));
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.context.remote;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class HttpRequestContextConfigTest {
|
||||
|
||||
@Test
|
||||
void testRequestContextFilterRegistration() {
|
||||
HttpRequestContextConfig contextConfig = new HttpRequestContextConfig();
|
||||
HttpRequestContextFilter filter = contextConfig.nacosRequestContextFilter();
|
||||
FilterRegistrationBean<HttpRequestContextFilter> actual = contextConfig.requestContextFilterRegistration(
|
||||
filter);
|
||||
assertEquals(filter, actual.getFilter());
|
||||
assertEquals("/*", actual.getUrlPatterns().iterator().next());
|
||||
assertEquals(Integer.MIN_VALUE, actual.getOrder());
|
||||
}
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.context.remote;
|
||||
|
||||
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
|
||||
import com.alibaba.nacos.core.context.RequestContext;
|
||||
import com.alibaba.nacos.core.context.RequestContextHolder;
|
||||
import com.alibaba.nacos.core.context.addition.BasicContext;
|
||||
import org.apache.http.HttpHeaders;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.opentest4j.AssertionFailedError;
|
||||
import org.springframework.mock.web.MockFilterChain;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class HttpRequestContextFilterTest {
|
||||
|
||||
@Mock
|
||||
private MockHttpServletRequest servletRequest;
|
||||
|
||||
@Mock
|
||||
private MockHttpServletResponse servletResponse;
|
||||
|
||||
@Mock
|
||||
private Servlet servlet;
|
||||
|
||||
HttpRequestContextFilter filter;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
filter = new HttpRequestContextFilter();
|
||||
RequestContextHolder.getContext();
|
||||
when(servletRequest.getHeader(HttpHeaders.HOST)).thenReturn("localhost");
|
||||
when(servletRequest.getHeader(HttpHeaders.USER_AGENT)).thenReturn("Nacos-Java-Client:v1.4.7");
|
||||
when(servletRequest.getHeader(HttpHeaderConsts.APP_FILED)).thenReturn("testApp");
|
||||
when(servletRequest.getMethod()).thenReturn("GET");
|
||||
when(servletRequest.getRequestURI()).thenReturn("/test/path");
|
||||
when(servletRequest.getCharacterEncoding()).thenReturn("GBK");
|
||||
when(servletRequest.getRemoteAddr()).thenReturn("1.1.1.1");
|
||||
when(servletRequest.getRemotePort()).thenReturn(3306);
|
||||
when(servletRequest.getHeader("X-Forwarded-For")).thenReturn("2.2.2.2");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
RequestContextHolder.removeContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoFilterSetsCorrectContextValues() throws Exception {
|
||||
MockNextFilter nextFilter = new MockNextFilter("testApp", "GBK");
|
||||
filter.doFilter(servletRequest, servletResponse, new MockFilterChain(servlet, nextFilter));
|
||||
if (null != nextFilter.error) {
|
||||
throw nextFilter.error;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoFilterWithoutEncoding() throws Exception {
|
||||
when(servletRequest.getCharacterEncoding()).thenReturn("");
|
||||
MockNextFilter nextFilter = new MockNextFilter("testApp", "UTF-8");
|
||||
filter.doFilter(servletRequest, servletResponse, new MockFilterChain(servlet, nextFilter));
|
||||
if (null != nextFilter.error) {
|
||||
throw nextFilter.error;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAppNameWithFallback() throws Exception {
|
||||
when(servletRequest.getHeader(HttpHeaderConsts.APP_FILED)).thenReturn("");
|
||||
MockNextFilter nextFilter = new MockNextFilter("unknown", "GBK");
|
||||
filter.doFilter(servletRequest, servletResponse, new MockFilterChain(servlet, nextFilter));
|
||||
if (null != nextFilter.error) {
|
||||
throw nextFilter.error;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MockNextFilter implements Filter {
|
||||
|
||||
private final String app;
|
||||
|
||||
private final String encoding;
|
||||
|
||||
AssertionError error;
|
||||
|
||||
public MockNextFilter(String app, String encoding) {
|
||||
this.app = app;
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
Filter.super.init(filterConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
try {
|
||||
RequestContext requestContext = RequestContextHolder.getContext();
|
||||
BasicContext basicContext = requestContext.getBasicContext();
|
||||
assertEquals("GET /test/path", basicContext.getRequestTarget());
|
||||
assertEquals(encoding, basicContext.getEncoding());
|
||||
assertEquals("Nacos-Java-Client:v1.4.7", basicContext.getUserAgent());
|
||||
assertEquals(app, basicContext.getApp());
|
||||
assertEquals("1.1.1.1", basicContext.getAddressContext().getRemoteIp());
|
||||
assertEquals("2.2.2.2", basicContext.getAddressContext().getSourceIp());
|
||||
assertEquals(3306, basicContext.getAddressContext().getRemotePort());
|
||||
assertEquals("localhost", basicContext.getAddressContext().getHost());
|
||||
} catch (AssertionFailedError error) {
|
||||
this.error = error;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
Filter.super.destroy();
|
||||
}
|
||||
}
|
||||
}
|
@ -18,12 +18,15 @@ package com.alibaba.nacos.core.utils;
|
||||
|
||||
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
|
||||
/**
|
||||
* {@link WebUtils} unit tests.
|
||||
@ -33,6 +36,10 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
*/
|
||||
class WebUtilsTest {
|
||||
|
||||
private static final String X_REAL_IP = "X-Real-IP";
|
||||
|
||||
private static final String X_FORWARDED_FOR = "X-Forwarded-For";
|
||||
|
||||
@Test
|
||||
void testRequired() {
|
||||
final String key = "key";
|
||||
@ -80,4 +87,27 @@ class WebUtilsTest {
|
||||
servletRequest.addHeader(HttpHeaderConsts.ACCEPT_ENCODING, "gzip, deflate, br");
|
||||
assertEquals("gzip", WebUtils.getAcceptEncoding(servletRequest));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetRemoteIp() {
|
||||
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
|
||||
|
||||
Mockito.when(request.getRemoteAddr()).thenReturn("127.0.0.1");
|
||||
assertEquals("127.0.0.1", WebUtils.getRemoteIp(request));
|
||||
|
||||
Mockito.when(request.getHeader(eq(X_REAL_IP))).thenReturn("127.0.0.2");
|
||||
assertEquals("127.0.0.2", WebUtils.getRemoteIp(request));
|
||||
|
||||
Mockito.when(request.getHeader(eq(X_FORWARDED_FOR))).thenReturn("127.0.0.3");
|
||||
assertEquals("127.0.0.3", WebUtils.getRemoteIp(request));
|
||||
|
||||
Mockito.when(request.getHeader(eq(X_FORWARDED_FOR))).thenReturn("127.0.0.3, 127.0.0.4");
|
||||
assertEquals("127.0.0.3", WebUtils.getRemoteIp(request));
|
||||
|
||||
Mockito.when(request.getHeader(eq(X_FORWARDED_FOR))).thenReturn("");
|
||||
assertEquals("127.0.0.2", WebUtils.getRemoteIp(request));
|
||||
|
||||
Mockito.when(request.getHeader(eq(X_REAL_IP))).thenReturn("");
|
||||
assertEquals("127.0.0.1", WebUtils.getRemoteIp(request));
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ import com.alibaba.nacos.naming.pojo.Subscriber;
|
||||
import com.alibaba.nacos.naming.pojo.instance.BeatInfoInstanceBuilder;
|
||||
import com.alibaba.nacos.naming.pojo.instance.HttpRequestInstanceBuilder;
|
||||
import com.alibaba.nacos.naming.pojo.instance.InstanceExtensionHandler;
|
||||
import com.alibaba.nacos.naming.utils.NamingRequestUtil;
|
||||
import com.alibaba.nacos.naming.web.CanDistro;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
@ -120,7 +121,8 @@ public class InstanceController {
|
||||
.setDefaultInstanceEphemeral(switchDomain.isDefaultInstanceEphemeral()).setRequest(request).build();
|
||||
|
||||
getInstanceOperator().registerInstance(namespaceId, serviceName, instance);
|
||||
NotifyCenter.publishEvent(new RegisterInstanceTraceEvent(System.currentTimeMillis(), "", false, namespaceId,
|
||||
NotifyCenter.publishEvent(new RegisterInstanceTraceEvent(System.currentTimeMillis(),
|
||||
NamingRequestUtil.getSourceIpForHttpRequest(request), false, namespaceId,
|
||||
NamingUtils.getGroupName(serviceName), NamingUtils.getServiceName(serviceName), instance.getIp(),
|
||||
instance.getPort()));
|
||||
return "ok";
|
||||
@ -145,9 +147,10 @@ public class InstanceController {
|
||||
NamingUtils.checkServiceNameFormat(serviceName);
|
||||
|
||||
getInstanceOperator().removeInstance(namespaceId, serviceName, instance);
|
||||
NotifyCenter.publishEvent(new DeregisterInstanceTraceEvent(System.currentTimeMillis(), "", false,
|
||||
DeregisterInstanceReason.REQUEST, namespaceId, NamingUtils.getGroupName(serviceName),
|
||||
NamingUtils.getServiceName(serviceName), instance.getIp(), instance.getPort()));
|
||||
NotifyCenter.publishEvent(new DeregisterInstanceTraceEvent(System.currentTimeMillis(),
|
||||
NamingRequestUtil.getSourceIpForHttpRequest(request), false, DeregisterInstanceReason.REQUEST,
|
||||
namespaceId, NamingUtils.getGroupName(serviceName), NamingUtils.getServiceName(serviceName),
|
||||
instance.getIp(), instance.getPort()));
|
||||
return "ok";
|
||||
}
|
||||
|
||||
@ -169,7 +172,8 @@ public class InstanceController {
|
||||
Instance instance = HttpRequestInstanceBuilder.newBuilder()
|
||||
.setDefaultInstanceEphemeral(switchDomain.isDefaultInstanceEphemeral()).setRequest(request).build();
|
||||
getInstanceOperator().updateInstance(namespaceId, serviceName, instance);
|
||||
NotifyCenter.publishEvent(new UpdateInstanceTraceEvent(System.currentTimeMillis(), "", namespaceId,
|
||||
NotifyCenter.publishEvent(new UpdateInstanceTraceEvent(System.currentTimeMillis(),
|
||||
NamingRequestUtil.getSourceIpForHttpRequest(request), namespaceId,
|
||||
NamingUtils.getGroupName(serviceName), NamingUtils.getServiceName(serviceName), instance.getIp(),
|
||||
instance.getPort(), instance.getMetadata()));
|
||||
return "ok";
|
||||
@ -267,7 +271,6 @@ public class InstanceController {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Patch instance.
|
||||
*
|
||||
|
@ -56,6 +56,7 @@ import com.alibaba.nacos.naming.paramcheck.NamingInstanceMetadataBatchHttpParamE
|
||||
import com.alibaba.nacos.naming.pojo.InstanceOperationInfo;
|
||||
import com.alibaba.nacos.naming.pojo.Subscriber;
|
||||
import com.alibaba.nacos.naming.pojo.instance.BeatInfoInstanceBuilder;
|
||||
import com.alibaba.nacos.naming.utils.NamingRequestUtil;
|
||||
import com.alibaba.nacos.naming.web.CanDistro;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
@ -115,9 +116,9 @@ public class InstanceControllerV2 {
|
||||
instanceServiceV2.registerInstance(instanceForm.getNamespaceId(), buildCompositeServiceName(instanceForm),
|
||||
instance);
|
||||
NotifyCenter.publishEvent(
|
||||
new RegisterInstanceTraceEvent(System.currentTimeMillis(), "", false, instanceForm.getNamespaceId(),
|
||||
instanceForm.getGroupName(), instanceForm.getServiceName(), instance.getIp(),
|
||||
instance.getPort()));
|
||||
new RegisterInstanceTraceEvent(System.currentTimeMillis(), NamingRequestUtil.getSourceIp(), false,
|
||||
instanceForm.getNamespaceId(), instanceForm.getGroupName(), instanceForm.getServiceName(),
|
||||
instance.getIp(), instance.getPort()));
|
||||
return Result.success("ok");
|
||||
}
|
||||
|
||||
@ -136,7 +137,8 @@ public class InstanceControllerV2 {
|
||||
Instance instance = buildInstance(instanceForm);
|
||||
instanceServiceV2.removeInstance(instanceForm.getNamespaceId(), buildCompositeServiceName(instanceForm),
|
||||
instance);
|
||||
NotifyCenter.publishEvent(new DeregisterInstanceTraceEvent(System.currentTimeMillis(), "", false,
|
||||
NotifyCenter.publishEvent(
|
||||
new DeregisterInstanceTraceEvent(System.currentTimeMillis(), NamingRequestUtil.getSourceIp(), false,
|
||||
DeregisterInstanceReason.REQUEST, instanceForm.getNamespaceId(), instanceForm.getGroupName(),
|
||||
instanceForm.getServiceName(), instance.getIp(), instance.getPort()));
|
||||
return Result.success("ok");
|
||||
@ -158,9 +160,9 @@ public class InstanceControllerV2 {
|
||||
instanceServiceV2.updateInstance(instanceForm.getNamespaceId(), buildCompositeServiceName(instanceForm),
|
||||
instance);
|
||||
NotifyCenter.publishEvent(
|
||||
new UpdateInstanceTraceEvent(System.currentTimeMillis(), "", instanceForm.getNamespaceId(),
|
||||
instanceForm.getGroupName(), instanceForm.getServiceName(), instance.getIp(),
|
||||
instance.getPort(), instance.getMetadata()));
|
||||
new UpdateInstanceTraceEvent(System.currentTimeMillis(), NamingRequestUtil.getSourceIp(),
|
||||
instanceForm.getNamespaceId(), instanceForm.getGroupName(), instanceForm.getServiceName(),
|
||||
instance.getIp(), instance.getPort(), instance.getMetadata()));
|
||||
return Result.success("ok");
|
||||
}
|
||||
|
||||
@ -231,7 +233,6 @@ public class InstanceControllerV2 {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Patch instance.
|
||||
*
|
||||
@ -463,4 +464,5 @@ public class InstanceControllerV2 {
|
||||
private String buildCompositeServiceName(InstanceMetadataBatchOperationForm form) {
|
||||
return NamingUtils.getGroupedName(form.getServiceName(), form.getGroupName());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -130,8 +130,8 @@ public class InstanceOperatorClientImpl implements InstanceOperator {
|
||||
throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.INSTANCE_ERROR,
|
||||
"service not found, namespace: " + namespaceId + ", service: " + service);
|
||||
}
|
||||
String metadataId = InstancePublishInfo
|
||||
.genMetadataId(instance.getIp(), instance.getPort(), instance.getClusterName());
|
||||
String metadataId = InstancePublishInfo.genMetadataId(instance.getIp(), instance.getPort(),
|
||||
instance.getClusterName());
|
||||
metadataOperateService.updateInstanceMetadata(service, metadataId, buildMetadata(instance));
|
||||
}
|
||||
|
||||
@ -149,8 +149,8 @@ public class InstanceOperatorClientImpl implements InstanceOperator {
|
||||
Service service = getService(namespaceId, serviceName, true);
|
||||
Instance instance = getInstance(namespaceId, serviceName, patchObject.getCluster(), patchObject.getIp(),
|
||||
patchObject.getPort());
|
||||
String metadataId = InstancePublishInfo
|
||||
.genMetadataId(instance.getIp(), instance.getPort(), instance.getClusterName());
|
||||
String metadataId = InstancePublishInfo.genMetadataId(instance.getIp(), instance.getPort(),
|
||||
instance.getClusterName());
|
||||
Optional<InstanceMetadata> instanceMetadata = metadataManager.getInstanceMetadata(service, metadataId);
|
||||
InstanceMetadata newMetadata = instanceMetadata.map(this::cloneMetadata).orElseGet(InstanceMetadata::new);
|
||||
mergeMetadata(newMetadata, patchObject);
|
||||
@ -189,8 +189,8 @@ public class InstanceOperatorClientImpl implements InstanceOperator {
|
||||
}
|
||||
ServiceInfo serviceInfo = serviceStorage.getData(service);
|
||||
ServiceMetadata serviceMetadata = metadataManager.getServiceMetadata(service).orElse(null);
|
||||
ServiceInfo result = ServiceUtil
|
||||
.selectInstancesWithHealthyProtection(serviceInfo, serviceMetadata, cluster, healthOnly, true, subscriber.getIp());
|
||||
ServiceInfo result = ServiceUtil.selectInstancesWithHealthyProtection(serviceInfo, serviceMetadata, cluster,
|
||||
healthOnly, true, subscriber.getIp());
|
||||
// adapt for v1.x sdk
|
||||
result.setName(NamingUtils.getGroupedName(result.getName(), result.getGroupName()));
|
||||
return result;
|
||||
@ -329,12 +329,8 @@ public class InstanceOperatorClientImpl implements InstanceOperator {
|
||||
|
||||
private void createIpPortClientIfAbsent(String clientId) {
|
||||
if (!clientManager.contains(clientId)) {
|
||||
ClientAttributes clientAttributes;
|
||||
if (ClientAttributesFilter.threadLocalClientAttributes.get() != null) {
|
||||
clientAttributes = ClientAttributesFilter.threadLocalClientAttributes.get();
|
||||
} else {
|
||||
clientAttributes = new ClientAttributes();
|
||||
}
|
||||
ClientAttributes clientAttributes = ClientAttributesFilter.getCurrentClientAttributes()
|
||||
.orElse(new ClientAttributes());
|
||||
clientManager.clientConnected(clientId, clientAttributes);
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import com.alibaba.nacos.core.remote.RequestHandler;
|
||||
import com.alibaba.nacos.naming.core.v2.pojo.Service;
|
||||
import com.alibaba.nacos.naming.core.v2.service.impl.EphemeralClientOperationServiceImpl;
|
||||
import com.alibaba.nacos.naming.utils.InstanceUtil;
|
||||
import com.alibaba.nacos.naming.utils.NamingRequestUtil;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -55,8 +56,8 @@ public class InstanceRequestHandler extends RequestHandler<InstanceRequest, Inst
|
||||
@Secured(action = ActionTypes.WRITE)
|
||||
@ExtractorManager.Extractor(rpcExtractor = InstanceRequestParamExtractor.class)
|
||||
public InstanceResponse handle(InstanceRequest request, RequestMeta meta) throws NacosException {
|
||||
Service service = Service
|
||||
.newService(request.getNamespace(), request.getGroupName(), request.getServiceName(), true);
|
||||
Service service = Service.newService(request.getNamespace(), request.getGroupName(), request.getServiceName(),
|
||||
true);
|
||||
InstanceUtil.setInstanceIdIfEmpty(request.getInstance(), service.getGroupedServiceName());
|
||||
switch (request.getType()) {
|
||||
case NamingRemoteConstants.REGISTER_INSTANCE:
|
||||
@ -73,16 +74,17 @@ public class InstanceRequestHandler extends RequestHandler<InstanceRequest, Inst
|
||||
throws NacosException {
|
||||
clientOperationService.registerInstance(service, request.getInstance(), meta.getConnectionId());
|
||||
NotifyCenter.publishEvent(new RegisterInstanceTraceEvent(System.currentTimeMillis(),
|
||||
meta.getClientIp(), true, service.getNamespace(), service.getGroup(), service.getName(),
|
||||
request.getInstance().getIp(), request.getInstance().getPort()));
|
||||
NamingRequestUtil.getSourceIpForGrpcRequest(meta), true, service.getNamespace(), service.getGroup(),
|
||||
service.getName(), request.getInstance().getIp(), request.getInstance().getPort()));
|
||||
return new InstanceResponse(NamingRemoteConstants.REGISTER_INSTANCE);
|
||||
}
|
||||
|
||||
private InstanceResponse deregisterInstance(Service service, InstanceRequest request, RequestMeta meta) {
|
||||
clientOperationService.deregisterInstance(service, request.getInstance(), meta.getConnectionId());
|
||||
NotifyCenter.publishEvent(new DeregisterInstanceTraceEvent(System.currentTimeMillis(),
|
||||
meta.getClientIp(), true, DeregisterInstanceReason.REQUEST, service.getNamespace(),
|
||||
service.getGroup(), service.getName(), request.getInstance().getIp(), request.getInstance().getPort()));
|
||||
NamingRequestUtil.getSourceIpForGrpcRequest(meta), true, DeregisterInstanceReason.REQUEST,
|
||||
service.getNamespace(), service.getGroup(), service.getName(), request.getInstance().getIp(),
|
||||
request.getInstance().getPort()));
|
||||
return new InstanceResponse(NamingRemoteConstants.DE_REGISTER_INSTANCE);
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ import com.alibaba.nacos.naming.core.v2.client.impl.IpPortBasedClient;
|
||||
import com.alibaba.nacos.naming.core.v2.pojo.Service;
|
||||
import com.alibaba.nacos.naming.core.v2.service.impl.PersistentClientOperationServiceImpl;
|
||||
import com.alibaba.nacos.naming.utils.InstanceUtil;
|
||||
import com.alibaba.nacos.naming.utils.NamingRequestUtil;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -75,8 +76,9 @@ public class PersistentInstanceRequestHandler extends RequestHandler<PersistentI
|
||||
Instance instance = request.getInstance();
|
||||
String clientId = IpPortBasedClient.getClientId(instance.toInetAddr(), false);
|
||||
clientOperationService.registerInstance(service, instance, clientId);
|
||||
NotifyCenter.publishEvent(new RegisterInstanceTraceEvent(System.currentTimeMillis(), meta.getClientIp(), true,
|
||||
service.getNamespace(), service.getGroup(), service.getName(), instance.getIp(), instance.getPort()));
|
||||
NotifyCenter.publishEvent(new RegisterInstanceTraceEvent(System.currentTimeMillis(),
|
||||
NamingRequestUtil.getSourceIpForGrpcRequest(meta), true, service.getNamespace(), service.getGroup(),
|
||||
service.getName(), instance.getIp(), instance.getPort()));
|
||||
return new InstanceResponse(NamingRemoteConstants.REGISTER_INSTANCE);
|
||||
}
|
||||
|
||||
@ -84,9 +86,9 @@ public class PersistentInstanceRequestHandler extends RequestHandler<PersistentI
|
||||
Instance instance = request.getInstance();
|
||||
String clientId = IpPortBasedClient.getClientId(instance.toInetAddr(), false);
|
||||
clientOperationService.deregisterInstance(service, instance, clientId);
|
||||
NotifyCenter.publishEvent(new DeregisterInstanceTraceEvent(System.currentTimeMillis(), meta.getClientIp(), true,
|
||||
DeregisterInstanceReason.REQUEST, service.getNamespace(), service.getGroup(), service.getName(),
|
||||
instance.getIp(), instance.getPort()));
|
||||
NotifyCenter.publishEvent(new DeregisterInstanceTraceEvent(System.currentTimeMillis(),
|
||||
NamingRequestUtil.getSourceIpForGrpcRequest(meta), true, DeregisterInstanceReason.REQUEST,
|
||||
service.getNamespace(), service.getGroup(), service.getName(), instance.getIp(), instance.getPort()));
|
||||
return new InstanceResponse(NamingRemoteConstants.DE_REGISTER_INSTANCE);
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import com.alibaba.nacos.naming.core.v2.index.ServiceStorage;
|
||||
import com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager;
|
||||
import com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadata;
|
||||
import com.alibaba.nacos.naming.core.v2.pojo.Service;
|
||||
import com.alibaba.nacos.naming.utils.NamingRequestUtil;
|
||||
import com.alibaba.nacos.naming.utils.ServiceUtil;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -65,7 +66,7 @@ public class ServiceQueryRequestHandler extends RequestHandler<ServiceQueryReque
|
||||
ServiceInfo result = serviceStorage.getData(service);
|
||||
ServiceMetadata serviceMetadata = metadataManager.getServiceMetadata(service).orElse(null);
|
||||
result = ServiceUtil.selectInstancesWithHealthyProtection(result, serviceMetadata, cluster, healthyOnly, true,
|
||||
meta.getClientIp());
|
||||
NamingRequestUtil.getSourceIpForGrpcRequest(meta));
|
||||
return QueryServiceResponse.buildSuccessResponse(result);
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.trace.event.naming.SubscribeServiceTraceEvent;
|
||||
import com.alibaba.nacos.common.trace.event.naming.UnsubscribeServiceTraceEvent;
|
||||
import com.alibaba.nacos.core.context.RequestContextHolder;
|
||||
import com.alibaba.nacos.core.control.TpsControl;
|
||||
import com.alibaba.nacos.core.paramcheck.ExtractorManager;
|
||||
import com.alibaba.nacos.core.paramcheck.impl.SubscribeServiceRequestParamExtractor;
|
||||
@ -36,6 +37,7 @@ import com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager;
|
||||
import com.alibaba.nacos.naming.core.v2.pojo.Service;
|
||||
import com.alibaba.nacos.naming.core.v2.service.impl.EphemeralClientOperationServiceImpl;
|
||||
import com.alibaba.nacos.naming.pojo.Subscriber;
|
||||
import com.alibaba.nacos.naming.utils.NamingRequestUtil;
|
||||
import com.alibaba.nacos.naming.utils.ServiceUtil;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -70,22 +72,24 @@ public class SubscribeServiceRequestHandler extends RequestHandler<SubscribeServ
|
||||
String namespaceId = request.getNamespace();
|
||||
String serviceName = request.getServiceName();
|
||||
String groupName = request.getGroupName();
|
||||
String app = request.getHeader("app", "unknown");
|
||||
String app = RequestContextHolder.getContext().getBasicContext().getApp();
|
||||
String groupedServiceName = NamingUtils.getGroupedName(serviceName, groupName);
|
||||
Service service = Service.newService(namespaceId, groupName, serviceName, true);
|
||||
Subscriber subscriber = new Subscriber(meta.getClientIp(), meta.getClientVersion(), app, meta.getClientIp(),
|
||||
namespaceId, groupedServiceName, 0, request.getClusters());
|
||||
ServiceInfo serviceInfo = ServiceUtil.selectInstancesWithHealthyProtection(serviceStorage.getData(service),
|
||||
metadataManager.getServiceMetadata(service).orElse(null), subscriber.getCluster(), false,
|
||||
true, subscriber.getIp());
|
||||
metadataManager.getServiceMetadata(service).orElse(null), subscriber.getCluster(), false, true,
|
||||
subscriber.getIp());
|
||||
if (request.isSubscribe()) {
|
||||
clientOperationService.subscribeService(service, subscriber, meta.getConnectionId());
|
||||
NotifyCenter.publishEvent(new SubscribeServiceTraceEvent(System.currentTimeMillis(),
|
||||
meta.getClientIp(), service.getNamespace(), service.getGroup(), service.getName()));
|
||||
NamingRequestUtil.getSourceIpForGrpcRequest(meta), service.getNamespace(), service.getGroup(),
|
||||
service.getName()));
|
||||
} else {
|
||||
clientOperationService.unsubscribeService(service, subscriber, meta.getConnectionId());
|
||||
NotifyCenter.publishEvent(new UnsubscribeServiceTraceEvent(System.currentTimeMillis(),
|
||||
meta.getClientIp(), service.getNamespace(), service.getGroup(), service.getName()));
|
||||
NamingRequestUtil.getSourceIpForGrpcRequest(meta), service.getNamespace(), service.getGroup(),
|
||||
service.getName()));
|
||||
}
|
||||
return new SubscribeServiceResponse(ResponseCode.SUCCESS.getCode(), "success", serviceInfo);
|
||||
}
|
||||
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.naming.utils;
|
||||
|
||||
import com.alibaba.nacos.api.remote.request.RequestMeta;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.core.context.RequestContextHolder;
|
||||
import com.alibaba.nacos.core.context.addition.AddressContext;
|
||||
import com.alibaba.nacos.core.utils.WebUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Naming request util.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public class NamingRequestUtil {
|
||||
|
||||
/**
|
||||
* Get source ip from request context.
|
||||
*
|
||||
* @return source ip, null if not found
|
||||
*/
|
||||
public static String getSourceIp() {
|
||||
AddressContext addressContext = RequestContextHolder.getContext().getBasicContext().getAddressContext();
|
||||
String sourceIp = addressContext.getSourceIp();
|
||||
if (StringUtils.isBlank(sourceIp)) {
|
||||
sourceIp = addressContext.getRemoteIp();
|
||||
}
|
||||
return sourceIp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get source ip from request context first, if it can't found, get from http request.
|
||||
*
|
||||
* @param httpServletRequest http request
|
||||
* @return source ip, null if not found
|
||||
*/
|
||||
public static String getSourceIpForHttpRequest(HttpServletRequest httpServletRequest) {
|
||||
String sourceIp = getSourceIp();
|
||||
// If can't get from request context, get from http request.
|
||||
if (StringUtils.isBlank(sourceIp)) {
|
||||
sourceIp = WebUtils.getRemoteIp(httpServletRequest);
|
||||
}
|
||||
return sourceIp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get source ip from request context first, if it can't found, get from http request.
|
||||
*
|
||||
* @param meta grpc request meta
|
||||
* @return source ip, null if not found
|
||||
*/
|
||||
public static String getSourceIpForGrpcRequest(RequestMeta meta) {
|
||||
String sourceIp = getSourceIp();
|
||||
// If can't get from request context, get from grpc request meta.
|
||||
if (StringUtils.isBlank(sourceIp)) {
|
||||
sourceIp = meta.getClientIp();
|
||||
}
|
||||
return sourceIp;
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ import com.alibaba.nacos.common.constant.HttpHeaderConsts;
|
||||
import com.alibaba.nacos.common.utils.HttpMethod;
|
||||
import com.alibaba.nacos.common.utils.InternetAddressUtil;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.core.context.RequestContextHolder;
|
||||
import com.alibaba.nacos.core.utils.WebUtils;
|
||||
import com.alibaba.nacos.naming.core.v2.client.ClientAttributes;
|
||||
import com.alibaba.nacos.naming.core.v2.client.impl.IpPortBasedClient;
|
||||
@ -35,6 +36,7 @@ import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -56,7 +58,14 @@ public class ClientAttributesFilter implements Filter {
|
||||
@Autowired
|
||||
private ClientManager clientManager;
|
||||
|
||||
public static ThreadLocal<ClientAttributes> threadLocalClientAttributes = new ThreadLocal<>();
|
||||
public static Optional<ClientAttributes> getCurrentClientAttributes() {
|
||||
Object clientAttributes = RequestContextHolder.getContext()
|
||||
.getExtensionContext(ClientAttributes.class.getSimpleName());
|
||||
if (clientAttributes instanceof ClientAttributes) {
|
||||
return Optional.of((ClientAttributes) clientAttributes);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
|
||||
@ -64,21 +73,20 @@ public class ClientAttributesFilter implements Filter {
|
||||
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
String uri = request.getRequestURI();
|
||||
String method = request.getMethod();
|
||||
try {
|
||||
try {
|
||||
if (isRegisterInstanceUri(uri, method)) {
|
||||
//register
|
||||
ClientAttributes requestClientAttributes = getClientAttributes(request);
|
||||
threadLocalClientAttributes.set(requestClientAttributes);
|
||||
ClientAttributes attributes = getClientAttributes();
|
||||
RequestContextHolder.getContext()
|
||||
.addExtensionContext(ClientAttributes.class.getSimpleName(), attributes);
|
||||
} else if (isBeatUri(uri, method)) {
|
||||
//beat
|
||||
String ip = WebUtils.optional(request, IP, StringUtils.EMPTY);
|
||||
int port = Integer.parseInt(WebUtils.optional(request, PORT, ZERO));
|
||||
String clientId = IpPortBasedClient
|
||||
.getClientId(ip + InternetAddressUtil.IP_PORT_SPLITER + port, true);
|
||||
String clientId = IpPortBasedClient.getClientId(ip + InternetAddressUtil.IP_PORT_SPLITER + port, true);
|
||||
IpPortBasedClient client = (IpPortBasedClient) clientManager.getClient(clientId);
|
||||
if (client != null) {
|
||||
ClientAttributes requestClientAttributes = getClientAttributes(request);
|
||||
ClientAttributes requestClientAttributes = getClientAttributes();
|
||||
//update clientAttributes,when client version attributes is null,then update.
|
||||
if (canUpdateClientAttributes(client, requestClientAttributes)) {
|
||||
client.setAttributes(requestClientAttributes);
|
||||
@ -93,30 +101,24 @@ public class ClientAttributesFilter implements Filter {
|
||||
} catch (ServletException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} finally {
|
||||
if (threadLocalClientAttributes.get() != null) {
|
||||
threadLocalClientAttributes.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBeatUri(String uri, String httpMethod) {
|
||||
return ((UtilsAndCommons.NACOS_SERVER_CONTEXT + UtilsAndCommons.NACOS_NAMING_CONTEXT
|
||||
+ UtilsAndCommons.NACOS_NAMING_INSTANCE_CONTEXT + BEAT_URI).equals(uri) || (
|
||||
UtilsAndCommons.NACOS_SERVER_CONTEXT + UtilsAndCommons.DEFAULT_NACOS_NAMING_CONTEXT_V2
|
||||
+ UtilsAndCommons.NACOS_NAMING_INSTANCE_CONTEXT + BEAT_URI).equals(uri)) && HttpMethod.PUT
|
||||
.equals(httpMethod);
|
||||
+ UtilsAndCommons.NACOS_NAMING_INSTANCE_CONTEXT + BEAT_URI).equals(uri))
|
||||
&& HttpMethod.PUT.equals(httpMethod);
|
||||
}
|
||||
|
||||
private boolean isRegisterInstanceUri(String uri, String httpMethod) {
|
||||
return ((UtilsAndCommons.NACOS_SERVER_CONTEXT + UtilsAndCommons.NACOS_NAMING_CONTEXT
|
||||
+ UtilsAndCommons.NACOS_NAMING_INSTANCE_CONTEXT).equals(uri) || (UtilsAndCommons.NACOS_SERVER_CONTEXT
|
||||
+ UtilsAndCommons.DEFAULT_NACOS_NAMING_CONTEXT_V2 + UtilsAndCommons.NACOS_NAMING_INSTANCE_CONTEXT)
|
||||
.equals(uri)) && HttpMethod.POST.equals(httpMethod);
|
||||
+ UtilsAndCommons.DEFAULT_NACOS_NAMING_CONTEXT_V2
|
||||
+ UtilsAndCommons.NACOS_NAMING_INSTANCE_CONTEXT).equals(uri)) && HttpMethod.POST.equals(httpMethod);
|
||||
}
|
||||
|
||||
private static boolean canUpdateClientAttributes(IpPortBasedClient client,
|
||||
ClientAttributes requestClientAttributes) {
|
||||
private boolean canUpdateClientAttributes(IpPortBasedClient client, ClientAttributes requestClientAttributes) {
|
||||
if (requestClientAttributes.getClientAttribute(HttpHeaderConsts.CLIENT_VERSION_HEADER) == null) {
|
||||
return false;
|
||||
}
|
||||
@ -127,10 +129,10 @@ public class ClientAttributesFilter implements Filter {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static ClientAttributes getClientAttributes(HttpServletRequest request) {
|
||||
String version = request.getHeader(HttpHeaderConsts.CLIENT_VERSION_HEADER);
|
||||
String app = request.getHeader(HttpHeaderConsts.APP_FILED);
|
||||
String clientIp = request.getRemoteAddr();
|
||||
private ClientAttributes getClientAttributes() {
|
||||
String version = RequestContextHolder.getContext().getBasicContext().getUserAgent();
|
||||
String app = RequestContextHolder.getContext().getBasicContext().getApp();
|
||||
String clientIp = RequestContextHolder.getContext().getBasicContext().getAddressContext().getSourceIp();
|
||||
ClientAttributes clientAttributes = new ClientAttributes();
|
||||
if (version != null) {
|
||||
clientAttributes.addClientAttribute(HttpHeaderConsts.CLIENT_VERSION_HEADER, version);
|
||||
|
@ -23,12 +23,14 @@ import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
|
||||
import com.alibaba.nacos.api.naming.remote.request.SubscribeServiceRequest;
|
||||
import com.alibaba.nacos.api.naming.remote.response.SubscribeServiceResponse;
|
||||
import com.alibaba.nacos.api.remote.request.RequestMeta;
|
||||
import com.alibaba.nacos.core.context.RequestContextHolder;
|
||||
import com.alibaba.nacos.naming.core.v2.index.ServiceStorage;
|
||||
import com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager;
|
||||
import com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadata;
|
||||
import com.alibaba.nacos.naming.core.v2.service.impl.EphemeralClientOperationServiceImpl;
|
||||
import com.alibaba.nacos.naming.selector.SelectorManager;
|
||||
import com.alibaba.nacos.sys.utils.ApplicationUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@ -78,6 +80,11 @@ class SubscribeServiceRequestHandlerTest {
|
||||
Mockito.when(applicationContext.getBean(SelectorManager.class)).thenReturn(selectorManager);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
RequestContextHolder.removeContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHandle() throws NacosException {
|
||||
Instance instance = new Instance();
|
||||
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.naming.utils;
|
||||
|
||||
import com.alibaba.nacos.api.remote.request.RequestMeta;
|
||||
import com.alibaba.nacos.core.context.RequestContextHolder;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class NamingRequestUtilTest {
|
||||
|
||||
@Mock
|
||||
HttpServletRequest request;
|
||||
|
||||
@Mock
|
||||
RequestMeta meta;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
RequestContextHolder.getContext().getBasicContext().getAddressContext().setRemoteIp("1.1.1.1");
|
||||
RequestContextHolder.getContext().getBasicContext().getAddressContext().setSourceIp("2.2.2.2");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
RequestContextHolder.removeContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetSourceIp() {
|
||||
assertEquals("2.2.2.2", NamingRequestUtil.getSourceIp());
|
||||
RequestContextHolder.getContext().getBasicContext().getAddressContext().setSourceIp(null);
|
||||
assertEquals("1.1.1.1", NamingRequestUtil.getSourceIp());
|
||||
RequestContextHolder.getContext().getBasicContext().getAddressContext().setRemoteIp(null);
|
||||
assertNull(NamingRequestUtil.getSourceIp());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSourceIpForHttpRequest() {
|
||||
when(request.getRemoteAddr()).thenReturn("3.3.3.3");
|
||||
assertEquals("2.2.2.2", NamingRequestUtil.getSourceIpForHttpRequest(request));
|
||||
RequestContextHolder.getContext().getBasicContext().getAddressContext().setSourceIp(null);
|
||||
assertEquals("1.1.1.1", NamingRequestUtil.getSourceIpForHttpRequest(request));
|
||||
RequestContextHolder.getContext().getBasicContext().getAddressContext().setRemoteIp(null);
|
||||
assertEquals("3.3.3.3", NamingRequestUtil.getSourceIpForHttpRequest(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSourceIpForGrpcRequest() {
|
||||
when(meta.getClientIp()).thenReturn("3.3.3.3");
|
||||
assertEquals("2.2.2.2", NamingRequestUtil.getSourceIpForGrpcRequest(meta));
|
||||
RequestContextHolder.getContext().getBasicContext().getAddressContext().setSourceIp(null);
|
||||
assertEquals("1.1.1.1", NamingRequestUtil.getSourceIpForGrpcRequest(meta));
|
||||
RequestContextHolder.getContext().getBasicContext().getAddressContext().setRemoteIp(null);
|
||||
assertEquals("3.3.3.3", NamingRequestUtil.getSourceIpForGrpcRequest(meta));
|
||||
}
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.naming.web;
|
||||
|
||||
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
|
||||
import com.alibaba.nacos.core.context.RequestContextHolder;
|
||||
import com.alibaba.nacos.naming.core.v2.client.ClientAttributes;
|
||||
import com.alibaba.nacos.naming.core.v2.client.impl.IpPortBasedClient;
|
||||
import com.alibaba.nacos.naming.core.v2.client.manager.ClientManager;
|
||||
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.mock.web.MockFilterChain;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class ClientAttributesFilterTest {
|
||||
|
||||
@Mock
|
||||
ClientManager clientManager;
|
||||
|
||||
@Mock
|
||||
IpPortBasedClient client;
|
||||
|
||||
@Mock
|
||||
HttpServletRequest request;
|
||||
|
||||
@Mock
|
||||
HttpServletResponse response;
|
||||
|
||||
@Mock
|
||||
Servlet servlet;
|
||||
|
||||
@InjectMocks
|
||||
ClientAttributesFilter filter;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
RequestContextHolder.getContext().getBasicContext().setUserAgent("Nacos-Java-Client:v2.4.0");
|
||||
RequestContextHolder.getContext().getBasicContext().setApp("testApp");
|
||||
RequestContextHolder.getContext().getBasicContext().getAddressContext().setRemoteIp("1.1.1.1");
|
||||
RequestContextHolder.getContext().getBasicContext().getAddressContext().setSourceIp("2.2.2.2");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
RequestContextHolder.removeContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDoFilterForRegisterUri() throws IOException {
|
||||
when(request.getRequestURI()).thenReturn(
|
||||
UtilsAndCommons.NACOS_SERVER_CONTEXT + UtilsAndCommons.NACOS_NAMING_CONTEXT
|
||||
+ UtilsAndCommons.NACOS_NAMING_INSTANCE_CONTEXT);
|
||||
when(request.getMethod()).thenReturn("POST");
|
||||
filter.doFilter(request, response, new MockFilterChain(servlet, new MockRegisterFilter()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDoFilterForBeatUri() throws IOException {
|
||||
when(request.getParameter("ip")).thenReturn("127.0.0.1");
|
||||
when(request.getParameter("port")).thenReturn("8848");
|
||||
when(request.getParameter("encoding")).thenReturn("utf-8");
|
||||
when(clientManager.getClient("127.0.0.1:8848#true")).thenReturn(client);
|
||||
when(request.getRequestURI()).thenReturn(
|
||||
UtilsAndCommons.NACOS_SERVER_CONTEXT + UtilsAndCommons.NACOS_NAMING_CONTEXT
|
||||
+ UtilsAndCommons.NACOS_NAMING_INSTANCE_CONTEXT + "/beat");
|
||||
when(request.getMethod()).thenReturn("PUT");
|
||||
filter.doFilter(request, response, new MockFilterChain());
|
||||
verify(client).setAttributes(any(ClientAttributes.class));
|
||||
}
|
||||
|
||||
private static class MockRegisterFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
Optional<ClientAttributes> clientAttributes = ClientAttributesFilter.getCurrentClientAttributes();
|
||||
assertTrue(clientAttributes.isPresent());
|
||||
assertEquals("Nacos-Java-Client:v2.4.0",
|
||||
clientAttributes.get().getClientAttribute(HttpHeaderConsts.CLIENT_VERSION_HEADER));
|
||||
assertEquals("testApp", clientAttributes.get().getClientAttribute(HttpHeaderConsts.APP_FILED));
|
||||
assertEquals("2.2.2.2", clientAttributes.get().getClientAttribute(HttpHeaderConsts.CLIENT_IP));
|
||||
}
|
||||
}
|
||||
}
|
220
style/NacosCheckStyle_9.xml
Normal file
220
style/NacosCheckStyle_9.xml
Normal file
@ -0,0 +1,220 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<!DOCTYPE module PUBLIC "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
|
||||
"https://checkstyle.org/dtds/configuration_1_3.dtd">
|
||||
|
||||
<module name="Checker">
|
||||
<property name="charset" value="UTF-8"/>
|
||||
<property name="severity" value="error"/>
|
||||
<property name="fileExtensions" value="java, properties, xml"/>
|
||||
|
||||
<module name="FileTabCharacter">
|
||||
<property name="eachLine" value="true"/>
|
||||
</module>
|
||||
<module name="LineLength">
|
||||
<property name="fileExtensions" value="java"/>
|
||||
<property name="max" value="150"/>
|
||||
<property name="ignorePattern"
|
||||
value="^implements.*|^extends.*|^package.*|^import.*|a href|href|http://|https://|ftp://"/>
|
||||
</module>
|
||||
<module name="SuppressWarningsFilter"/>
|
||||
|
||||
<module name="TreeWalker">
|
||||
<module name="SuppressionCommentFilter"/>
|
||||
<module name="SuppressWarningsHolder" />
|
||||
|
||||
<!-- Name Checker -->
|
||||
<module name="OuterTypeFilename"/>
|
||||
<module name="PackageName">
|
||||
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Package name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="TypeName"/>
|
||||
<module name="MemberName"/>
|
||||
<module name="ParameterName"/>
|
||||
<module name="LambdaParameterName"/>
|
||||
<module name="CatchParameterName"/>
|
||||
<module name="LocalVariableName"/>
|
||||
<module name="ClassTypeParameterName"/>
|
||||
<module name="MethodTypeParameterName"/>
|
||||
<module name="InterfaceTypeParameterName"/>
|
||||
<module name="MethodName"/>
|
||||
<module name="ConstantName"/>
|
||||
<module name="StaticVariableName"/>
|
||||
<module name="AbbreviationAsWordInName">
|
||||
<property name="ignoreFinal" value="false"/>
|
||||
<property name="allowedAbbreviationLength" value="1"/>
|
||||
<property name="allowedAbbreviations" value="VO"/>
|
||||
</module>
|
||||
|
||||
<!-- Import Checker -->
|
||||
<module name="AvoidStarImport"/>
|
||||
<module name="UnusedImports"/>
|
||||
<module name="RedundantImport"/>
|
||||
|
||||
<!-- Block Checker -->
|
||||
<module name="EmptyBlock">
|
||||
<property name="option" value="TEXT"/>
|
||||
<property name="tokens"
|
||||
value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
|
||||
</module>
|
||||
<module name="EmptyCatchBlock">
|
||||
<property name="exceptionVariableName" value="expected|ignore(d)?"/>
|
||||
</module>
|
||||
<module name="LeftCurly"/>
|
||||
<module name="RightCurly"/>
|
||||
<module name="NeedBraces"/>
|
||||
|
||||
<!-- Javadoc Checker -->
|
||||
<module name="JavadocMethod">
|
||||
<property name="accessModifiers" value="public"/>
|
||||
<property name="allowMissingParamTags" value="true"/>
|
||||
<property name="allowMissingReturnTag" value="true"/>
|
||||
<property name="allowedAnnotations"
|
||||
value="Override, Test, Before, After, BeforeClass, AfterClass, Parameterized, Parameters, Bean"/>
|
||||
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF"/>
|
||||
</module>
|
||||
<module name="MissingJavadocMethod">
|
||||
<property name="scope" value="public"/>
|
||||
<property name="minLineCount" value="2"/>
|
||||
<property name="allowedAnnotations"
|
||||
value="Override, Test, Before, After, BeforeClass, AfterClass, Parameterized, Parameters, Bean"/>
|
||||
<property name="ignoreMethodNamesRegex" value="^set[A-Z].*|^get[A-Z].*|main"/>
|
||||
<property name="tokens" value="METHOD_DEF, ANNOTATION_FIELD_DEF"/>
|
||||
</module>
|
||||
<module name="SingleLineJavadoc">
|
||||
<property name="ignoreInlineTags" value="false"/>
|
||||
</module>
|
||||
<module name="InvalidJavadocPosition"/>
|
||||
<module name="SummaryJavadoc">
|
||||
<property name="forbiddenSummaryFragments"
|
||||
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
|
||||
</module>
|
||||
<module name="JavadocParagraph"/>
|
||||
<module name="NonEmptyAtclauseDescription"/>
|
||||
|
||||
<!-- Coding Checker -->
|
||||
<module name="IllegalTokenText">
|
||||
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
|
||||
<property name="format"
|
||||
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
|
||||
<property name="message"
|
||||
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
|
||||
</module>
|
||||
<module name="OneStatementPerLine"/>
|
||||
<module name="MultipleVariableDeclarations"/>
|
||||
<module name="MissingSwitchDefault"/>
|
||||
<module name="FallThrough"/>
|
||||
<module name="NoFinalizer"/>
|
||||
<module name="OverloadMethodsDeclarationOrder"/>
|
||||
<module name="VariableDeclarationUsageDistance"/>
|
||||
<module name="AtclauseOrder">
|
||||
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
|
||||
</module>
|
||||
|
||||
<!-- Miscellaneous Checker -->
|
||||
<module name="AvoidEscapedUnicodeCharacters">
|
||||
<property name="allowEscapesForControlCharacters" value="true"/>
|
||||
<property name="allowByTailComment" value="true"/>
|
||||
<property name="allowNonPrintableEscapes" value="true"/>
|
||||
</module>
|
||||
<module name="Indentation">
|
||||
<property name="arrayInitIndent" value="8"/>
|
||||
<property name="lineWrappingIndentation" value="8"/>
|
||||
</module>
|
||||
<module name="CommentsIndentation">
|
||||
<property name="tokens" value="SINGLE_LINE_COMMENT, BLOCK_COMMENT_BEGIN"/>
|
||||
</module>
|
||||
<module name="ArrayTypeStyle"/>
|
||||
<module name="UpperEll"/>
|
||||
|
||||
<!-- Design Checker -->
|
||||
<module name="OneTopLevelClass"/>
|
||||
|
||||
<!-- Whitespace -->
|
||||
<module name="NoLineWrap"/>
|
||||
<module name="WhitespaceAfter"/>
|
||||
<module name="WhitespaceAround">
|
||||
<property name="allowEmptyConstructors" value="true"/>
|
||||
</module>
|
||||
<module name="EmptyLineSeparator">
|
||||
<property name="allowMultipleEmptyLines" value="false"/>
|
||||
<property name="allowMultipleEmptyLinesInsideClassMembers" value="false"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<property name="id" value="SeparatorWrapDot"/>
|
||||
<property name="tokens" value="DOT"/>
|
||||
<property name="option" value="nl"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<property name="id" value="SeparatorWrapComma"/>
|
||||
<property name="tokens" value="COMMA"/>
|
||||
<property name="option" value="EOL"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<property name="id" value="SeparatorWrapEllipsis"/>
|
||||
<property name="tokens" value="ELLIPSIS"/>
|
||||
<property name="option" value="EOL"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<property name="id" value="SeparatorWrapArrayDeclarator"/>
|
||||
<property name="tokens" value="ARRAY_DECLARATOR"/>
|
||||
<property name="option" value="EOL"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<property name="id" value="SeparatorWrapMethodRef"/>
|
||||
<property name="tokens" value="METHOD_REF"/>
|
||||
<property name="option" value="nl"/>
|
||||
</module>
|
||||
<module name="GenericWhitespace">
|
||||
<message key="ws.followed"
|
||||
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
|
||||
<message key="ws.preceded"
|
||||
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
|
||||
<message key="ws.illegalFollow"
|
||||
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
|
||||
<message key="ws.notPreceded"
|
||||
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
|
||||
</module>
|
||||
<module name="MethodParamPad"/>
|
||||
<module name="NoWhitespaceBefore"/>
|
||||
<module name="ParenPad"/>
|
||||
<module name="OperatorWrap">
|
||||
<property name="option" value="NL"/>
|
||||
<property name="tokens"
|
||||
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR,
|
||||
LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF "/>
|
||||
</module>
|
||||
|
||||
<!-- Modifier Checker -->
|
||||
<module name="ModifierOrder"/>
|
||||
|
||||
<!-- Annotation Checker -->
|
||||
<module name="AnnotationLocation">
|
||||
<property name="id" value="AnnotationLocationMostCases"/>
|
||||
<property name="tokens"
|
||||
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
|
||||
</module>
|
||||
<module name="AnnotationLocation">
|
||||
<property name="id" value="AnnotationLocationVariables"/>
|
||||
<property name="tokens" value="VARIABLE_DEF"/>
|
||||
<property name="allowSamelineMultipleAnnotations" value="true"/>
|
||||
</module>
|
||||
</module>
|
||||
</module>
|
@ -53,6 +53,8 @@ Volunteer wanted.
|
||||
3. Import `style/NacosCheckStyle.xml` to checkstyle plugin.
|
||||
4. Scan and check your modified code by plugin.
|
||||
|
||||
> If you install the latest version of CheckStyle plugin, it may not support the previous version of CheckStyle(9.0), you can modify the `style/NacosCheckStyle.xml` file to `style/NacosCheckStyle_9.xml` instead.
|
||||
|
||||
[checkstyle插件idea安装](https://plugins.jetbrains.com/plugin/1065-checkstyle-idea)
|
||||
|
||||
1. `Preferences/Settings --> Other Settings --> Checkstyle` 或者 `Preferences/Settings --> Tools --> Checkstyle`
|
||||
@ -60,6 +62,8 @@ Volunteer wanted.
|
||||
3. 导入源代码下`style/NacosCheckStyle.xml`文件到checkstyle插件。
|
||||
4. 用checkstyle插件扫描你修改的代码。
|
||||
|
||||
> 如果安装的CheckStyle的插件较新,已不支持9.0之前的Checkstyle版本,将上述第3步的`style/NacosCheckStyle.xml`文件修改为`style/NacosCheckStyle_9.xml`即可。
|
||||
|
||||
### eclipse IDE
|
||||
|
||||
#### p3c
|
||||
|
Loading…
Reference in New Issue
Block a user