From 491c9e215083404d23e49b5bd3b4d78106b1bccb Mon Sep 17 00:00:00 2001 From: Chengyuan Zhang Date: Tue, 11 Aug 2020 23:13:22 +0000 Subject: [PATCH] xds: add header matching special cases for hiding/exposing some gRPC headers (v1.31.x backport) (#7224) (#7313) Expose "content-type" header (hard-coded) at header matching, pretend it's already there. --- xds/src/main/java/io/grpc/xds/RouteMatch.java | 11 ++++++- .../test/java/io/grpc/xds/RouteMatchTest.java | 30 +++++++++++++++++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/xds/src/main/java/io/grpc/xds/RouteMatch.java b/xds/src/main/java/io/grpc/xds/RouteMatch.java index 5b52e71c298..4fdbe7c29a7 100644 --- a/xds/src/main/java/io/grpc/xds/RouteMatch.java +++ b/xds/src/main/java/io/grpc/xds/RouteMatch.java @@ -65,7 +65,16 @@ boolean matches(String path, Map> headers) { return false; } for (HeaderMatcher headerMatcher : headerMatchers) { - if (!headerMatcher.matchesValue(headers.get(headerMatcher.getName()))) { + Iterable headerValues = headers.get(headerMatcher.getName()); + // Special cases for hiding headers: "grpc-previous-rpc-attempts". + if (headerMatcher.getName().equals("grpc-previous-rpc-attempts")) { + headerValues = null; + } + // Special case for exposing headers: "content-type". + if (headerMatcher.getName().equals("content-type")) { + headerValues = Collections.singletonList("application/grpc"); + } + if (!headerMatcher.matchesValue(headerValues)) { return false; } } diff --git a/xds/src/test/java/io/grpc/xds/RouteMatchTest.java b/xds/src/test/java/io/grpc/xds/RouteMatchTest.java index 712758e1168..463473d7fc6 100644 --- a/xds/src/test/java/io/grpc/xds/RouteMatchTest.java +++ b/xds/src/test/java/io/grpc/xds/RouteMatchTest.java @@ -40,7 +40,7 @@ public class RouteMatchTest { @Before public void setUp() { - headers.put("content-type", Collections.singletonList("application/grpc")); + headers.put("authority", Collections.singletonList("foo.googleapis.com")); headers.put("grpc-encoding", Collections.singletonList("gzip")); headers.put("user-agent", Collections.singletonList("gRPC-Java")); headers.put("content-length", Collections.singletonList("1000")); @@ -79,7 +79,7 @@ public void routeMatching_withHeaders() { new HeaderMatcher( "grpc-encoding", "gzip", null, null, null, null, null, false), new HeaderMatcher( - "content-type", null, Pattern.compile(".*grpc.*"), null, null, null, + "authority", null, Pattern.compile(".*googleapis.*"), null, null, null, null, false), new HeaderMatcher( "content-length", null, null, new Range(100, 10000), null, null, null, false), @@ -93,7 +93,7 @@ public void routeMatching_withHeaders() { new PathMatcher("/FooService/barMethod", null, null), Collections.singletonList( new HeaderMatcher( - "content-type", null, Pattern.compile(".*grpc.*"), null, null, null, + "authority", null, Pattern.compile(".*googleapis.*"), null, null, null, null, true)), null); assertThat(routeMatch2.matches("/FooService/barMethod", headers)).isFalse(); @@ -161,6 +161,30 @@ public void routeMatching_withRuntimeFraction() { assertThat(routeMatch2.matches("/FooService/barMethod", headers)).isFalse(); } + @Test + public void headerMatching_specialCaseGrpcHeaders() { + Map> headers = new HashMap<>(); + headers.put("grpc-previous-rpc-attempts", Collections.singletonList("0")); + + RouteMatch routeMatch1 = + new RouteMatch(new PathMatcher("/FooService/barMethod", null, null), + Arrays.asList( + new HeaderMatcher( + "grpc-previous-rpc-attempts", "0", null, null, null, null, + null, false)), + null); + assertThat(routeMatch1.matches("/FooService/barMethod", headers)).isFalse(); + + RouteMatch routeMatch2 = + new RouteMatch(new PathMatcher("/FooService/barMethod", null, null), + Arrays.asList( + new HeaderMatcher( + "content-type", "application/grpc", null, null, null, null, + null, false)), + null); + assertThat(routeMatch2.matches("/FooService/barMethod", headers)).isTrue(); + } + private static final class FakeRandom implements ThreadSafeRandom { private final int value;