Thanks Devon! So just to clarify our request flow is:
Client > CDN > Go Reverse Proxy > Origin Our Go Reverse Proxy has historically been responsible for adding caching headers (e.g. Cache-Control and Surrogate-Control) when the origins have failed to do so (as a way to ensure things are cached appropriately). It's unclear to me why you should be setting an etag header if you're a > proxy. > That's why when it came to looking at setting serve stale defaults for our origins (e.g. stale-while-revalidate and stale-if-error) I realized that somewhere along the chain an appropriate ETag/Last-Modified should be set and that's why I started wondering if our proxy should be responsible for setting them. Even then I felt like setting Last-Modified was way outside the responsibility of our proxy, but that maybe setting of ETag would have sufficed. Unless you're serving from the filesystem handler (which does > implement IMS/INM), you'll need to implement these yourself. > I think your other related answers might explain to me why the go reverse proxy doesn't support conditional requests, in that it's NOT a 'caching proxy' and so being able to handle that revalidation logic wouldn't make sense. > Note that you _could_ simply proxy this to the origin and let it > handle the validation. This is often overkill for what people actually > need, but it is guaranteed to work. > OK, so as we are indeed just proxying the request pretty much 'as is' to the origin, i.e. the CDN is making the revalidation conditional request when our stale-while-revalidate TTL expires, I'm guessing (I appreciate this is the 'basics' of how a proxy works, but I want to talk it through in case I'm mistaken in any way!) the go proxy will transparently keep that information for the origin to respond with the appropriate ETag/Last-Modified, and the go proxy again will transparently pass back their response through to the CDN to then update its cache if it indeed got a `200 OK` from origin or to continue serving stale if the origin returned a `304 Not Modified` (and in either case I expect the origin should send ETag/Last-Modified headers regardless of 200/304 status'). A hash function over the body of the response would constitute strong > validation. I'm not sure why you'd need to mix in the path; there's > nothing wrong with serving the exact same content between two > endpoints, and the ETag is tied to a response object. > Ah ok, so I was thinking along these lines, but was getting confused between content that is cached vs content that is rendered at 'runtime' (e.g. I was getting confused with the response containing a <script> tag that might dynamically change the adverts on the page depending on the client and wondering if that meant it wasn't "strong" validation just hashing the server response body, but I guess it's redundant thinking like that because the *actual* cached content is what's compared as far as the hash is concerned and not what the client-side scripting is modifying. On Tuesday, 6 August 2019 15:48:49 UTC+1, Devon H. O'Dell wrote: > > Hi Mark, > > Whether or not your proxy is caching, you may find RFC7234[1] relevant > in addressing some of your questions (as well as many you may later > encounter). I think you may find section 5.2 to be of particular > interest, though any proxy author should be familiar with the full > text. > > Op di 6 aug. 2019 om 05:14 schreef <mark...@gmail.com <javascript:>>: > > > > Hello, > > > > I'm using Go's standard library reverse proxy and I'm trying to figure > out if the standard library HTTP web server (e.g. http.ListenAndServe) > implements the relevant conditional request handling logic for > ETag/Last-Modified headers. > > > > I did some Googling and noticed the HTTP file system request handler ( > https://golang.org/src/net/http/fs.go) does implement that logic, but I > couldn't find the same for the HTTP web server. > > > > I also couldn't find any examples of setting ETags/Last-Modified (other > than this basic implementation for setting ETags: > https://github.com/go-http-utils/etag/blob/master/etag.go). > > > > What's confusing me there is the concept of "strong" and "weak" > validation and how certain scenarios might influence whether an ETag is > marked as either strong or weak (depending on the implementation -- see > https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests#Validators). > > > > > > So to recap, my questions are (and I appreciate some of these are > outside the scope of just Go -- so apologies if that's not allowed in this > forum): > > I think this is a fine question for this list, which isn't necessarily > constrained to questions about Go, but also for how to achieve things > while using Go. Lines get blurred since many technologies touch each > other. I don't think any apologies are necessary :). > > > 1. Should I set ETag/Last-Modified in a proxy? Last-Modified feels like > it's not the responsibility of the proxy but the origin, where as an ETag > is something I feel is "ok" to do in the proxy as a 'fallback' (as we > already set 'serve stale' caching headers on behalf of our origins if they > neglect to include them). > > ETag and Last-Modified should be sent by the origin to any proxy to > let the proxy know when the content is stale (assuming the proxy is > caching). The only case in which a proxy might set these things is if > there are configurations provided by the content owner that allow the > proxy to determine what the lifetime of the response object is outside > of response headers. This is most useful in cases where the content is > synthetically generated by the proxy as a result of the content > owner's configuration. If you don't have such a system in place, your > proxy should never be generating these response headers, and you > should be working with your customers / users to help them understand > when to set cache control headers. > > > 2. Do I need to implement `If-None-Match` and `If-Modified-Since` > behaviours myself (i.e. is it not provided by the Go standard library's > HTTP web server)? > > Unless you're serving from the filesystem handler (which does > implement IMS/INM), you'll need to implement these yourself. > > Note that you _could_ simply proxy this to the origin and let it > handle the validation. This is often overkill for what people actually > need, but it is guaranteed to work. > > One trick that many CDN providers leverage is to offer their customers > the option to serve the stale object while revalidating it. If that > option is set, an asynchronous revalidation request is spawned -- new > requests are blocked on the completion of that request -- and the > potentially stale content is served to the original requester without > blocking that request on revalidation. > > > 3. I was planning on setting an ETag header on the response from within > httputil.ReverseProxy#ModifyResponse but wasn't sure if that would be the > correct place to set it. > > It's unclear to me why you should be setting an etag header if you're a > proxy. > > > 4. What constitutes a strong/weak validator (e.g. would a simple hash > function generating a digest of the URL path + response body suffice)? > > A hash function over the body of the response would constitute strong > validation. I'm not sure why you'd need to mix in the path; there's > nothing wrong with serving the exact same content between two > endpoints, and the ETag is tied to a response object. > > Weak validation is signified by an additional "W/" in the etag > identifier. In practice, this means that you mustn't use weak > identifiers for serving byte-range requests. Weak identifiers may be > more useful for dynamically generated content where you might for > example have a date added in, or an ad server link that is rotated > each time the page is served, or a counter, or something like this. An > example of weak validation would be something that is version and > encoding based -- each time the content changes materially, you'd > increment the version, and some identifier for the content-encoding > would also be mixed in. > > > Thanks for any help/insights/opinions y'all can share with me. > > > > Kind regards, > > Mark > > > > Hope that helps! > > Kind regards, > > --dho > > [1]: https://tools.ietf.org/html/rfc7234 > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/a8da59d3-c905-4e13-8d15-3792a36c2f61%40googlegroups.com.