我有一个网络服务器,它在响应中发出 ETag
header ,并检查来自客户端的 If-None-Match
header (如果存在)。在这种情况下,客户端不是 Web 浏览器,而是 Go 内置 net/http
http.Client
类型的扩展。
这是我的代码
package util
import "net/http"
import "net/url"
type HttpClient struct {
http.Client
etags map[url.URL]string
}
func (hc *HttpClient) Do(req *http.Request) (*http.Response, error) {
const ETAG_SERVER_HEADER = "ETag"
const ETAG_CLIENT_HEADER = "If-None-Match"
//Do not attempt to use ETags on non-GET requests
if req.Method != "GET" {
return hc.Client.Do(req)
}
//Check for an existing etag
etag, ok := hc.etags[*req.URL]
if ok { //If an ETag is present, send it along
if req.Header == nil {
req.Header = http.Header{}
}
req.Header.Add(ETAG_CLIENT_HEADER, etag)
}
//Do the response
response, err := hc.Client.Do(req)
//If the response is ok
if err == nil {
if hc.etags == nil {
hc.etags = make(map[url.URL]string)
}
//Check for an ETAG from the server, store it if present
etag = response.Header.Get(ETAG_SERVER_HEADER)
if len(etag) != 0 {
hc.etags[*req.URL] = etag
}
}
return response, err
}
目前一切正常。
我仅为 GET
请求存储和发送 ETag。虽然为其他请求发送它们是有效的,但它不在我当前的用例中,所以我不会打扰它。通过将 url.URL
对象映射到字符串来存储 ETag。
我的问题是这样的。我请求“http://foo.com/bar.html”。服务器使用 302 Found
和 Location
header 将我重定向到“http://foo.com/qux.html”。然后我请求“http://foo.com/qux.html”并获得 200 OK
以及 ETag
header 。
我将上次响应的 ETag
header 与哪个 URL 相关联?
302 Found
本身可以包含一个 ETag
header 吗?
最佳答案
安ETag与当前请求的“选定表示”相关联。 302 Found 的选定表示响应“通常包含一个简短的超文本注释,带有指向不同 URI 的超链接。”因此,如果 302 响应包含 ETag,则 ETag 与该超文本相关联。
但是,如果您在对以重定向响应的资源的请求中包含 If-None-Match(或其他前提条件),服务器将忽略该前提条件。根据Section 5 of RFC 7232 (我的重点):
A server MUST ignore all received preconditions if its response to the same request without those conditions would have been a status code other than a 2xx (Successful) or 412 (Precondition Failed). In other words, redirects and failures take precedence over the evaluation of preconditions in conditional requests.
因此,虽然 302 响应可以包含 ETag,但它没有用,因为服务器可能不会在对该资源的进一步请求中使用它。
关于HTTP ETag 和 HTTP 重定向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23014106/