-
Notifications
You must be signed in to change notification settings - Fork 4
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
Add cache issuer directory #15
Conversation
Insatead of computing the issuer directory whenever requested, cache it with the same setting used by clients. This cache is clearer upon key rotation. This commit also allows cache time to be configured per deployment.
Disable eslint no-unused-variable for handler. `request` does not have to be used, and it's good to have a consistent signature for the handlers.
To enable monitoring of cache miss, a dedicated prometheus metric is added.
With the multiplication of metrics, use alphabetical ordering to ease searches.
this.requestsTotal = this.registry.create('counter', 'requests_total', 'total requests'); | ||
this.directoryCacheMissTotal = this.registry.create( | ||
'counter', | ||
'directory_cache_miss_total', |
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.
the metric counts cache miss. It is also possible to devise a metric directory_cache_request_total{status="hit|miss"}
. However, I feel this would add uneccessary weight.
The response is pretty small (about 569 bytes). This PR tackles edge-side caching. Do you also want to attempt to address client-side caching? If you include a See https://gitlab.com/wireshark/ws-cloudflare-workers/-/blob/71ff179cbb71eed0242b0442eeaf571727b8de97/wiki-worker/src/index.js#L226-238 for an example if you are interested in that. I did not see the Last-Modified or ETag headers in production, but in dev I do see that it is being ignored.
I originally tried HEAD to test the endpoint, but there appears to be a bug there: #16 |
@Lekensteyn I've added a commit to support HEAD, and provide an Etag. If Etag on the request matches, 304 is returned. HEAD is only stripping GET body if there is one, to make sure the headers are correct. In addition, it adds |
src/index.ts
Outdated
@@ -179,6 +236,7 @@ export default { | |||
const router = new Router(); | |||
|
|||
router | |||
.head(PRIVATE_TOKEN_ISSUER_DIRECTORY, handleHeadTokenDirectory) |
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 think that head
method should be dropped, head
should be automatically added for all GET requests by the underlying router as suggested in #16 with appropriate tests verifying that behavior.
You do not have to go our of your way to omit the body in the Response constructor. The underlying Workers runtime will skip inclusion of the the body for HEAD requests.
The advantage of using the same implementation is that your response (headers) will be the same with no extra effort.
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.
updated
headers: { | ||
'content-type': MediaType.PRIVATE_TOKEN_ISSUER_DIRECTORY, | ||
'cache-control': 'public, max-age=86400', | ||
'cache-control': `public, max-age=${ctx.env.DIRECTORY_CACHE_MAX_AGE_SECONDS}`, | ||
'content-length': body.length.toString(), |
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.
Question: Isn't content-length automatically set? Or is it missing due to chunked encoding being used?
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.
when I first tested, it did not seem to be set automatically. therefore adding it here. The question I have is if the request is compressed, I'm not sure if it's modified automatically.
'cache-control': 'public, max-age=86400', | ||
'cache-control': `public, max-age=${ctx.env.DIRECTORY_CACHE_MAX_AGE_SECONDS}`, | ||
'content-length': body.length.toString(), | ||
'date': new Date().toUTCString(), |
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.
Date is not that important for caching, has this been added for debugging purposes?
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.
it's been added to help debugging if there are caching issues in the future.
Browsers might send `HEAD` request to understand if they should do a `GET` request. This commit adds an ETag on response, allowing `If-None-Match` to be handled, as well as `HEAD` request to be correctly processed.
de8f900
to
6482ab3
Compare
this.issuanceRequestTotal = this.registry.create( | ||
'counter', | ||
'issuance_request_total', | ||
'Number of requests for private token issuance.' |
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.
successful?
'Number of requests for private token issuance.' | |
'Number of successful requests for private token issuance.' |
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.
not necessary successful. the metric is increased at the start of handleTokenRequest
, no matter the response.
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.
side: this is also not a new metrics. The metrics have been sorted by alphabetical orders, and it's part of this change.
src/index.ts
Outdated
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
export const handleRotateKey = async (ctx: Context, request?: Request) => { |
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.
You can remove the linter exception and prepend variable's name with _
.
// eslint-disable-next-line @typescript-eslint/no-unused-vars | |
export const handleRotateKey = async (ctx: Context, request?: Request) => { | |
export const handleRotateKey = async (ctx: Context, _request?: Request) => { |
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.
the rule triggered a warning in both case. I've added a rule configuration to ignore ^_
, which _request
is.
The former has not been updated in 5 years.
once merged |
To reduce the number of calls to R2, with an expensive list operation, add cache in front of issuer directory endpoint.
It's worth noting that this change does not affect token issuance. The key is still retrieve for every issuance, incurring a class A operation.