Uploaded image for project: 'Spring Framework'
  1. Spring Framework
  2. SPR-14223

Consistent handling of multi-valued headers in HttpHeaders

    XMLWordPrintable

    Details

    • Type: Improvement
    • Status: Closed
    • Priority: Major
    • Resolution: Complete
    • Affects Version/s: 4.2.5
    • Fix Version/s: 4.3 RC2
    • Component/s: Web
    • Labels:
      None
    • Last commented by a User:
      true

      Description

      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 https://jira.spring.io/browse/SPR-14216, 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.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              bclozel Brian Clozel
              Reporter:
              sebster Sebastiaan van Erk
              Last updater:
              Spring Issuemaster
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:
                Days since last comment:
                1 year, 40 weeks, 6 days ago