44 "fmt"
55 "net"
66 "net/http"
7+ "net/url"
78 "strings"
89 "time"
910
@@ -73,15 +74,27 @@ func (crt connectedRoundTripper) RoundTrip(req *http.Request) (*http.Response, e
7374
7475// connectedConnHTTPTransport uses a preconnected connection to the CDN to make HTTP requests.
7576// This uses the pre-established connection to the CDN on the fronting domain.
76- func connectedConnHTTPTransport (conn net.Conn , disableKeepAlives bool ) * http.Transport {
77- return & http.Transport {
78- Dial : func (network , addr string ) (net.Conn , error ) {
79- return conn , nil
77+ func connectedConnHTTPTransport (conn net.Conn , disableKeepAlives bool ) http.RoundTripper {
78+ return & connectedTransport {
79+ Transport : http.Transport {
80+ Dial : func (network , addr string ) (net.Conn , error ) {
81+ return conn , nil
82+ },
83+ TLSHandshakeTimeout : 20 * time .Second ,
84+ DisableKeepAlives : disableKeepAlives ,
85+ IdleConnTimeout : 70 * time .Second ,
8086 },
81- TLSHandshakeTimeout : 20 * time .Second ,
82- DisableKeepAlives : disableKeepAlives ,
83- IdleConnTimeout : 70 * time .Second ,
8487 }
88+ /*
89+ return &http.Transport{
90+ Dial: func(network, addr string) (net.Conn, error) {
91+ return conn, nil
92+ },
93+ TLSHandshakeTimeout: 20 * time.Second,
94+ DisableKeepAlives: disableKeepAlives,
95+ IdleConnTimeout: 70 * time.Second,
96+ }
97+ */
8598}
8699
87100func withDomainFront (req * http.Request , frontedHost string ) * http.Request {
@@ -96,3 +109,44 @@ func withDomainFront(req *http.Request, frontedHost string) *http.Request {
96109
97110 return newReq
98111}
112+
113+ /*
114+ func withDomainFront(req *http.Request, frontedHost string) (*http.Request, error) {
115+ urlCopy := *req.URL
116+ urlCopy.Host = frontedHost
117+ r, err := http.NewRequestWithContext(req.Context(), req.Method, urlCopy.String(), req.Body)
118+ if err != nil {
119+ return nil, err
120+ }
121+ for k, vs := range req.Header {
122+ if !strings.EqualFold(k, "Host") {
123+ v := make([]string, len(vs))
124+ copy(v, vs)
125+ r.Header[k] = v
126+ }
127+ }
128+ return r, nil
129+ }
130+ */
131+
132+ // connectedTransport is a wrapper struct enabling us to modify the protocol of outgoing
133+ // requests to make them all HTTP instead of potentially HTTPS, which breaks our particular
134+ // implemenation of direct domain fronting.
135+ type connectedTransport struct {
136+ http.Transport
137+ }
138+
139+ func (ct * connectedTransport ) RoundTrip (req * http.Request ) (resp * http.Response , err error ) {
140+ defer func (op ops.Op ) { op .End () }(ops .Begin ("direct_transport_roundtrip" ))
141+ // The connection is already encrypted by domain fronting. We need to rewrite URLs starting
142+ // with "https://" to "http://", lest we get an error for doubling up on TLS.
143+
144+ // The RoundTrip interface requires that we not modify the memory in the request, so we just
145+ // create a copy.
146+ norm := new (http.Request )
147+ * norm = * req // includes shallow copies of maps, but okay
148+ norm .URL = new (url.URL )
149+ * norm .URL = * req .URL
150+ norm .URL .Scheme = "http"
151+ return ct .Transport .RoundTrip (norm )
152+ }
0 commit comments