{"action":"opened","number":5,"pull_request":{"url":"https://api.github.com/repos/AndrewBurian/eventsource/pulls/5","id":202980801,"node_id":"MDExOlB1bGxSZXF1ZXN0MjAyOTgwODAx","html_url":"https://github.com/AndrewBurian/eventsource/pull/5","diff_url":"https://github.com/AndrewBurian/eventsource/pull/5.diff","patch_url":"https://github.com/AndrewBurian/eventsource/pull/5.patch","issue_url":"https://api.github.com/repos/AndrewBurian/eventsource/issues/5","number":5,"state":"open","locked":false,"title":"Don't send Connection: keep-alive header to HTTP/2 clients","user":{"login":"lithium3141","id":386920,"node_id":"MDQ6VXNlcjM4NjkyMA==","avatar_url":"https://avatars3.githubusercontent.com/u/386920?v=4","gravatar_id":"","url":"https://api.github.com/users/lithium3141","html_url":"https://github.com/lithium3141","followers_url":"https://api.github.com/users/lithium3141/followers","following_url":"https://api.github.com/users/lithium3141/following{/other_user}","gists_url":"https://api.github.com/users/lithium3141/gists{/gist_id}","starred_url":"https://api.github.com/users/lithium3141/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lithium3141/subscriptions","organizations_url":"https://api.github.com/users/lithium3141/orgs","repos_url":"https://api.github.com/users/lithium3141/repos","events_url":"https://api.github.com/users/lithium3141/events{/privacy}","received_events_url":"https://api.github.com/users/lithium3141/received_events","type":"User","site_admin":false},"body":"When creating Client instances directly in response to HTTP/2 requests, the `NewClient()` function incorrectly sends the `Connection: keep-alive` header, which is treated as an error by some clients. This pull request changes the `NewClient()` function to additionally take an `http.Request` parameter, whose `ProtoMajor` is checked to determine if sending a `Connection` header is appropriate.\r\n\r\n---\r\n\r\nAs an example, consider the following Client-creating example:\r\n\r\n```go\r\nfunc HandleSSEClient(w http.ResponseWriter, req *http.Request) {\r\n\tclient := eventsource.NewClient(w)\r\n\tgo func() {\r\n\t\tfor {\r\n\t\t\ttime.Sleep(time.Second)\r\n\t\t\tclient.Send(eventsource.DataEvent(\"tick\"))\r\n\t\t}\r\n\t}()\r\n\tclient.Wait()\r\n}\r\n\r\nfunc main() {\r\n\thttp.ListenAndServeTLS(\":40443\", \"cert\", \"key\", http.HandlerFunc(HandleSSEClient))\r\n}\r\n```\r\n\r\nOn macOS 10.13.6, making an HTTP/2 request to this server with `curl` fails:\r\n\r\n```\r\n[tim@tevanian ~]$ curl --version\r\ncurl 7.54.0 (x86_64-apple-darwin17.0) libcurl/7.54.0 LibreSSL/2.0.20 zlib/1.2.11 nghttp2/1.24.0\r\nProtocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp\r\nFeatures: AsynchDNS IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz HTTP2 UnixSockets HTTPS-proxy\r\n[tim@tevanian ~]$ curl -k -v -H \"Accept: text/event-source\" https://localhost:40443/\r\n*   Trying ::1...\r\n* TCP_NODELAY set\r\n* Connected to localhost (::1) port 40443 (#0)\r\n* ALPN, offering h2\r\n* ALPN, offering http/1.1\r\n* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH\r\n* successfully set certificate verify locations:\r\n*   CAfile: /etc/ssl/cert.pem\r\n  CApath: none\r\n* TLSv1.2 (OUT), TLS handshake, Client hello (1):\r\n* TLSv1.2 (IN), TLS handshake, Server hello (2):\r\n* TLSv1.2 (IN), TLS handshake, Certificate (11):\r\n* TLSv1.2 (IN), TLS handshake, Server key exchange (12):\r\n* TLSv1.2 (IN), TLS handshake, Server finished (14):\r\n* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):\r\n* TLSv1.2 (OUT), TLS change cipher, Client hello (1):\r\n* TLSv1.2 (OUT), TLS handshake, Finished (20):\r\n* TLSv1.2 (IN), TLS change cipher, Client hello (1):\r\n* TLSv1.2 (IN), TLS handshake, Finished (20):\r\n* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256\r\n* ALPN, server accepted to use h2\r\n* Server certificate:\r\n*  subject: <self-signed; redacted>\r\n*  start date: Jul 20 02:30:00 2018 GMT\r\n*  expire date: Jul 20 02:30:00 2019 GMT\r\n*  issuer: <self-signed; redacted>\r\n*  SSL certificate verify result: self signed certificate (18), continuing anyway.\r\n* Using HTTP2, server supports multi-use\r\n* Connection state changed (HTTP/2 confirmed)\r\n* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0\r\n* Using Stream ID: 1 (easy handle 0x7fad49005800)\r\n> GET / HTTP/2\r\n> Host: localhost:40443\r\n> User-Agent: curl/7.54.0\r\n> Accept: text/event-source\r\n>\r\n* Connection state changed (MAX_CONCURRENT_STREAMS updated)!\r\n* http2 error: Invalid HTTP header field was received: frame type: 1, stream: 1, name: [connection], value: [keep-alive]\r\n* HTTP/2 stream 1 was not closed cleanly: PROTOCOL_ERROR (err 1)\r\n* Closing connection 0\r\n* TLSv1.2 (OUT), TLS alert, Client hello (1):\r\ncurl: (92) HTTP/2 stream 1 was not closed cleanly: PROTOCOL_ERROR (err 1)\r\n```\r\n\r\nAfter this change, the connection succeeds and begins receiving `tick` events.\r\n\r\n---\r\n\r\nThis change does alter the contract of the `NewRequest()` method; existing code would have to be updated to pass `nil` to preserve old behavior, or pass in a request to benefit from the new behavior. Given the ease of the change, I didn't add another method name for the request-accepting variant, but could do so if asked. (Adding semantic versioning branches or gopkg.in support could also help mitigate this problem, if done before this request is merged.)","created_at":"2018-07-21T00:14:09Z","updated_at":"2018-07-21T00:14:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":null,"assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/AndrewBurian/eventsource/pulls/5/commits","review_comments_url":"https://api.github.com/repos/AndrewBurian/eventsource/pulls/5/comments","review_comment_url":"https://api.github.com/repos/AndrewBurian/eventsource/pulls/comments{/number}","comments_url":"https://api.github.com/repos/AndrewBurian/eventsource/issues/5/comments","statuses_url":"https://api.github.com/repos/AndrewBurian/eventsource/statuses/110e77142096491104bb38ffc89fdeab8484872c","head":{"label":"lithium3141:http2-skip-keepalive-header","ref":"http2-skip-keepalive-header","sha":"110e77142096491104bb38ffc89fdeab8484872c","user":{"login":"lithium3141","id":386920,"node_id":"MDQ6VXNlcjM4NjkyMA==","avatar_url":"https://avatars3.githubusercontent.com/u/386920?v=4","gravatar_id":"","url":"https://api.github.com/users/lithium3141","html_url":"https://github.com/lithium3141","followers_url":"https://api.github.com/users/lithium3141/followers","following_url":"https://api.github.com/users/lithium3141/following{/other_user}","gists_url":"https://api.github.com/users/lithium3141/gists{/gist_id}","starred_url":"https://api.github.com/users/lithium3141/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lithium3141/subscriptions","organizations_url":"https://api.github.com/users/lithium3141/orgs","repos_url":"https://api.github.com/users/lithium3141/repos","events_url":"https://api.github.com/users/lithium3141/events{/privacy}","received_events_url":"https://api.github.com/users/lithium3141/received_events","type":"User","site_admin":false},"repo":{"id":141631133,"node_id":"MDEwOlJlcG9zaXRvcnkxNDE2MzExMzM=","name":"eventsource","full_name":"lithium3141/eventsource","owner":{"login":"lithium3141","id":386920,"node_id":"MDQ6VXNlcjM4NjkyMA==","avatar_url":"https://avatars3.githubusercontent.com/u/386920?v=4","gravatar_id":"","url":"https://api.github.com/users/lithium3141","html_url":"https://github.com/lithium3141","followers_url":"https://api.github.com/users/lithium3141/followers","following_url":"https://api.github.com/users/lithium3141/following{/other_user}","gists_url":"https://api.github.com/users/lithium3141/gists{/gist_id}","starred_url":"https://api.github.com/users/lithium3141/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lithium3141/subscriptions","organizations_url":"https://api.github.com/users/lithium3141/orgs","repos_url":"https://api.github.com/users/lithium3141/repos","events_url":"https://api.github.com/users/lithium3141/events{/privacy}","received_events_url":"https://api.github.com/users/lithium3141/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/lithium3141/eventsource","description":"SSE Swiss Army Knife for Go","fork":true,"url":"https://api.github.com/repos/lithium3141/eventsource","forks_url":"https://api.github.com/repos/lithium3141/eventsource/forks","keys_url":"https://api.github.com/repos/lithium3141/eventsource/keys{/key_id}","collaborators_url":"https://api.github.com/repos/lithium3141/eventsource/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/lithium3141/eventsource/teams","hooks_url":"https://api.github.com/repos/lithium3141/eventsource/hooks","issue_events_url":"https://api.github.com/repos/lithium3141/eventsource/issues/events{/number}","events_url":"https://api.github.com/repos/lithium3141/eventsource/events","assignees_url":"https://api.github.com/repos/lithium3141/eventsource/assignees{/user}","branches_url":"https://api.github.com/repos/lithium3141/eventsource/branches{/branch}","tags_url":"https://api.github.com/repos/lithium3141/eventsource/tags","blobs_url":"https://api.github.com/repos/lithium3141/eventsource/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/lithium3141/eventsource/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/lithium3141/eventsource/git/refs{/sha}","trees_url":"https://api.github.com/repos/lithium3141/eventsource/git/trees{/sha}","statuses_url":"https://api.github.com/repos/lithium3141/eventsource/statuses/{sha}","languages_url":"https://api.github.com/repos/lithium3141/eventsource/languages","stargazers_url":"https://api.github.com/repos/lithium3141/eventsource/stargazers","contributors_url":"https://api.github.com/repos/lithium3141/eventsource/contributors","subscribers_url":"https://api.github.com/repos/lithium3141/eventsource/subscribers","subscription_url":"https://api.github.com/repos/lithium3141/eventsource/subscription","commits_url":"https://api.github.com/repos/lithium3141/eventsource/commits{/sha}","git_commits_url":"https://api.github.com/repos/lithium3141/eventsource/git/commits{/sha}","comments_url":"https://api.github.com/repos/lithium3141/eventsource/comments{/number}","issue_comment_url":"https://api.github.com/repos/lithium3141/eventsource/issues/comments{/number}","contents_url":"https://api.github.com/repos/lithium3141/eventsource/contents/{+path}","compare_url":"https://api.github.com/repos/lithium3141/eventsource/compare/{base}...{head}","merges_url":"https://api.github.com/repos/lithium3141/eventsource/merges","archive_url":"https://api.github.com/repos/lithium3141/eventsource/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/lithium3141/eventsource/downloads","issues_url":"https://api.github.com/repos/lithium3141/eventsource/issues{/number}","pulls_url":"https://api.github.com/repos/lithium3141/eventsource/pulls{/number}","milestones_url":"https://api.github.com/repos/lithium3141/eventsource/milestones{/number}","notifications_url":"https://api.github.com/repos/lithium3141/eventsource/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/lithium3141/eventsource/labels{/name}","releases_url":"https://api.github.com/repos/lithium3141/eventsource/releases{/id}","deployments_url":"https://api.github.com/repos/lithium3141/eventsource/deployments","created_at":"2018-07-19T21:10:12Z","updated_at":"2018-07-19T21:10:14Z","pushed_at":"2018-07-20T23:35:10Z","git_url":"git://github.com/lithium3141/eventsource.git","ssh_url":"git@github.com:lithium3141/eventsource.git","clone_url":"https://github.com/lithium3141/eventsource.git","svn_url":"https://github.com/lithium3141/eventsource","homepage":"","size":20,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"AndrewBurian:master","ref":"master","sha":"8d57873cbd4847e43cfa5cfa4e074669d991fdee","user":{"login":"AndrewBurian","id":4976968,"node_id":"MDQ6VXNlcjQ5NzY5Njg=","avatar_url":"https://avatars2.githubusercontent.com/u/4976968?v=4","gravatar_id":"","url":"https://api.github.com/users/AndrewBurian","html_url":"https://github.com/AndrewBurian","followers_url":"https://api.github.com/users/AndrewBurian/followers","following_url":"https://api.github.com/users/AndrewBurian/following{/other_user}","gists_url":"https://api.github.com/users/AndrewBurian/gists{/gist_id}","starred_url":"https://api.github.com/users/AndrewBurian/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AndrewBurian/subscriptions","organizations_url":"https://api.github.com/users/AndrewBurian/orgs","repos_url":"https://api.github.com/users/AndrewBurian/repos","events_url":"https://api.github.com/users/AndrewBurian/events{/privacy}","received_events_url":"https://api.github.com/users/AndrewBurian/received_events","type":"User","site_admin":false},"repo":{"id":101320000,"node_id":"MDEwOlJlcG9zaXRvcnkxMDEzMjAwMDA=","name":"eventsource","full_name":"AndrewBurian/eventsource","owner":{"login":"AndrewBurian","id":4976968,"node_id":"MDQ6VXNlcjQ5NzY5Njg=","avatar_url":"https://avatars2.githubusercontent.com/u/4976968?v=4","gravatar_id":"","url":"https://api.github.com/users/AndrewBurian","html_url":"https://github.com/AndrewBurian","followers_url":"https://api.github.com/users/AndrewBurian/followers","following_url":"https://api.github.com/users/AndrewBurian/following{/other_user}","gists_url":"https://api.github.com/users/AndrewBurian/gists{/gist_id}","starred_url":"https://api.github.com/users/AndrewBurian/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AndrewBurian/subscriptions","organizations_url":"https://api.github.com/users/AndrewBurian/orgs","repos_url":"https://api.github.com/users/AndrewBurian/repos","events_url":"https://api.github.com/users/AndrewBurian/events{/privacy}","received_events_url":"https://api.github.com/users/AndrewBurian/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/AndrewBurian/eventsource","description":"SSE Swiss Army Knife for Go","fork":false,"url":"https://api.github.com/repos/AndrewBurian/eventsource","forks_url":"https://api.github.com/repos/AndrewBurian/eventsource/forks","keys_url":"https://api.github.com/repos/AndrewBurian/eventsource/keys{/key_id}","collaborators_url":"https://api.github.com/repos/AndrewBurian/eventsource/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/AndrewBurian/eventsource/teams","hooks_url":"https://api.github.com/repos/AndrewBurian/eventsource/hooks","issue_events_url":"https://api.github.com/repos/AndrewBurian/eventsource/issues/events{/number}","events_url":"https://api.github.com/repos/AndrewBurian/eventsource/events","assignees_url":"https://api.github.com/repos/AndrewBurian/eventsource/assignees{/user}","branches_url":"https://api.github.com/repos/AndrewBurian/eventsource/branches{/branch}","tags_url":"https://api.github.com/repos/AndrewBurian/eventsource/tags","blobs_url":"https://api.github.com/repos/AndrewBurian/eventsource/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/AndrewBurian/eventsource/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/AndrewBurian/eventsource/git/refs{/sha}","trees_url":"https://api.github.com/repos/AndrewBurian/eventsource/git/trees{/sha}","statuses_url":"https://api.github.com/repos/AndrewBurian/eventsource/statuses/{sha}","languages_url":"https://api.github.com/repos/AndrewBurian/eventsource/languages","stargazers_url":"https://api.github.com/repos/AndrewBurian/eventsource/stargazers","contributors_url":"https://api.github.com/repos/AndrewBurian/eventsource/contributors","subscribers_url":"https://api.github.com/repos/AndrewBurian/eventsource/subscribers","subscription_url":"https://api.github.com/repos/AndrewBurian/eventsource/subscription","commits_url":"https://api.github.com/repos/AndrewBurian/eventsource/commits{/sha}","git_commits_url":"https://api.github.com/repos/AndrewBurian/eventsource/git/commits{/sha}","comments_url":"https://api.github.com/repos/AndrewBurian/eventsource/comments{/number}","issue_comment_url":"https://api.github.com/repos/AndrewBurian/eventsource/issues/comments{/number}","contents_url":"https://api.github.com/repos/AndrewBurian/eventsource/contents/{+path}","compare_url":"https://api.github.com/repos/AndrewBurian/eventsource/compare/{base}...{head}","merges_url":"https://api.github.com/repos/AndrewBurian/eventsource/merges","archive_url":"https://api.github.com/repos/AndrewBurian/eventsource/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/AndrewBurian/eventsource/downloads","issues_url":"https://api.github.com/repos/AndrewBurian/eventsource/issues{/number}","pulls_url":"https://api.github.com/repos/AndrewBurian/eventsource/pulls{/number}","milestones_url":"https://api.github.com/repos/AndrewBurian/eventsource/milestones{/number}","notifications_url":"https://api.github.com/repos/AndrewBurian/eventsource/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/AndrewBurian/eventsource/labels{/name}","releases_url":"https://api.github.com/repos/AndrewBurian/eventsource/releases{/id}","deployments_url":"https://api.github.com/repos/AndrewBurian/eventsource/deployments","created_at":"2017-08-24T17:17:32Z","updated_at":"2017-09-19T18:08:38Z","pushed_at":"2017-09-20T22:15:51Z","git_url":"git://github.com/AndrewBurian/eventsource.git","ssh_url":"git@github.com:AndrewBurian/eventsource.git","clone_url":"https://github.com/AndrewBurian/eventsource.git","svn_url":"https://github.com/AndrewBurian/eventsource","homepage":"","size":20,"stargazers_count":4,"watchers_count":4,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":3,"license":null,"forks":1,"open_issues":3,"watchers":4,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/AndrewBurian/eventsource/pulls/5"},"html":{"href":"https://github.com/AndrewBurian/eventsource/pull/5"},"issue":{"href":"https://api.github.com/repos/AndrewBurian/eventsource/issues/5"},"comments":{"href":"https://api.github.com/repos/AndrewBurian/eventsource/issues/5/comments"},"review_comments":{"href":"https://api.github.com/repos/AndrewBurian/eventsource/pulls/5/comments"},"review_comment":{"href":"https://api.github.com/repos/AndrewBurian/eventsource/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/AndrewBurian/eventsource/pulls/5/commits"},"statuses":{"href":"https://api.github.com/repos/AndrewBurian/eventsource/statuses/110e77142096491104bb38ffc89fdeab8484872c"}},"author_association":"NONE","merged":false,"mergeable":null,"rebaseable":null,"mergeable_state":"unknown","merged_by":null,"comments":0,"review_comments":0,"maintainer_can_modify":true,"commits":2,"additions":11,"deletions":6,"changed_files":3}}
{"actor":{"display_login":"lithium3141"}}