{"action":"created","issue":{"url":"https://api.github.com/repos/golang/go/issues/21753","repository_url":"https://api.github.com/repos/golang/go","labels_url":"https://api.github.com/repos/golang/go/issues/21753/labels{/name}","comments_url":"https://api.github.com/repos/golang/go/issues/21753/comments","events_url":"https://api.github.com/repos/golang/go/issues/21753/events","html_url":"https://github.com/golang/go/issues/21753","id":254930211,"number":21753,"title":"proposal: make net/http work with external TLS stacks","user":{"login":"FiloSottile","id":1225294,"avatar_url":"https://avatars1.githubusercontent.com/u/1225294?v=4","gravatar_id":"","url":"https://api.github.com/users/FiloSottile","html_url":"https://github.com/FiloSottile","followers_url":"https://api.github.com/users/FiloSottile/followers","following_url":"https://api.github.com/users/FiloSottile/following{/other_user}","gists_url":"https://api.github.com/users/FiloSottile/gists{/gist_id}","starred_url":"https://api.github.com/users/FiloSottile/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/FiloSottile/subscriptions","organizations_url":"https://api.github.com/users/FiloSottile/orgs","repos_url":"https://api.github.com/users/FiloSottile/repos","events_url":"https://api.github.com/users/FiloSottile/events{/privacy}","received_events_url":"https://api.github.com/users/FiloSottile/received_events","type":"User","site_admin":false},"labels":[{"id":236419512,"url":"https://api.github.com/repos/golang/go/labels/Proposal","name":"Proposal","color":"ededed","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/golang/go/milestones/30","html_url":"https://github.com/golang/go/milestone/30","labels_url":"https://api.github.com/repos/golang/go/milestones/30/labels","id":1373555,"number":30,"title":"Proposal","description":"Proposals that are pending (not yet accepted/rejected).\r\n","creator":{"login":"rsc","id":104030,"avatar_url":"https://avatars1.githubusercontent.com/u/104030?v=4","gravatar_id":"","url":"https://api.github.com/users/rsc","html_url":"https://github.com/rsc","followers_url":"https://api.github.com/users/rsc/followers","following_url":"https://api.github.com/users/rsc/following{/other_user}","gists_url":"https://api.github.com/users/rsc/gists{/gist_id}","starred_url":"https://api.github.com/users/rsc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rsc/subscriptions","organizations_url":"https://api.github.com/users/rsc/orgs","repos_url":"https://api.github.com/users/rsc/repos","events_url":"https://api.github.com/users/rsc/events{/privacy}","received_events_url":"https://api.github.com/users/rsc/received_events","type":"User","site_admin":false},"open_issues":172,"closed_issues":213,"state":"open","created_at":"2015-10-24T01:40:49Z","updated_at":"2017-09-04T03:58:55Z","due_on":null,"closed_at":null},"comments":0,"created_at":"2017-09-04T03:58:53Z","updated_at":"2017-09-04T04:27:01Z","closed_at":null,"author_association":"MEMBER","body":"net/http is hardcoded to work with crypto/tls, and it's currently impossible to use any other TLS stack. That meant that for example to develop the tls-tris fork of crypto/tls with TLS 1.3 support I had to [do horrible things](https://github.com/cloudflare/tls-tris/blob/master/_dev/Makefile) which made life pretty hard for other developers on the project.\r\n\r\n@rsc mentioned he'd be interested in making it possible to use non-crypto/tls stacks with net/http. While I don't think we should necessarily encourage it (it's good that \"what TLS stack do I want?\" is not a question a Go developer has to ask themselves), I agree it would be nice to at least make it possible.\r\n\r\nHere's a survey of the coupling points, and proposals on how to fix (most) of them.\r\n\r\n/cc @agl @bradfitz @rsc @mholt\r\n\r\n## Server side\r\n\r\n* `Request.TLS` has type `*tls.ConnectionState`\r\n    * I think it's acceptable to require external stacks to use the crypto/tls `ConnectionState` type\r\n* `serve` type-asserts `*tls.Conn` to detect a TLS connection and call `Handshake()` and `ConnectionState()`\r\n    * Here we can type-assert to an (probably unexported) interface with those two methods\r\n* `Server.TLSNextProto` has type `map[string]func(*Server, *tls.Conn, Handler)`\r\n    * This is a problem: the function here will have to work with the concrete `*tls.Conn`, and there is code out there written with this assumption, including the standard http2 library\r\n* `ServeTLS` and `ListenAndServeTLS`\r\n    * These are helpers, no reason they shouldn't use crypto/tls\r\n* `Server.TLSConfig` has type `*tls.Config`\r\n    * We can mostly ignore this, as it's only used for `ServeTLS`/`ListenAndServeTLS` and for some auto-HTTP/2 logic\r\n\r\n## Client side\r\n\r\n* `Client` asserts `tls.RecordHeaderError` to detect a mistaken plain HTTP response\r\n    * External stacks can just use the crypto/tls error type\r\n* `Response.TLS` has type `*tls.ConnectionState`\r\n    * As above, it's acceptable to require external stacks to use the crypto/tls `ConnectionState` type\r\n* `Transport.TLSClientConfig` has type `*tls.Config`\r\n    * We can ignore this, as it can be overridden with `DialTLS`, so it's basically part of a helper\r\n* Auto-HTTP/2 is disabled by `DialTLS` being set\r\n    * I think the client logic should be more like the server one, where the HTTP stack is configured if the TLS state is unknown (`t.DialTLS != nil`) or the TLS Config is available (`t.TLSClientConfig != nil`) and `h2` is enabled (this might be a separate issue)\r\n* `Transport.TLSNextProto` has type `map[string]func(authority string, c *tls.Conn) RoundTripper`\r\n    * Like `Server.TLSNextProto`, this is a problem\r\n* `dialConn` type-asserts `*tls.Conn`\r\n    * Like above, we can instead assert an interface\r\n\r\n## Conclusion\r\n\r\nThe main problem are the two `TLSNextProto`, for which I have no good solution. The auto-HTTP/2 logic might also need attention. Other parts can be either ignored as helpers, or discreetly fixed."},"comment":{"url":"https://api.github.com/repos/golang/go/issues/comments/326863409","html_url":"https://github.com/golang/go/issues/21753#issuecomment-326863409","issue_url":"https://api.github.com/repos/golang/go/issues/21753","id":326863409,"user":{"login":"mholt","id":1128849,"avatar_url":"https://avatars2.githubusercontent.com/u/1128849?v=4","gravatar_id":"","url":"https://api.github.com/users/mholt","html_url":"https://github.com/mholt","followers_url":"https://api.github.com/users/mholt/followers","following_url":"https://api.github.com/users/mholt/following{/other_user}","gists_url":"https://api.github.com/users/mholt/gists{/gist_id}","starred_url":"https://api.github.com/users/mholt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mholt/subscriptions","organizations_url":"https://api.github.com/users/mholt/orgs","repos_url":"https://api.github.com/users/mholt/repos","events_url":"https://api.github.com/users/mholt/events{/privacy}","received_events_url":"https://api.github.com/users/mholt/received_events","type":"User","site_admin":false},"created_at":"2017-09-04T04:27:01Z","updated_at":"2017-09-04T04:27:01Z","author_association":"NONE","body":"I'll add that I'm also quite interested in this. It would make rolling out TLS 1.3 at scale much easier without having to endanger the reputation of the Go standard library with an experimental TLS version.\r\n\r\nRe: The TLSNextProto map's reliance on concrete `*tls.Conn` types: is it feasible to add an interface field or \"setter\" method for an unexported interface field on the `tls.Conn` struct so that its methods defer to the methods implemented by that value?\r\n\r\n```\r\ntype Conn struct {\r\n        Impl ConnInterface\r\n\r\n        // contains filtered or unexported fields\r\n}\r\n```\r\n\r\nWhere `ConnInterface` is an interface describing the exported methods on Conn. This is obviously not a pleasant solution as the interface isn't particularly small, and adding methods/fields to structs for niche uses is not ideal, but it's just an idea. (Also, I'm not sure if allowing \"overriding\" the exported methods will give sufficient coverage to essentially replace the concrete tls.Conn with another type...)"}}
{"actor":{"display_login":"mholt"}}