Skip to content

Conversation

schnapster
Copy link
Contributor

Something I'm seeing in the wild is a trailing semicolon for Accept-Language headers. Partial example stack trace:

java.lang.IllegalArgumentException: range=en;
    at java.util.Locale$LanguageRange.<init>(Locale.java:3099)
    at sun.util.locale.LocaleMatcher.parse(LocaleMatcher.java:525)
    at java.util.Locale$LanguageRange.parse(Locale.java:3214)
    at org.springframework.http.HttpHeaders.getAcceptLanguage(HttpHeaders.java:505)
    at org.springframework.http.HttpHeaders.getAcceptLanguageAsLocales(HttpHeaders.java:526)

I don't think it would hurt to be more lenient here and drop the trailing semicolon before attempting to parse it.

@pivotal-cla
Copy link

@schnapster Please sign the Contributor License Agreement!

Click here to manually synchronize the status of this Pull Request.

See the FAQ for frequently asked questions.

@pivotal-cla
Copy link

@schnapster Thank you for signing the Contributor License Agreement!

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Feb 13, 2024
@schnapster schnapster force-pushed the accept-language-header-trailing-semicolon branch from f456d26 to a3323de Compare February 13, 2024 15:59
@sbrannen sbrannen added the in: web Issues in web modules (web, webmvc, webflux, websocket) label Feb 13, 2024
@sbrannen sbrannen changed the title Handle trailing semicolon when parsing Accept-Language header Ignore trailing semicolons when parsing Accept-Language header Feb 13, 2024
Copy link
Contributor

@rstoyanchev rstoyanchev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@schnapster, the header is parsed via Locale.LanguageRange.parse, which supports a weighted list of ranges where each may have a q parameter. However, the parsing logic doesn't allow a lot of flexibility and looks specifically for ";q=". Note also it first splits by , to create a list of range value. So the problem may still occur if there is a trailing ; in one of the other ranges.

We don't want to replicate the parsing logic from Locale, but we may be able to do a split by , and then check for invalid ";" in each. However, this is better done defensively, i.e. allowing parsing to fail first and then reacting to that in fallback mode.

@rstoyanchev rstoyanchev added the status: waiting-for-feedback We need additional information before we can continue label Feb 15, 2024
@@ -502,6 +502,9 @@ public void setAcceptLanguage(List<Locale.LanguageRange> languages) {
*/
public List<Locale.LanguageRange> getAcceptLanguage() {
String value = getFirst(ACCEPT_LANGUAGE);
if (value != null) {
value = StringUtils.trimTrailingCharacter(value, ';');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

';' should be a variable

@@ -502,6 +502,9 @@ public void setAcceptLanguage(List<Locale.LanguageRange> languages) {
*/
public List<Locale.LanguageRange> getAcceptLanguage() {
String value = getFirst(ACCEPT_LANGUAGE);
if (value != null) {
Copy link

@kmesiab kmesiab Feb 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I think a null check is fine, why not also validate whether this string is non empty and at least [n] chars and avoid the noop?

@poutsma poutsma self-assigned this Apr 30, 2024
@schnapster
Copy link
Contributor Author

@rstoyanchev apologies for the late follow-up, I'm a bit out of the loop on this by now. Could you please provide a concrete header to demonstrate your example? Or ideally a (pseudo-cody) test case similar to the one I added? I'd be happy to take another stab at this if I understand better what the additional faults are that you want Spring to be able to handle. We can also handle that in another issue / PR, imho this one already provides incremental value by itself.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels May 19, 2024
@poutsma poutsma added type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jun 12, 2024
@poutsma poutsma closed this in 099d016 Jun 12, 2024
@poutsma
Copy link
Contributor

poutsma commented Jun 12, 2024

@schnapster Thank you for submitting a PR. I have combined your code and the suggestions of @rstoyanchev into 099d016.

@poutsma poutsma added this to the 6.2.0-M4 milestone Jun 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: feedback-provided Feedback has been provided type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants