From 1637912f37e9da41cb590f503537131fc5f12176 Mon Sep 17 00:00:00 2001 From: Blankjee <1257749706@qq.com> Date: Wed, 27 Sep 2023 11:12:24 +0800 Subject: [PATCH] fix: dynamic routing using cookies. (#1151) --- CHANGELOG.md | 1 + .../feign/FeignExpressionLabelUtils.java | 12 ++++++++++ .../feign/FeignExpressionLabelUtilsTest.java | 21 ++++++++++++++++ .../expresstion/ExpressionLabelUtils.java | 24 +++++++++++++++++++ .../SpringWebExpressionLabelUtils.java | 22 +++++++++++++++++ .../common/util/ExpressionLabelUtilsTest.java | 3 ++- 6 files changed, 82 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c330eaa8c..4a5edfb48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,3 +9,4 @@ - [feat:support service contract reporting.](https://github.com/Tencent/spring-cloud-tencent/pull/1140) - [feat:add swagger exposure filters.](https://github.com/Tencent/spring-cloud-tencent/pull/1145) - [feat:add swagger report switch.](https://github.com/Tencent/spring-cloud-tencent/pull/1149) +- [fix: dynamic routing using cookies.](https://github.com/Tencent/spring-cloud-tencent/pull/1097) \ No newline at end of file diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/FeignExpressionLabelUtils.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/FeignExpressionLabelUtils.java index 320aff3be..849d563c6 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/FeignExpressionLabelUtils.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/FeignExpressionLabelUtils.java @@ -63,6 +63,13 @@ public final class FeignExpressionLabelUtils { } labels.put(labelKey, getQueryValue(request, queryKey)); } + else if (ExpressionLabelUtils.isCookieLabel(labelKey)) { + String cookieKey = ExpressionLabelUtils.parseCookieKey(labelKey); + if (StringUtils.isBlank(cookieKey)) { + continue; + } + labels.put(labelKey, getCookieValue(request, cookieKey)); + } else if (ExpressionLabelUtils.isMethodLabel(labelKey)) { labels.put(labelKey, request.method()); } @@ -83,4 +90,9 @@ public final class FeignExpressionLabelUtils { public static String getQueryValue(RequestTemplate request, String key) { return ExpressionLabelUtils.getFirstValue(request.queries(), key); } + + public static String getCookieValue(RequestTemplate request, String key) { + Map> headers = request.headers(); + return ExpressionLabelUtils.getCookieFirstValue(headers, key); + } } diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/FeignExpressionLabelUtilsTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/FeignExpressionLabelUtilsTest.java index bc0194144..8d117ee2a 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/FeignExpressionLabelUtilsTest.java +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/FeignExpressionLabelUtilsTest.java @@ -18,6 +18,7 @@ package com.tencent.cloud.polaris.router.feign; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.stream.Stream; @@ -138,4 +139,24 @@ public class FeignExpressionLabelUtilsTest { assertThat(result).isNotEmpty(); assertThat(result.get(labelKey1)).isEqualTo(uri); } + + @Test + public void testGetCookie() { + String uri = "/"; + String cookieValue = "zhangsan"; + + RequestTemplate requestTemplate = new RequestTemplate(); + requestTemplate.uri(uri); + requestTemplate.method(Request.HttpMethod.GET); + requestTemplate.target("http://localhost"); + requestTemplate = requestTemplate.resolve(new HashMap<>()); + requestTemplate.header("cookie", Collections.singleton("uid=zhangsan; auth-token=dfhuwshfy77")); + + String labelKey1 = "${http.cookie.uid}"; + Map result = FeignExpressionLabelUtils.resolve(requestTemplate, Stream.of(labelKey1) + .collect(toSet())); + + assertThat(result).isNotEmpty(); + assertThat(result.get(labelKey1)).isEqualTo(cookieValue); + } } diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ExpressionLabelUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ExpressionLabelUtils.java index 627bf2b45..b7edce5a4 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ExpressionLabelUtils.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ExpressionLabelUtils.java @@ -22,6 +22,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import io.netty.handler.codec.http.HttpHeaderNames; import org.apache.commons.lang.StringUtils; import org.springframework.util.CollectionUtils; @@ -169,4 +170,27 @@ public final class ExpressionLabelUtils { return StringUtils.EMPTY; } + + public static String getCookieFirstValue(Map> valueMaps, String key) { + if (CollectionUtils.isEmpty(valueMaps)) { + return StringUtils.EMPTY; + } + + Collection values = valueMaps.get(HttpHeaderNames.COOKIE.toString()); + + if (CollectionUtils.isEmpty(values)) { + return StringUtils.EMPTY; + } + + for (String value : values) { + String[] cookieArray = StringUtils.split(value, ";"); + for (String cookieValue : cookieArray) { + String[] cookieKV = StringUtils.split(cookieValue, "="); + if (cookieKV != null && cookieKV.length == 2 && StringUtils.equals(cookieKV[0], key)) { + return cookieKV[1]; + } + } + } + return StringUtils.EMPTY; + } } diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/SpringWebExpressionLabelUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/SpringWebExpressionLabelUtils.java index b1bf54536..b8b1a59ad 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/SpringWebExpressionLabelUtils.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/SpringWebExpressionLabelUtils.java @@ -110,6 +110,13 @@ public final class SpringWebExpressionLabelUtils { } labels.put(labelKey, getQueryValue(request, queryKey)); } + else if (ExpressionLabelUtils.isCookieLabel(labelKey)) { + String cookieKey = ExpressionLabelUtils.parseCookieKey(labelKey); + if (StringUtils.isBlank(cookieKey)) { + continue; + } + labels.put(labelKey, getCookieValue(request, cookieKey)); + } else if (ExpressionLabelUtils.isMethodLabel(labelKey)) { labels.put(labelKey, request.getMethodValue()); } @@ -158,4 +165,19 @@ public final class SpringWebExpressionLabelUtils { String query = request.getURI().getQuery(); return ExpressionLabelUtils.getQueryValue(query, key); } + + public static String getCookieValue(HttpRequest request, String key) { + String first = request.getHeaders().getFirst(HttpHeaders.COOKIE); + if (StringUtils.isEmpty(first)) { + return StringUtils.EMPTY; + } + String[] cookieArray = StringUtils.split(first, ";"); + for (String cookieItem : cookieArray) { + String[] cookieKv = StringUtils.split(cookieItem, "="); + if (cookieKv != null && cookieKv.length == 2 && StringUtils.equals(cookieKv[0], key)) { + return cookieKv[1]; + } + } + return StringUtils.EMPTY; + } } diff --git a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/ExpressionLabelUtilsTest.java b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/ExpressionLabelUtilsTest.java index 1f9c94460..66d4445aa 100644 --- a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/ExpressionLabelUtilsTest.java +++ b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/ExpressionLabelUtilsTest.java @@ -197,12 +197,13 @@ public class ExpressionLabelUtilsTest { request.setMethod(HttpMethod.GET); request.setURI(URI.create("http://calleeService/user/get?uid=zhangsan")); request.getHeaders().add("uid", "zhangsan"); + request.getHeaders().add("cookie", "uid=zhangsan; auth-token=hauigdfu8esgf8"); Map result = SpringWebExpressionLabelUtils.resolve(request, labelKeys); assertThat(result.get(validLabel1)).isEqualTo("zhangsan"); assertThat(result.get(validLabel2)).isEqualTo("zhangsan"); - assertThat(result.get(validLabel3)).isNull(); + assertThat(result.get(validLabel3)).isEqualTo("zhangsan"); assertThat(result.get(validLabel4)).isEqualTo("GET"); assertThat(result.get(validLabel5)).isEqualTo("/user/get"); assertThat(result.get(invalidLabel1)).isNull();