diff --git a/build/src/main/resources/agent.properties b/build/src/main/resources/agent.properties
index d25ae84e..5e65afe8 100644
--- a/build/src/main/resources/agent.properties
+++ b/build/src/main/resources/agent.properties
@@ -214,6 +214,8 @@ plugin.observability.redis.metric.url=/platform-metrics
# plugin.observability.feignClient.tracing.enabled=true
## restTemplate tracing
# plugin.observability.restTemplate.tracing.enabled=true
+## httpURLConnection tracing
+# plugin.observability.httpURLConnection.tracing.enabled=true
# -------------------- service name ---------------------
## add service name to header by name for easemesh. default name: X-Mesh-RPC-Service
diff --git a/plugin-api/src/main/java/com/megaease/easeagent/plugin/api/config/ConfigConst.java b/plugin-api/src/main/java/com/megaease/easeagent/plugin/api/config/ConfigConst.java
index 7addef69..b741cd73 100644
--- a/plugin-api/src/main/java/com/megaease/easeagent/plugin/api/config/ConfigConst.java
+++ b/plugin-api/src/main/java/com/megaease/easeagent/plugin/api/config/ConfigConst.java
@@ -159,6 +159,7 @@ interface Namespace {
String WEB_CLIENT = "webclient";
String FEIGN_CLIENT = "feignClient";
String REST_TEMPLATE = "resTemplate";
+ String HTTPURLCONNECTION = "httpURLConnection";
String FORWARDED = "forwarded";
}
diff --git a/plugins/httpurlconnection/pom.xml b/plugins/httpurlconnection/pom.xml
new file mode 100644
index 00000000..0a85893e
--- /dev/null
+++ b/plugins/httpurlconnection/pom.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+ plugins
+ com.megaease.easeagent
+ 2.2.7
+
+ 4.0.0
+
+ httpurlconnection
+
+
+
+
+ com.megaease.easeagent
+ plugin-api
+ provided
+
+
+ com.google.guava
+ guava
+ provided
+
+
+ com.megaease.easeagent
+ plugin-api-mock
+ ${project.version}
+ test
+
+
+
diff --git a/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/ForwardedPlugin.java b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/ForwardedPlugin.java
new file mode 100644
index 00000000..6bcf4cf2
--- /dev/null
+++ b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/ForwardedPlugin.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2023, MegaEase
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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.megaease.easeagent.plugin.httpurlconnection;
+
+import com.megaease.easeagent.plugin.AgentPlugin;
+import com.megaease.easeagent.plugin.api.config.ConfigConst;
+
+public class ForwardedPlugin implements AgentPlugin {
+ @Override
+ public String getNamespace() {
+ return ConfigConst.Namespace.FORWARDED;
+ }
+
+ @Override
+ public String getDomain() {
+ return ConfigConst.INTEGRABILITY;
+ }
+}
diff --git a/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/HttpURLConnectionPlugin.java b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/HttpURLConnectionPlugin.java
new file mode 100644
index 00000000..efcc97dd
--- /dev/null
+++ b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/HttpURLConnectionPlugin.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2023, MegaEase
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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.megaease.easeagent.plugin.httpurlconnection;
+
+import com.megaease.easeagent.plugin.AgentPlugin;
+import com.megaease.easeagent.plugin.api.config.ConfigConst;
+
+public class HttpURLConnectionPlugin implements AgentPlugin {
+ @Override
+ public String getNamespace() {
+ return ConfigConst.Namespace.HTTPURLCONNECTION;
+ }
+
+ @Override
+ public String getDomain() {
+ return ConfigConst.OBSERVABILITY;
+ }
+}
diff --git a/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/advice/HttpURLConnectionGetResponseCodeAdvice.java b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/advice/HttpURLConnectionGetResponseCodeAdvice.java
new file mode 100644
index 00000000..1a115611
--- /dev/null
+++ b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/advice/HttpURLConnectionGetResponseCodeAdvice.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2023, MegaEase
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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.megaease.easeagent.plugin.httpurlconnection.advice;
+
+import com.megaease.easeagent.plugin.Points;
+import com.megaease.easeagent.plugin.matcher.ClassMatcher;
+import com.megaease.easeagent.plugin.matcher.IClassMatcher;
+import com.megaease.easeagent.plugin.matcher.IMethodMatcher;
+import com.megaease.easeagent.plugin.matcher.MethodMatcher;
+
+import java.util.Set;
+
+public class HttpURLConnectionGetResponseCodeAdvice implements Points {
+
+ @Override
+ public IClassMatcher getClassMatcher() {
+ return ClassMatcher.builder()
+ .hasSuperClass("java.net.HttpURLConnection")
+ .build();
+ }
+
+ @Override
+ public Set getMethodMatcher() {
+ return MethodMatcher.multiBuilder()
+ .match(MethodMatcher.builder().isPublic().named("getResponseCode").build())
+ .build();
+ }
+}
diff --git a/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeForwardedInterceptor.java b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeForwardedInterceptor.java
new file mode 100644
index 00000000..24ea16a3
--- /dev/null
+++ b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeForwardedInterceptor.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2023, MegaEase
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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.megaease.easeagent.plugin.httpurlconnection.interceptor;
+
+import com.megaease.easeagent.plugin.annotation.AdviceTo;
+import com.megaease.easeagent.plugin.api.Context;
+import com.megaease.easeagent.plugin.api.config.ConfigConst;
+import com.megaease.easeagent.plugin.enums.Order;
+import com.megaease.easeagent.plugin.httpurlconnection.ForwardedPlugin;
+import com.megaease.easeagent.plugin.httpurlconnection.HttpURLConnectionPlugin;
+import com.megaease.easeagent.plugin.httpurlconnection.advice.HttpURLConnectionGetResponseCodeAdvice;
+import com.megaease.easeagent.plugin.interceptor.Interceptor;
+import com.megaease.easeagent.plugin.interceptor.MethodInfo;
+
+import java.net.HttpURLConnection;
+
+@AdviceTo(value = HttpURLConnectionGetResponseCodeAdvice.class, qualifier = "default", plugin = ForwardedPlugin.class)
+public class HttpURLConnectionGetResponseCodeForwardedInterceptor implements Interceptor {
+
+ @Override
+ public void before(MethodInfo methodInfo, Context context) {
+ HttpURLConnection httpURLConnection = (HttpURLConnection) methodInfo.getInvoker();
+ context.injectForwardedHeaders(httpURLConnection::setRequestProperty);
+ }
+
+ @Override
+ public String getType() {
+ return ConfigConst.PluginID.FORWARDED;
+ }
+
+ @Override
+ public int order() {
+ return Order.FORWARDED.getOrder();
+ }
+}
diff --git a/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeInterceptor.java b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeInterceptor.java
new file mode 100644
index 00000000..a4f99d0a
--- /dev/null
+++ b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeInterceptor.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2023, MegaEase
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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.megaease.easeagent.plugin.httpurlconnection.interceptor;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import com.megaease.easeagent.plugin.annotation.AdviceTo;
+import com.megaease.easeagent.plugin.api.Context;
+import com.megaease.easeagent.plugin.api.trace.Span;
+import com.megaease.easeagent.plugin.httpurlconnection.HttpURLConnectionPlugin;
+import com.megaease.easeagent.plugin.httpurlconnection.advice.HttpURLConnectionGetResponseCodeAdvice;
+import com.megaease.easeagent.plugin.interceptor.MethodInfo;
+import com.megaease.easeagent.plugin.tools.trace.BaseHttpClientTracingInterceptor;
+import com.megaease.easeagent.plugin.tools.trace.HttpRequest;
+import com.megaease.easeagent.plugin.tools.trace.HttpResponse;
+import lombok.SneakyThrows;
+
+import java.net.HttpURLConnection;
+import java.util.List;
+import java.util.Map;
+
+
+@AdviceTo(value = HttpURLConnectionGetResponseCodeAdvice.class, qualifier = "default", plugin = HttpURLConnectionPlugin.class)
+public class HttpURLConnectionGetResponseCodeInterceptor extends BaseHttpClientTracingInterceptor {
+ @Override
+ public Object getProgressKey() {
+ return HttpURLConnectionGetResponseCodeInterceptor.class;
+ }
+
+ @Override
+ protected HttpRequest getRequest(MethodInfo methodInfo, Context context) {
+ return new InternalRequest((HttpURLConnection) methodInfo.getInvoker());
+ }
+
+
+ @Override
+ protected HttpResponse getResponse(MethodInfo methodInfo, Context context) {
+ return new InternalResponse(methodInfo.getThrowable(), (HttpURLConnection) methodInfo.getInvoker());
+ }
+
+
+ final static class InternalRequest implements HttpRequest {
+
+ private final HttpURLConnection httpURLConn;
+
+ public InternalRequest(HttpURLConnection httpURLConn) {
+ this.httpURLConn = httpURLConn;
+ }
+
+
+ @Override
+ public String method() {
+ return httpURLConn.getRequestMethod();
+ }
+
+ @Override
+ public String path() {
+ return httpURLConn.getURL().toString();
+ }
+
+ @Override
+ public String route() {
+ return null;
+ }
+
+ @Override
+ public String getRemoteAddr() {
+ return null;
+ }
+
+ @Override
+ public int getRemotePort() {
+ return 0;
+ }
+
+ @Override
+ public Span.Kind kind() {
+ return Span.Kind.CLIENT;
+ }
+
+ @Override
+ public String header(String name) {
+ return httpURLConn.getRequestProperty(name);
+ }
+
+ @Override
+ public boolean cacheScope() {
+ return false;
+ }
+
+ @Override
+ public void setHeader(String name, String value) {
+ httpURLConn.setRequestProperty(name, value);
+ }
+
+ }
+
+ final static class InternalResponse implements HttpResponse {
+ private final Throwable caught;
+ private final HttpURLConnection httpURLConn;
+ private final Multimap headers;
+
+ public InternalResponse(Throwable caught, HttpURLConnection httpURLConn) {
+ this.caught = caught;
+ this.httpURLConn = httpURLConn;
+ this.headers = getResponseHeaders(httpURLConn);
+ }
+
+ @Override
+ public String method() {
+ return httpURLConn.getRequestMethod();
+ }
+
+ @Override
+ public String route() {
+ return null;
+ }
+
+ @SneakyThrows
+ @Override
+ public int statusCode() {
+ return this.httpURLConn.getResponseCode();
+ }
+
+ @Override
+ public Throwable maybeError() {
+ return caught;
+ }
+
+
+ @Override
+ public String header(String name) {
+ return this.headers.get(name).stream().findFirst().orElse(null);
+
+ }
+
+ private Multimap getResponseHeaders(HttpURLConnection uc) {
+ Multimap headers = ArrayListMultimap.create();
+ for (Map.Entry> e : uc.getHeaderFields().entrySet()) {
+ if (e.getKey() != null) {
+ headers.putAll(e.getKey(), e.getValue());
+ }
+ }
+ return headers;
+ }
+ }
+}
diff --git a/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeForwardedInterceptorTest.java b/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeForwardedInterceptorTest.java
new file mode 100644
index 00000000..fb39ec55
--- /dev/null
+++ b/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeForwardedInterceptorTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2023, MegaEase
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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.megaease.easeagent.plugin.httpurlconnection.interceptor;
+
+import com.megaease.easeagent.mock.plugin.api.junit.EaseAgentJunit4ClassRunner;
+import com.megaease.easeagent.plugin.api.Context;
+import com.megaease.easeagent.plugin.api.config.ConfigConst;
+import com.megaease.easeagent.plugin.bridge.EaseAgent;
+import com.megaease.easeagent.plugin.interceptor.MethodInfo;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.HttpURLConnection;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+@RunWith(EaseAgentJunit4ClassRunner.class)
+public class HttpURLConnectionGetResponseCodeForwardedInterceptorTest {
+
+ @Test
+ public void before() {
+ Context context = EaseAgent.getContext();
+ HttpURLConnection conn = TestUtils.mockHttpURLConnection();
+ MethodInfo methodInfo = TestUtils.mockMethodInfo(conn);
+ HttpURLConnectionGetResponseCodeForwardedInterceptor httpClientDoExecuteForwardedInterceptor = new HttpURLConnectionGetResponseCodeForwardedInterceptor();
+
+ httpClientDoExecuteForwardedInterceptor.before(methodInfo, context);
+ assertNull(conn.getRequestProperty(TestUtils.FORWARDED_NAME));
+ context.put(TestUtils.FORWARDED_NAME, TestUtils.FORWARDED_VALUE);
+ httpClientDoExecuteForwardedInterceptor.before(methodInfo, context);
+ assertEquals(TestUtils.FORWARDED_VALUE, conn.getRequestProperty(TestUtils.FORWARDED_NAME));
+ context.remove(TestUtils.FORWARDED_NAME);
+ }
+
+ @Test
+ public void getType() {
+ HttpURLConnectionGetResponseCodeForwardedInterceptor httpClientDoExecuteForwardedInterceptor = new HttpURLConnectionGetResponseCodeForwardedInterceptor();
+ assertEquals(ConfigConst.PluginID.FORWARDED, httpClientDoExecuteForwardedInterceptor.getType());
+ }
+}
diff --git a/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java b/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java
new file mode 100644
index 00000000..54d6d0aa
--- /dev/null
+++ b/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2023, MegaEase
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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.megaease.easeagent.plugin.httpurlconnection.interceptor;
+
+import com.megaease.easeagent.mock.plugin.api.MockEaseAgent;
+import com.megaease.easeagent.mock.plugin.api.junit.EaseAgentJunit4ClassRunner;
+import com.megaease.easeagent.plugin.api.Context;
+import com.megaease.easeagent.plugin.api.trace.Scope;
+import com.megaease.easeagent.plugin.api.trace.Span;
+import com.megaease.easeagent.plugin.bridge.EaseAgent;
+import com.megaease.easeagent.plugin.interceptor.MethodInfo;
+import com.megaease.easeagent.plugin.report.tracing.ReportSpan;
+import com.megaease.easeagent.plugin.tools.trace.HttpRequest;
+import com.megaease.easeagent.plugin.tools.trace.HttpResponse;
+import lombok.SneakyThrows;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+@RunWith(EaseAgentJunit4ClassRunner.class)
+public class HttpURLConnectionGetResponseCodeInterceptorTest {
+
+ @SneakyThrows
+ @Test
+ public void before() {
+ Context context = EaseAgent.getContext();
+ MethodInfo methodInfo = TestUtils.mockMethodInfo();
+
+ HttpURLConnectionGetResponseCodeInterceptor httpURLConnectionWriteRequestsInterceptor = new HttpURLConnectionGetResponseCodeInterceptor();
+ MockEaseAgent.cleanLastSpan();
+ httpURLConnectionWriteRequestsInterceptor.before(methodInfo, context);
+ httpURLConnectionWriteRequestsInterceptor.after(methodInfo, context);
+ ReportSpan mockSpan = MockEaseAgent.getLastSpan();
+ assertNotNull(mockSpan);
+ assertEquals(Span.Kind.CLIENT.name(), mockSpan.kind());
+ assertEquals(TestUtils.RESPONSE_TAG_VALUE, mockSpan.tag(TestUtils.RESPONSE_TAG_NAME));
+ assertNull(mockSpan.parentId());
+
+ Span span = context.nextSpan();
+ try (Scope ignored = span.maybeScope()) {
+ httpURLConnectionWriteRequestsInterceptor.doBefore(methodInfo, context);
+ httpURLConnectionWriteRequestsInterceptor.doAfter(methodInfo, context);
+ mockSpan = MockEaseAgent.getLastSpan();
+ assertEquals(span.traceIdString(), mockSpan.traceId());
+ assertEquals(span.spanIdString(), mockSpan.parentId());
+ assertNotNull(mockSpan.id());
+ }
+ span.abandon();
+ }
+
+ @Test
+ public void after() {
+ before();
+ }
+
+
+ @SneakyThrows
+ @Test
+ public void getRequest() {
+ Context context = EaseAgent.getContext();
+ MethodInfo methodInfo = TestUtils.mockMethodInfo();
+
+ HttpURLConnectionGetResponseCodeInterceptor httpClientDoExecuteInterceptor = new HttpURLConnectionGetResponseCodeInterceptor();
+ HttpRequest request = httpClientDoExecuteInterceptor.getRequest(methodInfo, context);
+ assertEquals(Span.Kind.CLIENT, request.kind());
+ assertEquals("GET", request.method());
+ }
+
+ @SneakyThrows
+ @Test
+ public void getResponse() {
+ Context context = EaseAgent.getContext();
+ MethodInfo methodInfo = TestUtils.mockMethodInfo();
+
+ HttpURLConnectionGetResponseCodeInterceptor httpClientDoExecuteInterceptor = new HttpURLConnectionGetResponseCodeInterceptor();
+
+ HttpResponse httpResponse = httpClientDoExecuteInterceptor.getResponse(methodInfo, context);
+ assertEquals(200, httpResponse.statusCode());
+ }
+}
diff --git a/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/TestUtils.java b/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/TestUtils.java
new file mode 100644
index 00000000..4f7fa4f0
--- /dev/null
+++ b/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/TestUtils.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2023, MegaEase
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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.megaease.easeagent.plugin.httpurlconnection.interceptor;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.net.HttpHeaders;
+import com.megaease.easeagent.plugin.interceptor.MethodInfo;
+import lombok.SneakyThrows;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+final class TestUtils {
+ public static final String FORWARDED_NAME = "X-Forwarded-For";
+ public static final String FORWARDED_VALUE = "testForwarded";
+ public static final String RESPONSE_TAG_NAME = "X-EG-Test";
+ public static final String RESPONSE_TAG_VALUE = "X-EG-Test-Value";
+
+ @SneakyThrows
+ static MethodInfo mockMethodInfo() {
+ HttpURLConnection httpURLConnection = mockHttpURLConnection();
+ return mockMethodInfo(httpURLConnection);
+ }
+
+ static MethodInfo mockMethodInfo(HttpURLConnection httpURLConnection) {
+ MethodInfo methodInfo = MethodInfo.builder()
+ .invoker(httpURLConnection).retValue(httpURLConnection)
+ .build();
+ return methodInfo;
+ }
+
+ @SneakyThrows
+ static HttpURLConnection mockHttpURLConnection() {
+ URL url = new URL("http://127.0.0.1:8080");
+ Map responseHeader = ImmutableMap.of(TestUtils.RESPONSE_TAG_NAME, TestUtils.RESPONSE_TAG_VALUE);
+ return getConnection(url, "GET", null, responseHeader);
+ }
+
+ static HttpURLConnection getConnection(
+ URL url, String method, Map requestHeaders, Map responseHeader) throws IOException {
+
+ HttpURLConnection conn = new HttpURLConnection(url) {
+
+ @Override
+ public void connect() throws IOException {
+
+ }
+
+ @Override
+ public void disconnect() {
+
+ }
+
+ @Override
+ public boolean usingProxy() {
+ return false;
+ }
+
+ @Override
+ public int getResponseCode() throws IOException {
+ return 200;
+ }
+
+ @Override
+ public Map> getHeaderFields() {
+ Map> fields = new HashMap<>();
+ for (String key : responseHeader.keySet()) {
+ fields.put(key, Lists.newArrayList(responseHeader.get(key)));
+ }
+ return fields;
+ }
+ };
+ conn.setRequestMethod(method);
+ conn.setDoInput(true);
+ conn.setDoOutput(true);
+ conn.setRequestProperty(HttpHeaders.HOST, url.getHost());
+ if (requestHeaders != null) {
+ for (String key : requestHeaders.keySet()) {
+ conn.setRequestProperty(key, requestHeaders.get(key));
+ }
+ }
+
+ return conn;
+ }
+}
diff --git a/plugins/httpurlconnection/src/test/resources/mock_agent.properties b/plugins/httpurlconnection/src/test/resources/mock_agent.properties
new file mode 100644
index 00000000..8fb0c298
--- /dev/null
+++ b/plugins/httpurlconnection/src/test/resources/mock_agent.properties
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2023, MegaEase
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# 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.
+#
+
+easeagent.progress.forwarded.headers=X-Forwarded-For
+observability.tracings.tag.response.headers.eg.0=X-EG-Test
diff --git a/plugins/pom.xml b/plugins/pom.xml
index d81a14cc..85caab04 100644
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -52,6 +52,7 @@
dubbo
motan
sofarpc
+ httpurlconnection