From a345fd82693692781cd535cdbfa7897e2b5c295a Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Tue, 22 Feb 2022 13:01:46 -0800 Subject: [PATCH] Support forwarded proto field and x-forwarded-proto (#5357) * Renames for the better * Support forwarded proto * fix * Fix checkstyle complaining about abbrevation * checkstyle --- ...Parser.java => ForwardedHeaderParser.java} | 56 +++- .../http/HttpServerAttributesExtractor.java | 36 ++- .../http/ForwardedHeaderParserTest.java | 292 ++++++++++++++++++ .../http/ForwarderHeaderParserTest.java | 232 -------------- .../HttpServerAttributesExtractorTest.java | 21 +- 5 files changed, 390 insertions(+), 247 deletions(-) rename instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/{ForwarderHeaderParser.java => ForwardedHeaderParser.java} (51%) create mode 100644 instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/ForwardedHeaderParserTest.java delete mode 100644 instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/ForwarderHeaderParserTest.java diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/ForwarderHeaderParser.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/ForwardedHeaderParser.java similarity index 51% rename from instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/ForwarderHeaderParser.java rename to instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/ForwardedHeaderParser.java index 798fd5ee2516..f4c045df1ccd 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/ForwarderHeaderParser.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/ForwardedHeaderParser.java @@ -7,11 +7,31 @@ import javax.annotation.Nullable; -final class ForwarderHeaderParser { +final class ForwardedHeaderParser { - // VisibleForTesting + /** Extract proto (aka scheme) from "Forwarded" http header. */ @Nullable - static String extractForwarded(String forwarded) { + static String extractProtoFromForwardedHeader(String forwarded) { + int start = forwarded.toLowerCase().indexOf("proto="); + if (start < 0) { + return null; + } + start += 6; // start is now the index after proto= + if (start >= forwarded.length() - 1) { // the value after for= must not be empty + return null; + } + return extractProto(forwarded, start); + } + + /** Extract proto (aka scheme) from "X-Forwarded-Proto" http header. */ + @Nullable + static String extractProtoFromForwardedProtoHeader(String forwardedProto) { + return extractProto(forwardedProto, 0); + } + + /** Extract client IP address from "Forwarded" http header. */ + @Nullable + static String extractClientIpFromForwardedHeader(String forwarded) { int start = forwarded.toLowerCase().indexOf("for="); if (start < 0) { return null; @@ -23,10 +43,30 @@ static String extractForwarded(String forwarded) { return extractIpAddress(forwarded, start); } - // VisibleForTesting + /** Extract client IP address from "X-Forwarded-For" http header. */ + @Nullable + static String extractClientIpFromForwardedForHeader(String forwardedFor) { + return extractIpAddress(forwardedFor, 0); + } + @Nullable - static String extractForwardedFor(String forwarded) { - return extractIpAddress(forwarded, 0); + private static String extractProto(String forwarded, int start) { + if (forwarded.length() == start) { + return null; + } + if (forwarded.charAt(start) == '"') { + return extractProto(forwarded, start + 1); + } + for (int i = start; i < forwarded.length(); i++) { + char c = forwarded.charAt(i); + if (c == ',' || c == ';' || c == '"') { + if (i == start) { // empty string + return null; + } + return forwarded.substring(start, i); + } + } + return forwarded.substring(start); } // from https://www.rfc-editor.org/rfc/rfc7239 @@ -53,7 +93,7 @@ private static String extractIpAddress(String forwarded, int start) { return forwarded.substring(start + 1, end); } boolean inIpv4 = false; - for (int i = start; i < forwarded.length() - 1; i++) { + for (int i = start; i < forwarded.length(); i++) { char c = forwarded.charAt(i); if (c == '.') { inIpv4 = true; @@ -67,5 +107,5 @@ private static String extractIpAddress(String forwarded, int start) { return forwarded.substring(start); } - private ForwarderHeaderParser() {} + private ForwardedHeaderParser() {} } diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractor.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractor.java index b5e1436df085..1df6832d0545 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractor.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractor.java @@ -5,8 +5,10 @@ package io.opentelemetry.instrumentation.api.instrumenter.http; -import static io.opentelemetry.instrumentation.api.instrumenter.http.ForwarderHeaderParser.extractForwarded; -import static io.opentelemetry.instrumentation.api.instrumenter.http.ForwarderHeaderParser.extractForwardedFor; +import static io.opentelemetry.instrumentation.api.instrumenter.http.ForwardedHeaderParser.extractClientIpFromForwardedForHeader; +import static io.opentelemetry.instrumentation.api.instrumenter.http.ForwardedHeaderParser.extractClientIpFromForwardedHeader; +import static io.opentelemetry.instrumentation.api.instrumenter.http.ForwardedHeaderParser.extractProtoFromForwardedHeader; +import static io.opentelemetry.instrumentation.api.instrumenter.http.ForwardedHeaderParser.extractProtoFromForwardedProtoHeader; import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.context.Context; @@ -64,7 +66,11 @@ public void onStart(AttributesBuilder attributes, Context parentContext, REQUEST super.onStart(attributes, parentContext, request); set(attributes, SemanticAttributes.HTTP_FLAVOR, getter.flavor(request)); - set(attributes, SemanticAttributes.HTTP_SCHEME, getter.scheme(request)); + String forwardedProto = forwardedProto(request); + set( + attributes, + SemanticAttributes.HTTP_SCHEME, + forwardedProto != null ? forwardedProto : getter.scheme(request)); set(attributes, SemanticAttributes.HTTP_HOST, host(request)); set(attributes, SemanticAttributes.HTTP_TARGET, getter.target(request)); set(attributes, SemanticAttributes.HTTP_ROUTE, getter.route(request)); @@ -89,12 +95,32 @@ private String host(REQUEST request) { return firstHeaderValue(getter.requestHeader(request, "host")); } + @Nullable + private String forwardedProto(REQUEST request) { + // try Forwarded + String forwarded = firstHeaderValue(getter.requestHeader(request, "forwarded")); + if (forwarded != null) { + forwarded = extractProtoFromForwardedHeader(forwarded); + if (forwarded != null) { + return forwarded; + } + } + + // try X-Forwarded-Proto + forwarded = firstHeaderValue(getter.requestHeader(request, "x-forwarded-proto")); + if (forwarded != null) { + return extractProtoFromForwardedProtoHeader(forwarded); + } + + return null; + } + @Nullable private String clientIp(REQUEST request) { // try Forwarded String forwarded = firstHeaderValue(getter.requestHeader(request, "forwarded")); if (forwarded != null) { - forwarded = extractForwarded(forwarded); + forwarded = extractClientIpFromForwardedHeader(forwarded); if (forwarded != null) { return forwarded; } @@ -103,7 +129,7 @@ private String clientIp(REQUEST request) { // try X-Forwarded-For forwarded = firstHeaderValue(getter.requestHeader(request, "x-forwarded-for")); if (forwarded != null) { - return extractForwardedFor(forwarded); + return extractClientIpFromForwardedForHeader(forwarded); } return null; diff --git a/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/ForwardedHeaderParserTest.java b/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/ForwardedHeaderParserTest.java new file mode 100644 index 000000000000..2756aab924a8 --- /dev/null +++ b/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/ForwardedHeaderParserTest.java @@ -0,0 +1,292 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.instrumenter.http; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +class ForwardedHeaderParserTest { + + @Test + void extractProtoFromForwardedHeader() { + assertThat(ForwardedHeaderParser.extractProtoFromForwardedHeader("for=1.1.1.1;proto=xyz")) + .isEqualTo("xyz"); + } + + @Test + void extractProtoFromForwardedHeaderWithTrailingSemicolon() { + assertThat(ForwardedHeaderParser.extractProtoFromForwardedHeader("for=1.1.1.1;proto=xyz;")) + .isEqualTo("xyz"); + } + + @Test + void extractProtoFromForwardedHeaderWithTrailingComma() { + assertThat(ForwardedHeaderParser.extractProtoFromForwardedHeader("for=1.1.1.1;proto=xyz,")) + .isEqualTo("xyz"); + } + + @Test + void extractProtoFromForwardedHeaderWithQuotes() { + assertThat(ForwardedHeaderParser.extractProtoFromForwardedHeader("for=1.1.1.1;proto=\"xyz\"")) + .isEqualTo("xyz"); + } + + @Test + void extractProtoFromForwardedHeaderWithQuotesAndTrailingSemicolon() { + assertThat(ForwardedHeaderParser.extractProtoFromForwardedHeader("for=1.1.1.1;proto=\"xyz\";")) + .isEqualTo("xyz"); + } + + @Test + void extractProtoFromForwardedHeaderWithQuotesAndTrailingComma() { + assertThat(ForwardedHeaderParser.extractProtoFromForwardedHeader("for=1.1.1.1;proto=\"xyz\",")) + .isEqualTo("xyz"); + } + + @Test + void extractProtoFromForwardedProtoHeader() { + assertThat(ForwardedHeaderParser.extractProtoFromForwardedProtoHeader("xyz")).isEqualTo("xyz"); + } + + @Test + void extractProtoFromForwardedProtoHeaderWithQuotes() { + assertThat(ForwardedHeaderParser.extractProtoFromForwardedProtoHeader("\"xyz\"")) + .isEqualTo("xyz"); + } + + @Test + void extractClientIpFromForwardedHeader() { + assertThat(ForwardedHeaderParser.extractClientIpFromForwardedHeader("for=1.1.1.1")) + .isEqualTo("1.1.1.1"); + } + + @Test + void extractClientIpFromForwardedHeaderWithIpv6() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedHeader( + "for=\"[1111:1111:1111:1111:1111:1111:1111:1111]\"")) + .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); + } + + @Test + void extractClientIpFromForwardedHeaderWithPort() { + assertThat(ForwardedHeaderParser.extractClientIpFromForwardedHeader("for=\"1.1.1.1:2222\"")) + .isEqualTo("1.1.1.1"); + } + + @Test + void extractClientIpFromForwardedHeaderWithIpv6AndPort() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedHeader( + "for=\"[1111:1111:1111:1111:1111:1111:1111:1111]:2222\"")) + .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); + } + + @Test + void extractClientIpFromForwardedHeaderWithCaps() { + assertThat(ForwardedHeaderParser.extractClientIpFromForwardedHeader("For=1.1.1.1")) + .isEqualTo("1.1.1.1"); + } + + @Test + void extractClientIpFromMalformedForwardedHeader() { + assertThat(ForwardedHeaderParser.extractClientIpFromForwardedHeader("for=;for=1.1.1.1")) + .isNull(); + } + + @Test + void extractClientIpFromEmptyForwardedHeader() { + assertThat(ForwardedHeaderParser.extractClientIpFromForwardedHeader("")).isNull(); + } + + @Test + void extractClientIpFromForwardedHeaderWithEmptyValue() { + assertThat(ForwardedHeaderParser.extractClientIpFromForwardedHeader("for=")).isNull(); + } + + @Test + void extractClientIpFromForwardedHeaderWithValueAndSemicolon() { + assertThat(ForwardedHeaderParser.extractClientIpFromForwardedHeader("for=;")).isNull(); + } + + @Test + void extractClientIpFromForwardedHeaderWithNoFor() { + assertThat(ForwardedHeaderParser.extractClientIpFromForwardedHeader("by=1.1.1.1;test=1.1.1.1")) + .isNull(); + } + + @Test + void extractClientIpFromForwardedHeaderWithMultiple() { + assertThat(ForwardedHeaderParser.extractClientIpFromForwardedHeader("for=1.1.1.1;for=1.2.3.4")) + .isEqualTo("1.1.1.1"); + } + + @Test + void extractClientIpFromForwardedHeaderWithMultipleIpV6() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedHeader( + "for=\"[1111:1111:1111:1111:1111:1111:1111:1111]\";for=1.2.3.4")) + .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); + } + + @Test + void extractClientIpFromForwardedHeaderWithMultipleAndPort() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedHeader( + "for=\"1.1.1.1:2222\";for=1.2.3.4")) + .isEqualTo("1.1.1.1"); + } + + @Test + void extractClientIpFromForwardedHeaderWithMultipleIpV6AndPort() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedHeader( + "for=\"[1111:1111:1111:1111:1111:1111:1111:1111]:2222\";for=1.2.3.4")) + .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); + } + + @Test + void extractClientIpFromForwardedHeaderWithMixedSplitter() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedHeader( + "test=abcd; by=1.2.3.4, for=1.1.1.1;for=1.2.3.4")) + .isEqualTo("1.1.1.1"); + } + + @Test + void extractClientIpFromForwardedHeaderWithMixedSplitterIpv6() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedHeader( + "test=abcd; by=1.2.3.4, for=\"[1111:1111:1111:1111:1111:1111:1111:1111]\";for=1.2.3.4")) + .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); + } + + @Test + void extractClientIpFromForwardedHeaderWithMixedSplitterAndPort() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedHeader( + "test=abcd; by=1.2.3.4, for=\"1.1.1.1:2222\";for=1.2.3.4")) + .isEqualTo("1.1.1.1"); + } + + @Test + void extractClientIpFromForwardedHeaderWithMixedSplitterIpv6AndPort() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedHeader( + "test=abcd; by=1.2.3.4, for=\"[1111:1111:1111:1111:1111:1111:1111:1111]:2222\";for=1.2.3.4")) + .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); + } + + @Test + void extractClientIpFromForwardedForHeader() { + assertThat(ForwardedHeaderParser.extractClientIpFromForwardedForHeader("1.1.1.1")) + .isEqualTo("1.1.1.1"); + } + + @Test + void extractClientIpFromForwardedForHeaderWithIpv6() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedForHeader( + "\"[1111:1111:1111:1111:1111:1111:1111:1111]\"")) + .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); + } + + @Test + void extractClientIpFromForwardedForHeaderWithIpv6Unquoted() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedForHeader( + "[1111:1111:1111:1111:1111:1111:1111:1111]")) + .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); + } + + @Test + void extractClientIpFromForwardedForHeaderWithIpv6Unbracketed() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedForHeader( + "1111:1111:1111:1111:1111:1111:1111:1111")) + .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); + } + + @Test + void extractClientIpFromForwardedForHeaderWithPort() { + assertThat(ForwardedHeaderParser.extractClientIpFromForwardedForHeader("1.1.1.1:2222")) + .isEqualTo("1.1.1.1"); + } + + @Test + void extractClientIpFromForwardedForHeaderWithIpv6AndPort() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedForHeader( + "\"[1111:1111:1111:1111:1111:1111:1111:1111]:2222\"")) + .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); + } + + @Test + void extractClientIpFromForwardedForHeaderWithIpv6UnquotedAndPort() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedForHeader( + "[1111:1111:1111:1111:1111:1111:1111:1111]:2222")) + .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); + } + + @Test + void extractClientIpFromEmptyForwardedForHeader() { + assertThat(ForwardedHeaderParser.extractClientIpFromForwardedForHeader("")).isNull(); + } + + @Test + void extractClientIpFromForwardedForHeaderWithMultiple() { + assertThat(ForwardedHeaderParser.extractClientIpFromForwardedForHeader("1.1.1.1,1.2.3.4")) + .isEqualTo("1.1.1.1"); + } + + @Test + void extractClientIpFromForwardedForHeaderWithMultipleIpv6() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedForHeader( + "\"[1111:1111:1111:1111:1111:1111:1111:1111]\",1.2.3.4")) + .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); + } + + @Test + void extractClientIpFromForwardedForHeaderWithMultipleIpv6Unquoted() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedForHeader( + "[1111:1111:1111:1111:1111:1111:1111:1111],1.2.3.4")) + .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); + } + + @Test + void extractClientIpFromForwardedForHeaderWithMultipleIpv6Unbracketed() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedForHeader( + "1111:1111:1111:1111:1111:1111:1111:1111,1.2.3.4")) + .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); + } + + @Test + void extractClientIpFromForwardedForHeaderWithMultipleAndPort() { + assertThat(ForwardedHeaderParser.extractClientIpFromForwardedForHeader("1.1.1.1:2222,1.2.3.4")) + .isEqualTo("1.1.1.1"); + } + + @Test + void extractClientIpFromForwardedForHeaderWithMultipleIpv6AndPort() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedForHeader( + "\"[1111:1111:1111:1111:1111:1111:1111:1111]:2222\",1.2.3.4")) + .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); + } + + @Test + void extractClientIpFromForwardedForHeaderWithMultipleIpv6UnquotedAndPort() { + assertThat( + ForwardedHeaderParser.extractClientIpFromForwardedForHeader( + "[1111:1111:1111:1111:1111:1111:1111:1111]:2222,1.2.3.4")) + .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); + } +} diff --git a/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/ForwarderHeaderParserTest.java b/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/ForwarderHeaderParserTest.java deleted file mode 100644 index 3d37637bac69..000000000000 --- a/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/ForwarderHeaderParserTest.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.api.instrumenter.http; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.Test; - -class ForwarderHeaderParserTest { - - @Test - void extractForwarded() { - assertThat(ForwarderHeaderParser.extractForwarded("for=1.1.1.1")).isEqualTo("1.1.1.1"); - } - - @Test - void extractForwardedIpv6() { - assertThat( - ForwarderHeaderParser.extractForwarded( - "for=\"[1111:1111:1111:1111:1111:1111:1111:1111]\"")) - .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); - } - - @Test - void extractForwardedWithPort() { - assertThat(ForwarderHeaderParser.extractForwarded("for=\"1.1.1.1:2222\"")).isEqualTo("1.1.1.1"); - } - - @Test - void extractForwardedIpv6WithPort() { - assertThat( - ForwarderHeaderParser.extractForwarded( - "for=\"[1111:1111:1111:1111:1111:1111:1111:1111]:2222\"")) - .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); - } - - @Test - void extractForwardedCaps() { - assertThat(ForwarderHeaderParser.extractForwarded("For=1.1.1.1")).isEqualTo("1.1.1.1"); - } - - @Test - void extractForwardedMalformed() { - assertThat(ForwarderHeaderParser.extractForwarded("for=;for=1.1.1.1")).isNull(); - } - - @Test - void extractForwardedEmpty() { - assertThat(ForwarderHeaderParser.extractForwarded("")).isNull(); - } - - @Test - void extractForwardedEmptyValue() { - assertThat(ForwarderHeaderParser.extractForwarded("for=")).isNull(); - } - - @Test - void extractForwardedEmptyValueWithSemicolon() { - assertThat(ForwarderHeaderParser.extractForwarded("for=;")).isNull(); - } - - @Test - void extractForwardedNoFor() { - assertThat(ForwarderHeaderParser.extractForwarded("by=1.1.1.1;test=1.1.1.1")).isNull(); - } - - @Test - void extractForwardedMultiple() { - assertThat(ForwarderHeaderParser.extractForwarded("for=1.1.1.1;for=1.2.3.4")) - .isEqualTo("1.1.1.1"); - } - - @Test - void extractForwardedMultipleIpV6() { - assertThat( - ForwarderHeaderParser.extractForwarded( - "for=\"[1111:1111:1111:1111:1111:1111:1111:1111]\";for=1.2.3.4")) - .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); - } - - @Test - void extractForwardedMultipleWithPort() { - assertThat(ForwarderHeaderParser.extractForwarded("for=\"1.1.1.1:2222\";for=1.2.3.4")) - .isEqualTo("1.1.1.1"); - } - - @Test - void extractForwardedMultipleIpV6WithPort() { - assertThat( - ForwarderHeaderParser.extractForwarded( - "for=\"[1111:1111:1111:1111:1111:1111:1111:1111]:2222\";for=1.2.3.4")) - .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); - } - - @Test - void extractForwardedMixedSplitter() { - assertThat( - ForwarderHeaderParser.extractForwarded( - "test=abcd; by=1.2.3.4, for=1.1.1.1;for=1.2.3.4")) - .isEqualTo("1.1.1.1"); - } - - @Test - void extractForwardedMixedSplitterIpv6() { - assertThat( - ForwarderHeaderParser.extractForwarded( - "test=abcd; by=1.2.3.4, for=\"[1111:1111:1111:1111:1111:1111:1111:1111]\";for=1.2.3.4")) - .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); - } - - @Test - void extractForwardedMixedSplitterWithPort() { - assertThat( - ForwarderHeaderParser.extractForwarded( - "test=abcd; by=1.2.3.4, for=\"1.1.1.1:2222\";for=1.2.3.4")) - .isEqualTo("1.1.1.1"); - } - - @Test - void extractForwardedMixedSplitterIpv6WithPort() { - assertThat( - ForwarderHeaderParser.extractForwarded( - "test=abcd; by=1.2.3.4, for=\"[1111:1111:1111:1111:1111:1111:1111:1111]:2222\";for=1.2.3.4")) - .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); - } - - @Test - void extractForwardedFor() { - assertThat(ForwarderHeaderParser.extractForwardedFor("1.1.1.1")).isEqualTo("1.1.1.1"); - } - - @Test - void extractForwardedForIpv6() { - assertThat( - ForwarderHeaderParser.extractForwardedFor( - "\"[1111:1111:1111:1111:1111:1111:1111:1111]\"")) - .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); - } - - @Test - void extractForwardedForIpv6Unquoted() { - assertThat( - ForwarderHeaderParser.extractForwardedFor("[1111:1111:1111:1111:1111:1111:1111:1111]")) - .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); - } - - @Test - void extractForwardedForIpv6Unbracketed() { - assertThat(ForwarderHeaderParser.extractForwardedFor("1111:1111:1111:1111:1111:1111:1111:1111")) - .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); - } - - @Test - void extractForwardedForWithPort() { - assertThat(ForwarderHeaderParser.extractForwardedFor("1.1.1.1:2222")).isEqualTo("1.1.1.1"); - } - - @Test - void extractForwardedForIpv6WithPort() { - assertThat( - ForwarderHeaderParser.extractForwardedFor( - "\"[1111:1111:1111:1111:1111:1111:1111:1111]:2222\"")) - .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); - } - - @Test - void extractForwardedForIpv6UnquotedWithPort() { - assertThat( - ForwarderHeaderParser.extractForwardedFor( - "[1111:1111:1111:1111:1111:1111:1111:1111]:2222")) - .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); - } - - @Test - void extractForwardedForEmpty() { - assertThat(ForwarderHeaderParser.extractForwardedFor("")).isNull(); - } - - @Test - void extractForwardedForMultiple() { - assertThat(ForwarderHeaderParser.extractForwardedFor("1.1.1.1,1.2.3.4")).isEqualTo("1.1.1.1"); - } - - @Test - void extractForwardedForMultipleIpv6() { - assertThat( - ForwarderHeaderParser.extractForwardedFor( - "\"[1111:1111:1111:1111:1111:1111:1111:1111]\",1.2.3.4")) - .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); - } - - @Test - void extractForwardedForMultipleIpv6Unquoted() { - assertThat( - ForwarderHeaderParser.extractForwardedFor( - "[1111:1111:1111:1111:1111:1111:1111:1111],1.2.3.4")) - .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); - } - - @Test - void extractForwardedForMultipleIpv6Unbracketed() { - assertThat( - ForwarderHeaderParser.extractForwardedFor( - "1111:1111:1111:1111:1111:1111:1111:1111,1.2.3.4")) - .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); - } - - @Test - void extractForwardedForMultipleWithPort() { - assertThat(ForwarderHeaderParser.extractForwardedFor("1.1.1.1:2222,1.2.3.4")) - .isEqualTo("1.1.1.1"); - } - - @Test - void extractForwardedForMultipleIpv6WithPort() { - assertThat( - ForwarderHeaderParser.extractForwardedFor( - "\"[1111:1111:1111:1111:1111:1111:1111:1111]:2222\",1.2.3.4")) - .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); - } - - @Test - void extractForwardedForMultipleIpv6UnquotedWithPort() { - assertThat( - ForwarderHeaderParser.extractForwardedFor( - "[1111:1111:1111:1111:1111:1111:1111:1111]:2222,1.2.3.4")) - .isEqualTo("1111:1111:1111:1111:1111:1111:1111:1111"); - } -} diff --git a/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractorTest.java b/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractorTest.java index 437393199883..8303d6bb52e0 100644 --- a/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractorTest.java +++ b/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractorTest.java @@ -109,7 +109,7 @@ void normal() { request.put("method", "POST"); request.put("url", "http://github.com"); request.put("target", "/repositories/1"); - request.put("scheme", "https"); + request.put("scheme", "http"); request.put("requestContentLength", "10"); request.put("requestContentLengthUncompressed", "11"); request.put("flavor", "http/2"); @@ -117,7 +117,7 @@ void normal() { request.put("serverName", "server"); request.put("header.user-agent", "okhttp 3.x"); request.put("header.host", "github.com"); - request.put("header.forwarded", "for=1.1.1.1"); + request.put("header.forwarded", "for=1.1.1.1;proto=https"); request.put("header.custom-request-header", "123,456"); Map response = new HashMap<>(); @@ -196,4 +196,21 @@ void extractClientIpFromX_Forwarded_For() { assertThat(attributes.build()) .containsOnly(entry(SemanticAttributes.HTTP_CLIENT_IP, "1.1.1.1")); } + + @Test + void extractClientIpFromX_Forwarded_Proto() { + Map request = new HashMap<>(); + request.put("header.x-forwarded-proto", "https"); + + HttpServerAttributesExtractor, Map> extractor = + HttpServerAttributesExtractor.create( + new TestHttpServerAttributesExtractor(), CapturedHttpHeaders.empty()); + + AttributesBuilder attributes = Attributes.builder(); + extractor.onStart(attributes, Context.root(), request); + assertThat(attributes.build()).containsOnly(entry(SemanticAttributes.HTTP_SCHEME, "https")); + + extractor.onEnd(attributes, Context.root(), request, null, null); + assertThat(attributes.build()).containsOnly(entry(SemanticAttributes.HTTP_SCHEME, "https")); + } }