From 633a16c915ac4058831cd3bceb5ea51c56ce85d1 Mon Sep 17 00:00:00 2001 From: Nathan Erwin Date: Sun, 1 Oct 2023 11:00:28 -0400 Subject: [PATCH] Use java.util.Locale to parse the languages from the Accept-Language header * added some tests with various language tag scenarios * Fixes #36227 Signed-off-by:Nathan Erwin --- .../reactive/common/util/LocaleHelper.java | 16 +- .../vertx/test/headers/RequestHeaderTest.java | 172 ++++++++++++++++++ 2 files changed, 174 insertions(+), 14 deletions(-) create mode 100644 independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/headers/RequestHeaderTest.java diff --git a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/LocaleHelper.java b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/LocaleHelper.java index 5a67103d60b8d..2fb185d218cfe 100644 --- a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/LocaleHelper.java +++ b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/LocaleHelper.java @@ -11,15 +11,7 @@ public static Locale extractLocale(String lang) { if (q > -1) { lang = lang.substring(0, q); } - String[] split = lang.trim().split("-"); - if (split.length == 1) { - return new Locale(split[0].toLowerCase()); - } else if (split.length == 2) { - return new Locale(split[0].toLowerCase(), split[1].toLowerCase()); - } else if (split.length > 2) { - return new Locale(split[0], split[1], split[2]); - } - return null; // unreachable + return Locale.forLanguageTag(lang); } /** @@ -30,10 +22,6 @@ public static Locale extractLocale(String lang) { * @return converted language format string */ public static String toLanguageString(Locale value) { - StringBuffer buf = new StringBuffer(value.getLanguage().toLowerCase()); - if (value.getCountry() != null && !value.getCountry().equals("")) { - buf.append("-").append(value.getCountry().toLowerCase()); - } - return buf.toString(); + return value.toLanguageTag(); } } diff --git a/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/headers/RequestHeaderTest.java b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/headers/RequestHeaderTest.java new file mode 100644 index 0000000000000..bd65ef5d6edbd --- /dev/null +++ b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/headers/RequestHeaderTest.java @@ -0,0 +1,172 @@ +package org.jboss.resteasy.reactive.server.vertx.test.headers; + +import static org.hamcrest.Matchers.equalToIgnoringCase; + +import java.util.Locale; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.HttpHeaders; + +import org.jboss.resteasy.reactive.server.vertx.test.framework.ResteasyReactiveUnitTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.restassured.RestAssured; + +public class RequestHeaderTest { + + private static final String BASE_PATH = "/test"; + + @RegisterExtension + static ResteasyReactiveUnitTest TEST = new ResteasyReactiveUnitTest() + .addScanCustomizer(scanStep -> scanStep.setSingleDefaultProduces(true)) + .withApplicationRoot((jar) -> jar.addClasses(TestResource.class)); + + @Test + public void testISO2Language() { + String expected = "en"; + + RestAssured + .given() + .header(HttpHeaders.ACCEPT_LANGUAGE, expected) + .get(BASE_PATH) + .then() + .statusCode(200) + .assertThat().body(equalToIgnoringCase(expected)); + } + + @Test + public void testISO3Language() { + String expected = "tlh"; + + RestAssured + .given() + .header(HttpHeaders.ACCEPT_LANGUAGE, expected) + .get(BASE_PATH) + .then() + .statusCode(200) + .assertThat().body(equalToIgnoringCase(expected)); + } + + @Test + public void testScriptSubtag() { + String expected = "zh-Hans"; + + RestAssured + .given() + .header(HttpHeaders.ACCEPT_LANGUAGE, expected) + .get(BASE_PATH) + .then() + .statusCode(200) + .assertThat().body(equalToIgnoringCase(expected)); + } + + @Test + public void testRegionSubtag() { + String expected = "en-GB"; + + RestAssured + .given() + .header(HttpHeaders.ACCEPT_LANGUAGE, expected) + .get(BASE_PATH) + .then() + .statusCode(200) + .assertThat().body(equalToIgnoringCase(expected)); + } + + @Test + public void testRegionSubtag2() { + String expected = "es-005"; + + RestAssured + .given() + .header(HttpHeaders.ACCEPT_LANGUAGE, expected) + .get(BASE_PATH) + .then() + .statusCode(200) + .assertThat().body(equalToIgnoringCase(expected)); + } + + @Test + public void testRegionSubtag3() { + String expected = "zh-Hant-HK"; + + RestAssured + .given() + .header(HttpHeaders.ACCEPT_LANGUAGE, expected) + .get(BASE_PATH) + .then() + .statusCode(200) + .assertThat().body(equalToIgnoringCase(expected)); + } + + @Test + public void testVariantSubtag() { + String expected = "sl-nedis"; + + RestAssured + .given() + .header(HttpHeaders.ACCEPT_LANGUAGE, expected) + .get(BASE_PATH) + .then() + .statusCode(200) + .assertThat().body(equalToIgnoringCase(expected)); + } + + @Test + public void testVariantSubtag2() { + String expected = "sl-IT-nedis"; + + RestAssured + .given() + .header(HttpHeaders.ACCEPT_LANGUAGE, expected) + .get(BASE_PATH) + .then() + .statusCode(200) + .assertThat().body(equalToIgnoringCase(expected)); + } + + @Test + public void testExtensionSubtag() { + String expected = "de-DE-u-co-phonebk"; + + RestAssured + .given() + .header(HttpHeaders.ACCEPT_LANGUAGE, expected) + .get(BASE_PATH) + .then() + .statusCode(200) + .assertThat().body(equalToIgnoringCase(expected)); + } + + @Test + public void testPrivateUseSubtag() { + String expected = "en-US-x-twain"; + + RestAssured + .given() + .header(HttpHeaders.ACCEPT_LANGUAGE, expected) + .get(BASE_PATH) + .then() + .statusCode(200) + .assertThat().body(equalToIgnoringCase(expected)); + } + + @Path(BASE_PATH) + public static class TestResource { + + @Context + HttpHeaders headers; + + @GET + public String echo() { + final Locale locale = headers.getAcceptableLanguages().isEmpty() ? Locale.ENGLISH + : headers.getAcceptableLanguages().get(0); + + return locale.toLanguageTag(); + } + + } +}