-
Couldn't load subscription status.
- Fork 230
Cache busting #284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cache busting #284
Conversation
|
/cc @apelisse |
|
/assign @apelisse |
|
@Jefftree: GitHub didn't allow me to request PR reviews from the following users: alexzielenski. Note that only kubernetes members and repo collaborators can review this PR, and authors cannot review their own PRs. In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
pkg/handler3/handler.go
Outdated
| if err != nil { | ||
| return nil, err | ||
| } | ||
| discovery.Paths[k] = "openapi/v3/" + k + "?hash=" + unquoteETag(etag) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While consuming this API in a test I found it a bit unwieldy. I expected discovery.Paths to be a groupVersion -> ETAG map, rather than a groupVersion -> path map. I ended up using url.Parse to extract the hash query param from the path since the client-go discovery client for OpenAPI V3 asks for the hash by itself.
Also it is worth pointing out that in the future more query params may be added to the OpenAPI endpoints, so it may become inconvenient to deal with these paths with an assumed URL structure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may also in the future end up wanting to extend the discovery map to include additional metadata. Should the type of discovery.Paths[k] be a map[string]interface{} rather than simply a string? So that for example the response might be:
{
"paths": {
"batch/v1": {
"hash": <ETAG>
}
}
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't disagree with that, but it should be a URL rather than the hash so it's built automatically (clients shouldn't even have to know what to do with the hash, it should just contain the URL they need to download as a relative link).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While consuming this API in a test I found it a bit unwieldy. I expected discovery.Paths to be a groupVersion -> ETAG map, rather than a groupVersion -> path map. I ended up using url.Parse to extract the hash query param from the path since the client-go discovery client for OpenAPI V3 asks for the hash by itself.
Interesting, why didn't you just want to download the relative path given?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may also in the future end up wanting to extend the discovery map to include additional metadata.
Good idea, I'll change the structure.
I ended up using url.Parse to extract the hash query param from the path since the client-go discovery client
Thanks for catching this inconsistency. Question for both of you: Would it make more sense for the client-go interface to directly consume the URL (eg: OpenAPISchema(URL string)) instead of the current OpenAPISchema(gvPath, hash string). I agree we shouldn't assume an URL structure and going the route of parsing the URL may add more complexity in the future
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't disagree with that, but it should be a URL rather than the hash so it's built automatically (clients shouldn't even have to know what to do with the hash, it should just contain the URL they need to download as a relative link).
In that case a URL could be included as one of the keys in the map I proposed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed the Discovery schema format to
{
"paths": {
"apis/batch/v1": {
"url": "/openapi/v3/apis/batch/v1?hash=XXX"
}
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I don't disagree that having an object rather than a direct mapping gives us more flexibility in the future, but we shouldn't need the hash per-se.
pkg/handler3/handler.go
Outdated
| if err != nil { | ||
| return nil, err | ||
| } | ||
| discovery.Paths[k] = "openapi/v3/" + k + "?hash=" + unquoteETag(etag) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't disagree with that, but it should be a URL rather than the hash so it's built automatically (clients shouldn't even have to know what to do with the hash, it should just contain the URL they need to download as a relative link).
ba6b055 to
768107d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks clean. Very minor nits
pkg/handler3/handler.go
Outdated
| if hash := r.URL.Query().Get("hash"); hash != "" && hash != etag { | ||
| u := constructURL(group, etag) | ||
| http.Redirect(w, r, u, 301) | ||
| return | ||
| } | ||
| applyCacheBusting(w, r, etag) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Piling up on Alex's comment, a lot of the conditions here are very similar to the conditions in applyCacheBusting. Try to remove the applyCacheBusting method below and move the code here, I think you'll be able to do a few other simplifications.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since I don't code enough these days, I'll do it for fun. Not addressing the Vary comment.
| if hash := r.URL.Query().Get("hash"); hash != "" && hash != etag { | |
| u := constructURL(group, etag) | |
| http.Redirect(w, r, u, 301) | |
| return | |
| } | |
| applyCacheBusting(w, r, etag) | |
| if hash := r.URL.Query().Get("hash"); hash != "" { | |
| // The Vary header is required because the Accept header can | |
| // change the contents returned. This prevents clients from caching | |
| // protobuf as JSON and vice versa. | |
| // Do you need Vary in the 301?! | |
| w.Header().Set("Vary", "*") | |
| if hash != etag { | |
| u := constructURL(group, etag) | |
| http.Redirect(w, r, u, 301) | |
| return | |
| } | |
| // Only set these headers when a hash is given. | |
| w.Header().Set("Cache-Control", "public, immutable") | |
| // Set the Expires directive to the maximum value of one year from the request, | |
| // effectively indicating that the cache never expires. | |
| w.Header().Set("Expires", time.Now().AddDate(1, 0, 0).Format(time.RFC1123)) | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we're not redirecting if no hash is given?
|
/lgtm |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: apelisse, Jefftree The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Support Cache Busting in kube-openapi.
Also fix a bug where lazy marshaling wasn't performed on OpenAPI V3.