HTTP头部键可以重复吗?

6
在JAVA的HttpUrlConnection中,请求头设置的主要逻辑代码如下所示:
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);
}

验证了关键字应该是唯一的,关键字必须与值保持一对一的映射关系。

相反,在响应模块的HeaderFields中,结构被定义为Entry >。也就是说,关键字与值不保持一对一的映射关系。

为什么会这样?HTTP协议有相关的协定吗?

添加: 在HttpClient4中,请求头设置的主要逻辑代码如下:

 /**
 * 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);
}

响应头部

/**
 * 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()]);
}

他们与HttpUrlConnection相同。
1个回答

15
HTTP协议有相关协议吗?
是的。RFC 2616 Section 4.2 "Message Headers"指出:
如果且仅当整个字段值被定义为逗号分隔列表(即#(values)),则可以在消息中使用具有相同字段名称的多个消息头字段。必须能够通过将每个后续字段值附加到第一个字段值,每个字段值之间用逗号分隔,将多个标头字段组合成一个“field-name:field-value”对,而不更改消息的语义。因此,接收具有相同字段名称的标题字段的顺序对于解释组合字段值至关重要,因此代理在转发消息时不得更改这些字段值的顺序。 RFC 7230 Section 3.2.2 "Field Order"进一步扩展了此内容:
发送方在消息中不得生成具有相同字段名称的多个标头字段,除非该标头字段的整个字段值被定义为逗号分隔的列表(即#(values)),或者该标头字段是众所周知的例外情况(如下所述)。 收件人可以将具有相同字段名称的多个标头字段组合成一个“field-name:field-value”对,通过将每个后续字段值按顺序附加到组合字段值中以逗号分隔的方式,而不改变消息的语义。因此,接收到具有相同字段名称的标头字段的顺序对于解释组合字段值至关重要;代理在转发消息时不得更改这些字段值的顺序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接