{"action":"created","comment":{"url":"https://api.github.com/repos/badges/shields/pulls/comments/234459675","pull_request_review_id":176103722,"id":234459675,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIzNDQ1OTY3NQ==","diff_hunk":"@@ -143,25 +152,18 @@ describe('The request handler', function() {\n       })\n \n       it('should set Cache-Control: no-cache, no-store, must-revalidate if maxAge=0', async function() {\n-        process.env.BADGE_MAX_AGE_SECONDS = 0\n+        register({ cacheHeaderConfig: { defaultCacheLengthSeconds: 0 } })\n         const res = await fetch(`${baseUri}/testing/123.json`)\n         expect(res.headers.get('expires')).to.equal(res.headers.get('date'))\n         expect(res.headers.get('cache-control')).to.equal(\n           'no-cache, no-store, must-revalidate'\n         )\n       })\n \n-      it('should set the expires header to current time + 120 if BADGE_MAX_AGE_SECONDS not set', async function() {","path":"lib/request-handler.spec.js","position":160,"original_position":160,"commit_id":"22e3eaa49acb7f817c71c1006760778d3cac78d1","original_commit_id":"22e3eaa49acb7f817c71c1006760778d3cac78d1","user":{"login":"paulmelnikow","id":1487036,"node_id":"MDQ6VXNlcjE0ODcwMzY=","avatar_url":"https://avatars2.githubusercontent.com/u/1487036?v=4","gravatar_id":"","url":"https://api.github.com/users/paulmelnikow","html_url":"https://github.com/paulmelnikow","followers_url":"https://api.github.com/users/paulmelnikow/followers","following_url":"https://api.github.com/users/paulmelnikow/following{/other_user}","gists_url":"https://api.github.com/users/paulmelnikow/gists{/gist_id}","starred_url":"https://api.github.com/users/paulmelnikow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paulmelnikow/subscriptions","organizations_url":"https://api.github.com/users/paulmelnikow/orgs","repos_url":"https://api.github.com/users/paulmelnikow/repos","events_url":"https://api.github.com/users/paulmelnikow/events{/privacy}","received_events_url":"https://api.github.com/users/paulmelnikow/received_events","type":"User","site_admin":false},"body":"This functionality was removed. Responsibility for setting the default is now with `server-config`.","created_at":"2018-11-18T20:09:21Z","updated_at":"2018-11-18T20:16:31Z","html_url":"https://github.com/badges/shields/pull/2360#discussion_r234459675","pull_request_url":"https://api.github.com/repos/badges/shields/pulls/2360","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/badges/shields/pulls/comments/234459675"},"html":{"href":"https://github.com/badges/shields/pull/2360#discussion_r234459675"},"pull_request":{"href":"https://api.github.com/repos/badges/shields/pulls/2360"}}},"pull_request":{"url":"https://api.github.com/repos/badges/shields/pulls/2360","id":231810396,"node_id":"MDExOlB1bGxSZXF1ZXN0MjMxODEwMzk2","html_url":"https://github.com/badges/shields/pull/2360","diff_url":"https://github.com/badges/shields/pull/2360.diff","patch_url":"https://github.com/badges/shields/pull/2360.patch","issue_url":"https://api.github.com/repos/badges/shields/issues/2360","number":2360,"state":"open","locked":false,"title":"Refactor cache-header handling and config, create NoncachingBaseService, rewrite [flip]","user":{"login":"paulmelnikow","id":1487036,"node_id":"MDQ6VXNlcjE0ODcwMzY=","avatar_url":"https://avatars2.githubusercontent.com/u/1487036?v=4","gravatar_id":"","url":"https://api.github.com/users/paulmelnikow","html_url":"https://github.com/paulmelnikow","followers_url":"https://api.github.com/users/paulmelnikow/followers","following_url":"https://api.github.com/users/paulmelnikow/following{/other_user}","gists_url":"https://api.github.com/users/paulmelnikow/gists{/gist_id}","starred_url":"https://api.github.com/users/paulmelnikow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paulmelnikow/subscriptions","organizations_url":"https://api.github.com/users/paulmelnikow/orgs","repos_url":"https://api.github.com/users/paulmelnikow/repos","events_url":"https://api.github.com/users/paulmelnikow/events{/privacy}","received_events_url":"https://api.github.com/users/paulmelnikow/received_events","type":"User","site_admin":false},"body":"There's a lot going on in this PR, though it's all interdependent, so the only way I can see to break it up into smaller pieces would be serially.\r\n\r\n1. I completely refactored the functions for managing cache headers. These have been added to `services/cache-headers.js`, and in some ways set the stage for the rest of this PR.\r\n\r\n    - As there are ample higher-level test of the functionality via `request-handler`, there are few unit tests of these functions. Refactoring the tests and writing new tests was deferred. Cache headers were previously dealt with in three places:\r\n        - `request-handler.js`, for the dynamic badges. This function now calls `setCacheHeaders`.\r\n        - `base-static.js`, for the static badges. This method now calls the wordy `serverHasBeenUpSinceResourceCached` and `setCacheHeadersForStaticResource`.\r\n        - The bitFlip badge in `server.js`. 👈 This is what set all this in motion. This badge has been refactored to a new-style service based on a new `NoncachingBaseService` which does not use the Shields in-memory cache that the dynamic badges user.\r\n    - I'm open to clearer names for `NoncachingBaseService`, which is kind of terrible. Absent alternatives, I wrote a short essay of clarification in the docstring. 😝 \r\n\r\n2. In the process of writing `NoncachingBaseService`, I discovered it takes several lines of code to instantiate and invoke a service. These would be duplicated in three or four places in production code, and in lots and lots of tests. I kept the line that goes from regex to namedParams (for reasons) and moved the rest into a static method called `invoke()`, which instantiates and invokes the service. This _replaced_ the instance method `invokeHandler`.\r\n    - I gently reworked the unit tests to use `invoke` instead of `invokeHandler`– generally for the better.\r\n    - I made a small change to `BaseStatic`. Now it invokes `handle()` async as the dynamic badges do. This way it could use `BaseService.invoke()`.\r\n\r\n3. There was logic in `request-handler` for processing environment variables, validating them, and setting defaults. This could have been lifted whole-hog to `services/cache-headers.js`, though I didn't do that. Instead I moved it to `server-config.js`. Ideally `server-config` is the only module that should access `process.env`. This puts the defaults and config validation in one place, decouples the config schema from the entire rest of the application, and significantly simplifies our ability to test different configs, particularly on small units of code. (We were doing this well enough before in `request-handler.spec`, though it required mutating the environment, which was kludgy.) Some of the `request-handler` tests could be rewritten at a higher level, with lower-level data-driven tests directly against `cache-headers`.","created_at":"2018-11-18T20:05:33Z","updated_at":"2018-11-18T20:16:30Z","closed_at":null,"merged_at":null,"merge_commit_sha":"698199d6d6ce70a8051b5c60c68126a1c223900e","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":1129114825,"node_id":"MDU6TGFiZWwxMTI5MTE0ODI1","url":"https://api.github.com/repos/badges/shields/labels/blocker","name":"blocker","color":"fe7d37","default":false},{"id":585616182,"node_id":"MDU6TGFiZWw1ODU2MTYxODI=","url":"https://api.github.com/repos/badges/shields/labels/core","name":"core","color":"c5def5","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/badges/shields/pulls/2360/commits","review_comments_url":"https://api.github.com/repos/badges/shields/pulls/2360/comments","review_comment_url":"https://api.github.com/repos/badges/shields/pulls/comments{/number}","comments_url":"https://api.github.com/repos/badges/shields/issues/2360/comments","statuses_url":"https://api.github.com/repos/badges/shields/statuses/22e3eaa49acb7f817c71c1006760778d3cac78d1","head":{"label":"badges:noncaching","ref":"noncaching","sha":"22e3eaa49acb7f817c71c1006760778d3cac78d1","user":{"login":"badges","id":6254238,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYyNTQyMzg=","avatar_url":"https://avatars2.githubusercontent.com/u/6254238?v=4","gravatar_id":"","url":"https://api.github.com/users/badges","html_url":"https://github.com/badges","followers_url":"https://api.github.com/users/badges/followers","following_url":"https://api.github.com/users/badges/following{/other_user}","gists_url":"https://api.github.com/users/badges/gists{/gist_id}","starred_url":"https://api.github.com/users/badges/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/badges/subscriptions","organizations_url":"https://api.github.com/users/badges/orgs","repos_url":"https://api.github.com/users/badges/repos","events_url":"https://api.github.com/users/badges/events{/privacy}","received_events_url":"https://api.github.com/users/badges/received_events","type":"Organization","site_admin":false},"repo":{"id":7910045,"node_id":"MDEwOlJlcG9zaXRvcnk3OTEwMDQ1","name":"shields","full_name":"badges/shields","private":false,"owner":{"login":"badges","id":6254238,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYyNTQyMzg=","avatar_url":"https://avatars2.githubusercontent.com/u/6254238?v=4","gravatar_id":"","url":"https://api.github.com/users/badges","html_url":"https://github.com/badges","followers_url":"https://api.github.com/users/badges/followers","following_url":"https://api.github.com/users/badges/following{/other_user}","gists_url":"https://api.github.com/users/badges/gists{/gist_id}","starred_url":"https://api.github.com/users/badges/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/badges/subscriptions","organizations_url":"https://api.github.com/users/badges/orgs","repos_url":"https://api.github.com/users/badges/repos","events_url":"https://api.github.com/users/badges/events{/privacy}","received_events_url":"https://api.github.com/users/badges/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/badges/shields","description":"Concise, consistent, and legible badges in SVG and raster format","fork":false,"url":"https://api.github.com/repos/badges/shields","forks_url":"https://api.github.com/repos/badges/shields/forks","keys_url":"https://api.github.com/repos/badges/shields/keys{/key_id}","collaborators_url":"https://api.github.com/repos/badges/shields/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/badges/shields/teams","hooks_url":"https://api.github.com/repos/badges/shields/hooks","issue_events_url":"https://api.github.com/repos/badges/shields/issues/events{/number}","events_url":"https://api.github.com/repos/badges/shields/events","assignees_url":"https://api.github.com/repos/badges/shields/assignees{/user}","branches_url":"https://api.github.com/repos/badges/shields/branches{/branch}","tags_url":"https://api.github.com/repos/badges/shields/tags","blobs_url":"https://api.github.com/repos/badges/shields/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/badges/shields/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/badges/shields/git/refs{/sha}","trees_url":"https://api.github.com/repos/badges/shields/git/trees{/sha}","statuses_url":"https://api.github.com/repos/badges/shields/statuses/{sha}","languages_url":"https://api.github.com/repos/badges/shields/languages","stargazers_url":"https://api.github.com/repos/badges/shields/stargazers","contributors_url":"https://api.github.com/repos/badges/shields/contributors","subscribers_url":"https://api.github.com/repos/badges/shields/subscribers","subscription_url":"https://api.github.com/repos/badges/shields/subscription","commits_url":"https://api.github.com/repos/badges/shields/commits{/sha}","git_commits_url":"https://api.github.com/repos/badges/shields/git/commits{/sha}","comments_url":"https://api.github.com/repos/badges/shields/comments{/number}","issue_comment_url":"https://api.github.com/repos/badges/shields/issues/comments{/number}","contents_url":"https://api.github.com/repos/badges/shields/contents/{+path}","compare_url":"https://api.github.com/repos/badges/shields/compare/{base}...{head}","merges_url":"https://api.github.com/repos/badges/shields/merges","archive_url":"https://api.github.com/repos/badges/shields/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/badges/shields/downloads","issues_url":"https://api.github.com/repos/badges/shields/issues{/number}","pulls_url":"https://api.github.com/repos/badges/shields/pulls{/number}","milestones_url":"https://api.github.com/repos/badges/shields/milestones{/number}","notifications_url":"https://api.github.com/repos/badges/shields/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/badges/shields/labels{/name}","releases_url":"https://api.github.com/repos/badges/shields/releases{/id}","deployments_url":"https://api.github.com/repos/badges/shields/deployments","created_at":"2013-01-30T07:41:54Z","updated_at":"2018-11-18T19:26:31Z","pushed_at":"2018-11-18T20:10:29Z","git_url":"git://github.com/badges/shields.git","ssh_url":"git@github.com:badges/shields.git","clone_url":"https://github.com/badges/shields.git","svn_url":"https://github.com/badges/shields","homepage":"https://shields.io","size":13423,"stargazers_count":6603,"watchers_count":6603,"language":"JavaScript","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":1511,"mirror_url":null,"archived":false,"open_issues_count":202,"license":{"key":"cc0-1.0","name":"Creative Commons Zero v1.0 Universal","spdx_id":"CC0-1.0","url":"https://api.github.com/licenses/cc0-1.0","node_id":"MDc6TGljZW5zZTY="},"forks":1511,"open_issues":202,"watchers":6603,"default_branch":"master"}},"base":{"label":"badges:master","ref":"master","sha":"842f54520734c44b3775a03cdafdb53b49a14df7","user":{"login":"badges","id":6254238,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYyNTQyMzg=","avatar_url":"https://avatars2.githubusercontent.com/u/6254238?v=4","gravatar_id":"","url":"https://api.github.com/users/badges","html_url":"https://github.com/badges","followers_url":"https://api.github.com/users/badges/followers","following_url":"https://api.github.com/users/badges/following{/other_user}","gists_url":"https://api.github.com/users/badges/gists{/gist_id}","starred_url":"https://api.github.com/users/badges/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/badges/subscriptions","organizations_url":"https://api.github.com/users/badges/orgs","repos_url":"https://api.github.com/users/badges/repos","events_url":"https://api.github.com/users/badges/events{/privacy}","received_events_url":"https://api.github.com/users/badges/received_events","type":"Organization","site_admin":false},"repo":{"id":7910045,"node_id":"MDEwOlJlcG9zaXRvcnk3OTEwMDQ1","name":"shields","full_name":"badges/shields","private":false,"owner":{"login":"badges","id":6254238,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYyNTQyMzg=","avatar_url":"https://avatars2.githubusercontent.com/u/6254238?v=4","gravatar_id":"","url":"https://api.github.com/users/badges","html_url":"https://github.com/badges","followers_url":"https://api.github.com/users/badges/followers","following_url":"https://api.github.com/users/badges/following{/other_user}","gists_url":"https://api.github.com/users/badges/gists{/gist_id}","starred_url":"https://api.github.com/users/badges/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/badges/subscriptions","organizations_url":"https://api.github.com/users/badges/orgs","repos_url":"https://api.github.com/users/badges/repos","events_url":"https://api.github.com/users/badges/events{/privacy}","received_events_url":"https://api.github.com/users/badges/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/badges/shields","description":"Concise, consistent, and legible badges in SVG and raster format","fork":false,"url":"https://api.github.com/repos/badges/shields","forks_url":"https://api.github.com/repos/badges/shields/forks","keys_url":"https://api.github.com/repos/badges/shields/keys{/key_id}","collaborators_url":"https://api.github.com/repos/badges/shields/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/badges/shields/teams","hooks_url":"https://api.github.com/repos/badges/shields/hooks","issue_events_url":"https://api.github.com/repos/badges/shields/issues/events{/number}","events_url":"https://api.github.com/repos/badges/shields/events","assignees_url":"https://api.github.com/repos/badges/shields/assignees{/user}","branches_url":"https://api.github.com/repos/badges/shields/branches{/branch}","tags_url":"https://api.github.com/repos/badges/shields/tags","blobs_url":"https://api.github.com/repos/badges/shields/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/badges/shields/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/badges/shields/git/refs{/sha}","trees_url":"https://api.github.com/repos/badges/shields/git/trees{/sha}","statuses_url":"https://api.github.com/repos/badges/shields/statuses/{sha}","languages_url":"https://api.github.com/repos/badges/shields/languages","stargazers_url":"https://api.github.com/repos/badges/shields/stargazers","contributors_url":"https://api.github.com/repos/badges/shields/contributors","subscribers_url":"https://api.github.com/repos/badges/shields/subscribers","subscription_url":"https://api.github.com/repos/badges/shields/subscription","commits_url":"https://api.github.com/repos/badges/shields/commits{/sha}","git_commits_url":"https://api.github.com/repos/badges/shields/git/commits{/sha}","comments_url":"https://api.github.com/repos/badges/shields/comments{/number}","issue_comment_url":"https://api.github.com/repos/badges/shields/issues/comments{/number}","contents_url":"https://api.github.com/repos/badges/shields/contents/{+path}","compare_url":"https://api.github.com/repos/badges/shields/compare/{base}...{head}","merges_url":"https://api.github.com/repos/badges/shields/merges","archive_url":"https://api.github.com/repos/badges/shields/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/badges/shields/downloads","issues_url":"https://api.github.com/repos/badges/shields/issues{/number}","pulls_url":"https://api.github.com/repos/badges/shields/pulls{/number}","milestones_url":"https://api.github.com/repos/badges/shields/milestones{/number}","notifications_url":"https://api.github.com/repos/badges/shields/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/badges/shields/labels{/name}","releases_url":"https://api.github.com/repos/badges/shields/releases{/id}","deployments_url":"https://api.github.com/repos/badges/shields/deployments","created_at":"2013-01-30T07:41:54Z","updated_at":"2018-11-18T19:26:31Z","pushed_at":"2018-11-18T20:10:29Z","git_url":"git://github.com/badges/shields.git","ssh_url":"git@github.com:badges/shields.git","clone_url":"https://github.com/badges/shields.git","svn_url":"https://github.com/badges/shields","homepage":"https://shields.io","size":13423,"stargazers_count":6603,"watchers_count":6603,"language":"JavaScript","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":1511,"mirror_url":null,"archived":false,"open_issues_count":202,"license":{"key":"cc0-1.0","name":"Creative Commons Zero v1.0 Universal","spdx_id":"CC0-1.0","url":"https://api.github.com/licenses/cc0-1.0","node_id":"MDc6TGljZW5zZTY="},"forks":1511,"open_issues":202,"watchers":6603,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/badges/shields/pulls/2360"},"html":{"href":"https://github.com/badges/shields/pull/2360"},"issue":{"href":"https://api.github.com/repos/badges/shields/issues/2360"},"comments":{"href":"https://api.github.com/repos/badges/shields/issues/2360/comments"},"review_comments":{"href":"https://api.github.com/repos/badges/shields/pulls/2360/comments"},"review_comment":{"href":"https://api.github.com/repos/badges/shields/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/badges/shields/pulls/2360/commits"},"statuses":{"href":"https://api.github.com/repos/badges/shields/statuses/22e3eaa49acb7f817c71c1006760778d3cac78d1"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"paulmelnikow"}}