I have a webserver that issues the ETag
header on responses and checks the If-None-Match
header from the client, if present. The client in this case, is not a web browser but an extension of go's builtin net/http
http.Client
type.
Here is my code
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
}
It is working without issue as of present.
I am only storing and sending the ETag for GET
requests. While it is valid to send them for other requests, it is not in my use case as of current so I'm not bothering with it. The ETags are stored by mapping the url.URL
object to a string.
My question is this. I request "http://foo.com/bar.html". The server redirects me using 302 Found
and the Location
header to "http://foo.com/qux.html". I then request "http://foo.com/qux.html" and get a 200 OK
along with an ETag
header.
With what URL do I associate the ETag
header from the last response?
Could the 302 Found
itself include an ETag
header?
An ETag is associated with the "selected representation" of the current request. The selected representation for a 302 Found response "usually contains a short hypertext note with a hyperlink to the different URI(s)." Therefore, if a 302 response contains an ETag, the ETag is associated with that hypertext.
However, if you include an If-None-Match (or other precondition) in a request to a resource that responds with a redirect, the server will ignore the precondition. According to Section 5 of RFC 7232 (my emphasis):
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.
Thus, while a 302 response can contain an ETag, it is not useful because the server may not use it in further requests to that resource.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With