我有一个Web服务器,它会在响应中发出ETag
标头,并检查客户端的If-None-Match
标头(如果存在)。在这种情况下,客户端不是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
标头重定向到“http://foo.com/qux.html”。然后,我请求“http://foo.com/qux.html”并获得200 OK
以及ETag
标题。
我使用什么URL关联上一个响应的ETag
标题?
302 Found
本身是否包含ETag
标题?
答案 0 :(得分:3)
正如您在第266行的/src/pkg/net/http/client.go中所看到的,请求 - 响应周期将继续,直到或:
http.Client
的重定向检查器(CheckRedirect
字段)返回错误在循环期间,之前的响应将被丢弃,而client.Do
返回的响应的标题是最后一个响应的响应。
这意味着您应该在示例中将ETag
与qux.html
相关联。
302 Found本身是否包含ETag标题?
是的,但可以,但由于它是重定向,客户端将关注它并从目标网址获取一组新的响应标头。
答案 1 :(得分:2)
ETag与"选定的表示相关联"当前的请求。 302 Found响应的所选表示通常包含一个短超文本注释,其中包含指向不同URI的超链接。"因此,如果302响应包含ETag,则ETag与该超文本相关联。
但是,如果在对具有重定向响应的资源的请求中包含ETag,则服务器将忽略ETag。根据{{3}}(我的强调):
如果服务器对没有这些条件的同一请求的响应是2xx(成功)或412(前提条件失败)以外的状态代码,则它必须忽略所有收到的前提条件。换句话说,重定向和失败优先于条件请求中的前提条件评估。
因此,虽然302响应可以包含ETag,但它没有用,因为服务器可能不会在对该资源的进一步请求中使用它。