filters) {
+ super(context, filters);
+ }
+
+ /**
+ * Enhanced logic before method execution
+ *
+ *
+ * @param ctx ExecutableContext
+ * @see feign.Client#execute(Request, Request.Options)
+ */
+ @Override
+ public void onEnter(ExecutableContext ctx) {
+ MethodContext mc = (MethodContext) ctx;
+ Request request = (Request) mc.getArguments()[0];
+ HttpOutboundInvocation invocation;
+ try {
+ invocation = process(new FeignOutboundRequest(request, RequestContext.getAttribute(Carrier.ATTRIBUTE_SERVICE_ID)));
+ mc.setResult(invokeWithRetry(invocation, mc));
+ } catch (RejectException e) {
+ mc.setResult(feign.Response.builder().status(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE.value())
+ .body(e.getMessage().getBytes(StandardCharsets.UTF_8)).build());
+ }
+ mc.setSkip(true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onExit(ExecutableContext ctx) {
+ RequestContext.remove();
+ }
+
+ @Override
+ protected Response createResponse(Object result, Throwable throwable) {
+ return new FeignOutboundResponse((feign.Response) result, throwable);
+ }
+}
diff --git a/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/request/FeignOutboundRequest.java b/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/request/FeignOutboundRequest.java
new file mode 100644
index 00000000..9d07a52a
--- /dev/null
+++ b/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/request/FeignOutboundRequest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright © ${year} ${owner} (${email})
+ *
+ * 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.jd.live.agent.plugin.router.springcloud.v3.request;
+
+import com.jd.live.agent.core.util.cache.LazyObject;
+import com.jd.live.agent.governance.request.AbstractHttpRequest;
+import com.jd.live.agent.governance.request.Cookie;
+import com.jd.live.agent.governance.request.HttpMethod;
+import feign.Request;
+
+import java.net.HttpCookie;
+import java.net.URI;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * FeignOutboundRequest
+ *
+ * @since 1.0.0
+ */
+public class FeignOutboundRequest extends AbstractHttpRequest.AbstractHttpOutboundRequest {
+
+ private static final String COOKIE_HEADER = "Cookie";
+
+ private final String serviceId;
+
+ public FeignOutboundRequest(Request request, String serviceId) {
+ super(request);
+ this.serviceId = serviceId;
+ this.uri = URI.create(request.url());
+ this.queries = new LazyObject<>(() -> parseQuery(request.requestTemplate().queryLine()));
+ this.headers = new LazyObject<>(convertToListMap(request.headers()));
+ this.cookies = new LazyObject<>(() -> parseCookie(request.headers().get(COOKIE_HEADER)));
+ }
+
+ public static Map> convertToListMap(Map> map) {
+ return map.entrySet().stream()
+ .collect(Collectors.toMap(
+ Map.Entry::getKey,
+ e -> new ArrayList<>(e.getValue())
+ ));
+ }
+
+ protected Map> parseCookie(Collection headers) {
+ Map> result = new HashMap<>();
+ if (headers == null || headers.isEmpty()) {
+ return result;
+ }
+ for (String header : headers) {
+ if (header != null && !header.isEmpty()) {
+ String[] values = header.split(";");
+ List cookies;
+ for (String cookie : values) {
+ cookies = HttpCookie.parse(cookie.trim());
+ cookies.forEach(c -> result.computeIfAbsent(c.getName(), k -> new ArrayList<>()).add(new Cookie(c.getName(), c.getValue())));
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public HttpMethod getHttpMethod() {
+ Request.HttpMethod method = request.httpMethod();
+ try {
+ return method == null ? null : HttpMethod.valueOf(method.name());
+ } catch (IllegalArgumentException ignore) {
+ return null;
+ }
+ }
+}
diff --git a/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/response/ClientHttpOutboundResponse.java b/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/response/ClientHttpOutboundResponse.java
index 4972c212..4f3f4b56 100644
--- a/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/response/ClientHttpOutboundResponse.java
+++ b/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/response/ClientHttpOutboundResponse.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright © ${year} ${owner} (${email})
+ *
+ * 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.jd.live.agent.plugin.router.springcloud.v3.response;
import com.jd.live.agent.governance.response.AbstractHttpResponse.AbstractHttpOutboundResponse;
diff --git a/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/response/FeignOutboundResponse.java b/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/response/FeignOutboundResponse.java
new file mode 100644
index 00000000..73e019af
--- /dev/null
+++ b/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/response/FeignOutboundResponse.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright © ${year} ${owner} (${email})
+ *
+ * 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.jd.live.agent.plugin.router.springcloud.v3.response;
+
+import com.jd.live.agent.governance.response.AbstractHttpResponse.AbstractHttpOutboundResponse;
+import feign.Response;
+
+/**
+ * FeignOutboundResponse
+ *
+ * @since 1.0.0
+ */
+public class FeignOutboundResponse extends AbstractHttpOutboundResponse {
+
+ public FeignOutboundResponse(Response response, Throwable throwable) {
+ super(response, throwable);
+ }
+
+ @Override
+ public String getCode() {
+ return response == null ? "500" : String.valueOf(response.status());
+ }
+
+}
diff --git a/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/resources/META-INF/services/com.jd.live.agent.core.plugin.definition.PluginDefinition b/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/resources/META-INF/services/com.jd.live.agent.core.plugin.definition.PluginDefinition
index 729c6808..08ecec2c 100644
--- a/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/resources/META-INF/services/com.jd.live.agent.core.plugin.definition.PluginDefinition
+++ b/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/resources/META-INF/services/com.jd.live.agent.core.plugin.definition.PluginDefinition
@@ -5,4 +5,5 @@ com.jd.live.agent.plugin.router.springcloud.v3.definition.FilteringWebHandlerDef
com.jd.live.agent.plugin.router.springcloud.v3.definition.StickySessionDefinition
com.jd.live.agent.plugin.router.springcloud.v3.definition.PreferSameInstanceDefinition
com.jd.live.agent.plugin.router.springcloud.v3.definition.ZonePreferenceDefinition
-com.jd.live.agent.plugin.router.springcloud.v3.definition.ReactorLoadBalancerDefinition
\ No newline at end of file
+com.jd.live.agent.plugin.router.springcloud.v3.definition.ReactorLoadBalancerDefinition
+com.jd.live.agent.plugin.router.springcloud.v3.definition.FeignRequestDefinition
\ No newline at end of file