HTTP Header Key can be repeated?

2019-07-14 00:05发布

问题:

In JAVA HttpUrlConnection , the main logic code of request Header settings as following:

public synchronized void set(String k, String v) {
        for (int i = nkeys; --i >= 0;)
            if (k.equalsIgnoreCase(keys[i])) {
                values[i] = v;
                return;
            }
        add(k, v);
}

It is verified that the key should be unique, the key has to keep one to one mapping relationship with the value.

On the contrary, in HeaderFields of Response module, structure is defined as Entry >. That is, the key does not keep one to one mapping relationship with the value.

Why is this? Does the HTTP protocol has relevant agreement?

Add: In HttpClient4 ,the main logic code of request Header settings as following:

 /**
 * Replaces the first occurence of the header with the same name. If no header with
 * the same name is found the given header is added to the end of the list.
 *
 * @param header the new header that should replace the first header with the same
 * name if present in the list.
 */
public void updateHeader(final Header header) {
    if (header == null) {
        return;
    }
    // HTTPCORE-361 : we don't use the for-each syntax, i.e.
    //     for (Header header : headers)
    // as that creates an Iterator that needs to be garbage-collected
    for (int i = 0; i < this.headers.size(); i++) {
        final Header current = this.headers.get(i);
        if (current.getName().equalsIgnoreCase(header.getName())) {
            this.headers.set(i, header);
            return;
        }
    }
    this.headers.add(header);
}

Header of response

/**
 * Gets all of the headers with the given name.  The returned array
 * maintains the relative order in which the headers were added.
 *
 * <p>Header name comparison is case insensitive.
 *
 * @param name the name of the header(s) to get
 *
 * @return an array of length >= 0
 */
public Header[] getHeaders(final String name) {
    final List<Header> headersFound = new ArrayList<Header>();
    // HTTPCORE-361 : we don't use the for-each syntax, i.e.
    //     for (Header header : headers)
    // as that creates an Iterator that needs to be garbage-collected
    for (int i = 0; i < this.headers.size(); i++) {
        final Header header = this.headers.get(i);
        if (header.getName().equalsIgnoreCase(name)) {
            headersFound.add(header);
        }
    }

    return headersFound.toArray(new Header[headersFound.size()]);
}

They are the same of HttpUrlConnection

回答1:

Does the HTTP protocol has relevant agreement?

Yes. RFC 2616 Section 4.2 "Message Headers" says:

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.

This is expanded further by RFC 7230 Section 3.2.2 "Field Order":

A sender MUST NOT generate multiple header fields with the same field name in a message unless either the entire field value for that header field is defined as a comma-separated list [i.e., #(values)] or the header field is a well-known exception (as noted below).

A recipient MAY combine multiple header fields with the same field name into one "field-name: field-value" pair, without changing the semantics of the message, by appending each subsequent field value to the combined field value in order, 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; a proxy MUST NOT change the order of these field values when forwarding a message.



标签: http header