diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/grpc/RequestAttributes.java b/service/src/main/java/org/whispersystems/textsecuregcm/grpc/RequestAttributes.java index 23ba732eb..7a6890343 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/grpc/RequestAttributes.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/grpc/RequestAttributes.java @@ -5,12 +5,37 @@ package org.whispersystems.textsecuregcm.grpc; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.net.InetAddress; +import java.util.Collections; import java.util.List; import java.util.Locale; import javax.annotation.Nullable; public record RequestAttributes(InetAddress remoteAddress, @Nullable String userAgent, + @Nullable String acceptLanguageRaw, List acceptLanguage) { + + private static final Logger LOGGER = LoggerFactory.getLogger(RequestAttributes.class); + + public RequestAttributes(InetAddress remoteAddress, + @Nullable String userAgent, + @Nullable String acceptLanguageRaw) { + this(remoteAddress, userAgent, acceptLanguageRaw, parseAcceptLanguage(acceptLanguageRaw, userAgent)); + } + + private static List parseAcceptLanguage(final String acceptLanguageRaw, final String userAgent) { + List acceptLanguages = Collections.emptyList(); + if (StringUtils.isNotBlank(acceptLanguageRaw)) { + try { + acceptLanguages = Locale.LanguageRange.parse(acceptLanguageRaw); + } catch (final IllegalArgumentException e) { + LOGGER.debug("Invalid Accept-Language header from User-Agent {}: {}", userAgent, acceptLanguageRaw, e); + } + } + return acceptLanguages; + } } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/grpc/RequestAttributesInterceptor.java b/service/src/main/java/org/whispersystems/textsecuregcm/grpc/RequestAttributesInterceptor.java index 9c468ec0d..eeeab6684 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/grpc/RequestAttributesInterceptor.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/grpc/RequestAttributesInterceptor.java @@ -70,17 +70,8 @@ public class RequestAttributesInterceptor implements ServerInterceptor { return ServerInterceptorUtil.closeWithStatus(call, Status.UNAVAILABLE); } - @Nullable List acceptLanguages = Collections.emptyList(); - if (StringUtils.isNotBlank(acceptLanguageHeader)) { - try { - acceptLanguages = Locale.LanguageRange.parse(acceptLanguageHeader); - } catch (final IllegalArgumentException e) { - log.debug("Invalid Accept-Language header from User-Agent {}: {}", userAgentHeader, acceptLanguageHeader, e); - } - } - final RequestAttributes requestAttributes = - new RequestAttributes(remoteAddress.get(), userAgentHeader, acceptLanguages); + new RequestAttributes(remoteAddress.get(), userAgentHeader, acceptLanguageHeader); return Contexts.interceptCall( Context.current().withValue(RequestAttributesUtil.REQUEST_ATTRIBUTES_CONTEXT_KEY, requestAttributes), call, headers, next); diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/grpc/RequestAttributesUtil.java b/service/src/main/java/org/whispersystems/textsecuregcm/grpc/RequestAttributesUtil.java index 25673cfbf..e87733d2d 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/grpc/RequestAttributesUtil.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/grpc/RequestAttributesUtil.java @@ -1,6 +1,7 @@ package org.whispersystems.textsecuregcm.grpc; import io.grpc.Context; +import javax.annotation.Nullable; import java.net.InetAddress; import java.util.Arrays; import java.util.List; @@ -22,6 +23,15 @@ public class RequestAttributesUtil { return REQUEST_ATTRIBUTES_CONTEXT_KEY.get().acceptLanguage(); } + /** + * Returns the raw "Accept-Language" header string from the remote client in the current gRPC request context + * + * @return the raw "Accept-Language" header listed by the remote client; may be null if not specified + */ + public static @Nullable String getAcceptLanguageRaw() { + return REQUEST_ATTRIBUTES_CONTEXT_KEY.get().acceptLanguageRaw(); + } + /** * Returns a list of distinct locales supported by the JVM and accepted by the remote client in the current gRPC * context. May be empty if the client did not supply a list of acceptable languages, if the list of acceptable diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/grpc/ProfileAnonymousGrpcServiceTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/grpc/ProfileAnonymousGrpcServiceTest.java index f30e33eb0..985f87db8 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/grpc/ProfileAnonymousGrpcServiceTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/grpc/ProfileAnonymousGrpcServiceTest.java @@ -96,7 +96,7 @@ public class ProfileAnonymousGrpcServiceTest extends SimpleBaseGrpcTest availableAcceptedLocales = - callWithRequestAttributes(buildRequestAttributes(Locale.LanguageRange.parse("en,ja")), + callWithRequestAttributes(buildRequestAttributes(null, "en,ja"), RequestAttributesUtil::getAvailableAcceptedLocales); assertFalse(availableAcceptedLocales.isEmpty()); @@ -56,11 +56,11 @@ class RequestAttributesUtilTest { @Test void getUserAgent() throws Exception { assertEquals(Optional.empty(), - callWithRequestAttributes(buildRequestAttributes((String) null), + callWithRequestAttributes(buildRequestAttributes(null, null), RequestAttributesUtil::getUserAgent)); assertEquals(Optional.of("Signal-Desktop/1.2.3 Linux"), - callWithRequestAttributes(buildRequestAttributes("Signal-Desktop/1.2.3 Linux"), + callWithRequestAttributes(buildRequestAttributes("Signal-Desktop/1.2.3 Linux", null), RequestAttributesUtil::getUserAgent)); } @@ -70,16 +70,8 @@ class RequestAttributesUtilTest { .call(callable); } - private static RequestAttributes buildRequestAttributes(final String userAgent) { - return buildRequestAttributes(userAgent, Collections.emptyList()); - } - - private static RequestAttributes buildRequestAttributes(final List acceptLanguage) { - return buildRequestAttributes(null, acceptLanguage); - } - private static RequestAttributes buildRequestAttributes(@Nullable final String userAgent, - final List acceptLanguage) { + @Nullable final String acceptLanguage) { return new RequestAttributes(REMOTE_ADDRESS, userAgent, acceptLanguage); }