-
Couldn't load subscription status.
- Fork 38.8k
Description
Sending accept-language with a quality value such as Accept-Language: en-us, en-BA;q=0.1 is part of the ietf standard in https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.5
When this is sent and the code uses @RequestHeader(HttpHeaders.ACCEPT_LANGUAGE) Locale locale) the framework throws a MethodArgumentTypeMismatchException due to
private static void validateLocalePart(String localePart) {
for (int i = 0; i < localePart.length(); i++) {
char ch = localePart.charAt(i);
if (ch != ' ' && ch != '_' && ch != '-' && ch != '#' && !Character.isLetterOrDigit(ch)) {
throw new IllegalArgumentException(
"Locale part \"" + localePart + "\" contains invalid characters");
}
}
}being called from
https://github.com/spring-projects/spring-framework/blob/main/spring-core/src/main/java/org/springframework/core/convert/support/StringToLocaleConverter.java#L41
There are easy workarounds such as simply removing the @RequestHeader annotation or using the Tomcat HttpServletRequest getLocale() method which uses https://github.com/apache/tomcat/blob/main/java/org/apache/catalina/connector/Request.java#L2951
@RestController
public class TestLocale {
private final HttpServletRequest httpServletRequest;
@Autowired
public TestLocale(final HttpServletRequest httpServletRequest) {
this.httpServletRequest = httpServletRequest;
}
// Works with "en-us". Fails with "en-us, en-BA;q=0.1"
@GetMapping(path = "/test-header")
public String localeUsingHeader(@RequestHeader(HttpHeaders.ACCEPT_LANGUAGE) Locale locale) {
return locale.toLanguageTag();
}
// Works with "en-us" and with "en-us, en-BA;q=0.1"
@GetMapping(path = "/test-servlet")
public String testServlet() {
return httpServletRequest.getLocale().toLanguageTag();
}
// Works with "en-us" and with "en-us, en-BA;q=0.1"
@GetMapping(path = "/test-locale")
public String testLocale(Locale locale) {
return locale.toLanguageTag();
}
}The full request being sent
curl --location 'http://localhost:8080/test-header' \
--header 'Content-Type: application/json' \
--header 'Accept-Language: en-us, en-BA;q=0.1' \
--header 'Accept: application/json'