Skip to content

Consistent handling of multi-valued headers in HttpHeaders [SPR-14223] #18797

Closed
@spring-projects-issues

Description

@spring-projects-issues

Sebastiaan van Erk opened SPR-14223 and commented

The org.springframework.http.HttpHeaders class wraps HTTP request headers and makes them easy to work with (e.g., parsing HTTP dates such as in the Last-Modified header) for you.

However, it treats multi-valued headers incorrectly in my opinion. From RFC2616 https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2:

Multiple message-header fields with the same field-name MAY be present in a message if and only if the entire field-value for that header field is defined as a comma-separated list [i.e., #(values)]. It MUST be possible to combine the multiple header fields into one "field-name: field-value" pair, without changing the semantics of the message, by appending each subsequent field-value to the first, each separated by a comma. The order in which header fields with the same field-name are received is therefore significant to the interpretation of the combined field value, and thus a proxy MUST NOT change the order of these field values when a message is forwarded.

Thus, it seems to me that the following sets of headers mean the same thing:

X-List: a, b, c

X-List: a
X-List: b
X-List: c

X-List: a, b
X-List: c

In all cases the header value of the X-List header is the list of strings "a", "b", "c". Note that a proxy may convert the second or third form to the first form.

According to the documentation on HttpHeaders:

getFirst(String) returns the first value associated with a given header name

I would expect in all 3 cases that getFirst("X-List") returns the string "a". However this is not the case. In the first case it returns "a, b, c", in the second case "a", and in the third case "a, b".

Note that this is actually a problem in the handling of some of the headers (the various Access-Control headers, the If-None-Match header), because they call getFirst or getFirstValueAsList. But this way they ignore any values in repeated headers, which are valid and should be appended to the list according to the RFC.

Since the processing of multiple header values is rather complicated, it would be really helpful if the HttpHeaders class removed this complexity from the API user.

NOTE:

As commented in #18790, there is a problem with the method to split the header into values (getFirstValueAsList): the values themselves may contain commas (ETags are an example of this). It seems that to split the header you need to understand the syntax of the values themselves. I don't see how one could implement this correctly for the generic case (e.g., unknown X-* headers). However, for the known HTTP headers it should be possible to split the list correctly.


Affects: 4.2.5

Issue Links:

Referenced from: commits 55dae61

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions