{"action":"created","issue":{"url":"https://api.github.com/repos/zendframework/zend-expressive-swoole/issues/12","repository_url":"https://api.github.com/repos/zendframework/zend-expressive-swoole","labels_url":"https://api.github.com/repos/zendframework/zend-expressive-swoole/issues/12/labels{/name}","comments_url":"https://api.github.com/repos/zendframework/zend-expressive-swoole/issues/12/comments","events_url":"https://api.github.com/repos/zendframework/zend-expressive-swoole/issues/12/events","html_url":"https://github.com/zendframework/zend-expressive-swoole/pull/12","id":352257731,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA5NjEzNjgz","number":12,"title":"Handle http cache, etag and last-modified header","user":{"login":"huangzhhui","id":12077148,"node_id":"MDQ6VXNlcjEyMDc3MTQ4","avatar_url":"https://avatars1.githubusercontent.com/u/12077148?v=4","gravatar_id":"","url":"https://api.github.com/users/huangzhhui","html_url":"https://github.com/huangzhhui","followers_url":"https://api.github.com/users/huangzhhui/followers","following_url":"https://api.github.com/users/huangzhhui/following{/other_user}","gists_url":"https://api.github.com/users/huangzhhui/gists{/gist_id}","starred_url":"https://api.github.com/users/huangzhhui/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/huangzhhui/subscriptions","organizations_url":"https://api.github.com/users/huangzhhui/orgs","repos_url":"https://api.github.com/users/huangzhhui/repos","events_url":"https://api.github.com/users/huangzhhui/events{/privacy}","received_events_url":"https://api.github.com/users/huangzhhui/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2018-08-20T19:03:44Z","updated_at":"2018-08-22T19:26:20Z","closed_at":null,"author_association":"CONTRIBUTOR","pull_request":{"url":"https://api.github.com/repos/zendframework/zend-expressive-swoole/pulls/12","html_url":"https://github.com/zendframework/zend-expressive-swoole/pull/12","diff_url":"https://github.com/zendframework/zend-expressive-swoole/pull/12.diff","patch_url":"https://github.com/zendframework/zend-expressive-swoole/pull/12.patch"},"body":"Provide a narrative description of what you are trying to accomplish:\r\n\r\n- [x] Are you creating a new feature?\r\n  - [x] Why is the new feature needed? What purpose does it serve?\r\nComplete #10 \r\n  - [x] How will users use the new feature?\r\nRunner will set the headers automatically with static files request\r\n  - [x] Base your feature on the `master` branch, and submit against that branch.\r\n  - [x] Add only one feature per pull request; split multiple features over multiple pull requests\r\n  - [x] Add tests for the new feature.\r\n  - [ ] Add documentation for the new feature.\r\n  - [ ] Add a `CHANGELOG.md` entry for the new feature.\r\n"},"comment":{"url":"https://api.github.com/repos/zendframework/zend-expressive-swoole/issues/comments/415150535","html_url":"https://github.com/zendframework/zend-expressive-swoole/pull/12#issuecomment-415150535","issue_url":"https://api.github.com/repos/zendframework/zend-expressive-swoole/issues/12","id":415150535,"node_id":"MDEyOklzc3VlQ29tbWVudDQxNTE1MDUzNQ==","user":{"login":"weierophinney","id":25943,"node_id":"MDQ6VXNlcjI1OTQz","avatar_url":"https://avatars1.githubusercontent.com/u/25943?v=4","gravatar_id":"","url":"https://api.github.com/users/weierophinney","html_url":"https://github.com/weierophinney","followers_url":"https://api.github.com/users/weierophinney/followers","following_url":"https://api.github.com/users/weierophinney/following{/other_user}","gists_url":"https://api.github.com/users/weierophinney/gists{/gist_id}","starred_url":"https://api.github.com/users/weierophinney/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/weierophinney/subscriptions","organizations_url":"https://api.github.com/users/weierophinney/orgs","repos_url":"https://api.github.com/users/weierophinney/repos","events_url":"https://api.github.com/users/weierophinney/events{/privacy}","received_events_url":"https://api.github.com/users/weierophinney/received_events","type":"User","site_admin":false},"created_at":"2018-08-22T19:26:20Z","updated_at":"2018-08-22T19:26:20Z","author_association":"MEMBER","body":"@huangzhhui —\r\n\r\n> It is already determine if the extension of static file exist in `RequestHandlerSwooleRunner::$cacheTypeFile` before handle `ETag` header, I think add a blocklists for `ETag` is not a good idea.\r\n\r\nI was thinking something along the lines of the following nginx configuration:\r\n\r\n```nginx\r\n# JS\r\nlocation ~* ^/static/js/$ {\r\n    add_header Cache-Control public; # Indicate that the resource may be cached by public caches like web caches for instance, if set to 'private' the resource may only be cached by client's browser.\r\n\r\n    expires     24h; # Indicate that the resource can be cached for 24 hours\r\n}\r\n\r\n# CSS\r\nlocation ~* ^/static/css/$ {\r\n    add_header Cache-Control public;\r\n\r\n    # Equivalent to above:\r\n    expires     86400; # Indicate that the resource can be cached for 86400 seconds (24 hours)\r\n\r\n    etag on; # Add an ETag header with an identifier that can be stored by the client\r\n}\r\n\r\n# Images\r\nlocation ~* ^/static/images/$ {\r\n    add_header Cache-Control must-revalidate; # Indicate that the resource must be revalidated at each access\r\n\r\n    etag on;\r\n}\r\n```\r\n\r\nNote how not EVERY asset gets an ETag or Expires header, and that the Cache-Control headers vary based on asset type. My thought is that we should:\r\n\r\n- Provide mechanisms for adding these client-side-caching headers\r\n- Provide a way to configure the headers based on file, extension, or path\r\n\r\nRight now, this patch is solving the first problem, but we also need to be able to solve the second to make this flexible enough for general purpose usage, as these are common scenarios when serving static content.\r\n\r\nAs I review the nginx configuration, everything is _opt-in_, so this would be an _acceptlist_, not a _blocklist_; if no configuration is specified, no caching occurs.\r\n\r\nDoes that make sense?\r\n\r\n(One thing we could do for now if you don't want to tackle the second aspect is to just provide the methods for generating the headers. A later pull request — from you or from myself or @ezimuel — could tackle the acceptlist and configuration.)"}}
{"actor":{"display_login":"weierophinney"}}