]> Cypherpunks.ru repositories - gostls13.git/commitdiff
net/http: guarantee that the Transport dial functions are respected in js/wasm
authorNeil Alexander <neilalexander@users.noreply.github.com>
Fri, 3 Sep 2021 21:07:22 +0000 (21:07 +0000)
committerDamien Neil <dneil@google.com>
Thu, 28 Oct 2021 17:57:57 +0000 (17:57 +0000)
The net/http package has a documented contract that if DialContext, DialDLSContext, Dial or DialTLS are specified in an instance of Transport, that they will be used to set up the connection. If they are not specified, then a reasonable fallback is made (e.g. using the net package).

This is ordinarily true, except for when compiling for the js/wasm target, where the browser's Fetch API is preferred in all cases (except for when it is undefined/unavailable) and therefore the dial functions are all ignored. As a result, the http.Transport implementation under js/wasm doesn't meet that contract.

This PR updates the RoundTrip behaviour of http.Transport so that if DialContext, DialTLSContext, Dial or DialTLS are specified, they are used as expected. The Fetch API will be used as a fallback if they are not specified.

Fixes #27495

Change-Id: I88c6eb6ffdd077827b421d606f3e60ebdafd538f
GitHub-Last-Rev: 948a0ed97ec4661f03cd346335f1d3d180f4c1ae
GitHub-Pull-Request: golang/go#46923
Reviewed-on: https://go-review.googlesource.com/c/go/+/330852
Reviewed-by: Damien Neil <dneil@google.com>
Trust: Damien Neil <dneil@google.com>
Trust: Carlos Amedee <carlos@golang.org>
Run-TryBot: Damien Neil <dneil@google.com>
TryBot-Result: Go Bot <gobot@golang.org>

AUTHORS
CONTRIBUTORS
src/net/http/roundtrip_js.go
src/net/http/transport.go
src/net/http/transport_default_js.go [new file with mode: 0644]
src/net/http/transport_default_other.go [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index 8d8d83605e411c28054699aff1cd9799b93b4fc7..ad907967b4aa2da99c75f165494712191fef5af9 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1015,6 +1015,7 @@ Nathan Youngman <git@nathany.com>
 Nathaniel Cook <nvcook42@gmail.com>
 Naveen Kumar Sangi <naveenkumarsangi@protonmail.com>
 Neelesh Chandola <neelesh.c98@gmail.com>
+Neil Alexander <neilalexander@neilalexander.dev>
 Neil Lyons <nwjlyons@googlemail.com>
 Netflix, Inc.
 Neuman Vong <neuman.vong@gmail.com>
index 74d4687373022399471ffe5ef19e39e335825957..706d630193fb4fef0934e2d3071bf266a262445f 100644 (file)
@@ -1901,6 +1901,7 @@ Naveen Kumar Sangi <naveenkumarsangi@protonmail.com>
 Neeilan Selvalingam <neeilan96@gmail.com>
 Neelesh Chandola <neelesh.c98@gmail.com>
 Nehal J Wani <nehaljw.kkd1@gmail.com>
+Neil Alexander <neilalexander@neilalexander.dev>
 Neil Lyons <nwjlyons@googlemail.com>
 Neuman Vong <neuman.vong@gmail.com>
 Neven Sajko <nsajko@gmail.com>
index 362dbcbdde14e6fe8d93b6da2bcb4ac2e9d658c8..4a8595ebcff4262294df60be988468b090cb2524 100644 (file)
@@ -41,11 +41,19 @@ const jsFetchCreds = "js.fetch:credentials"
 // Reference: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters
 const jsFetchRedirect = "js.fetch:redirect"
 
-var useFakeNetwork = js.Global().Get("fetch").IsUndefined()
+// jsFetchMissing will be true if the Fetch API is not present in
+// the browser globals.
+var jsFetchMissing = js.Global().Get("fetch").IsUndefined()
 
 // RoundTrip implements the RoundTripper interface using the WHATWG Fetch API.
 func (t *Transport) RoundTrip(req *Request) (*Response, error) {
-       if useFakeNetwork {
+       // The Transport has a documented contract that states that if the DialContext or
+       // DialTLSContext functions are set, they will be used to set up the connections.
+       // If they aren't set then the documented contract is to use Dial or DialTLS, even
+       // though they are deprecated. Therefore, if any of these are set, we should obey
+       // the contract and dial using the regular round-trip instead. Otherwise, we'll try
+       // to fall back on the Fetch API, unless it's not available.
+       if t.Dial != nil || t.DialContext != nil || t.DialTLS != nil || t.DialTLSContext != nil || jsFetchMissing {
                return t.roundTrip(req)
        }
 
index 17f0047b59982b48f910edcd2fe38111862d8e4f..0e60992e6c000fe21e18bc9f995a1d955d9078ca 100644 (file)
@@ -42,10 +42,10 @@ import (
 // $no_proxy) environment variables.
 var DefaultTransport RoundTripper = &Transport{
        Proxy: ProxyFromEnvironment,
-       DialContext: (&net.Dialer{
+       DialContext: defaultTransportDialContext(&net.Dialer{
                Timeout:   30 * time.Second,
                KeepAlive: 30 * time.Second,
-       }).DialContext,
+       }),
        ForceAttemptHTTP2:     true,
        MaxIdleConns:          100,
        IdleConnTimeout:       90 * time.Second,
diff --git a/src/net/http/transport_default_js.go b/src/net/http/transport_default_js.go
new file mode 100644 (file)
index 0000000..c07d35e
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build js && wasm
+// +build js,wasm
+
+package http
+
+import (
+       "context"
+       "net"
+)
+
+func defaultTransportDialContext(dialer *net.Dialer) func(context.Context, string, string) (net.Conn, error) {
+       return nil
+}
diff --git a/src/net/http/transport_default_other.go b/src/net/http/transport_default_other.go
new file mode 100644 (file)
index 0000000..8a2f1cc
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !(js && wasm)
+// +build !js !wasm
+
+package http
+
+import (
+       "context"
+       "net"
+)
+
+func defaultTransportDialContext(dialer *net.Dialer) func(context.Context, string, string) (net.Conn, error) {
+       return dialer.DialContext
+}