refactor: continue to simplify engine/netx (#769)
The objective of this diff is to simplify the code inside engine/netx while moving more bits of code inside netxlite. See https://github.com/ooni/probe/issues/2121
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
package httptransport
|
||||
|
||||
import "github.com/ooni/probe-cli/v3/internal/bytecounter"
|
||||
|
||||
type ByteCountingTransport = bytecounter.HTTPTransport
|
||||
@@ -1,62 +0,0 @@
|
||||
package httptransport
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
type FakeDialer struct {
|
||||
Conn net.Conn
|
||||
Err error
|
||||
}
|
||||
|
||||
func (d FakeDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
time.Sleep(10 * time.Microsecond)
|
||||
return d.Conn, d.Err
|
||||
}
|
||||
|
||||
type FakeTransport struct {
|
||||
Name string
|
||||
Err error
|
||||
Func func(*http.Request) (*http.Response, error)
|
||||
Resp *http.Response
|
||||
}
|
||||
|
||||
func (txp FakeTransport) Network() string {
|
||||
return txp.Name
|
||||
}
|
||||
|
||||
func (txp FakeTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
time.Sleep(10 * time.Microsecond)
|
||||
if txp.Func != nil {
|
||||
return txp.Func(req)
|
||||
}
|
||||
if req.Body != nil {
|
||||
netxlite.ReadAllContext(req.Context(), req.Body)
|
||||
req.Body.Close()
|
||||
}
|
||||
if txp.Err != nil {
|
||||
return nil, txp.Err
|
||||
}
|
||||
txp.Resp.Request = req // non thread safe but it doesn't matter
|
||||
return txp.Resp, nil
|
||||
}
|
||||
|
||||
func (txp FakeTransport) CloseIdleConnections() {}
|
||||
|
||||
type FakeBody struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
func (fb FakeBody) Read(p []byte) (int, error) {
|
||||
time.Sleep(10 * time.Microsecond)
|
||||
return 0, fb.Err
|
||||
}
|
||||
|
||||
func (fb FakeBody) Close() error {
|
||||
return nil
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package httptransport
|
||||
|
||||
import (
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
// NewHTTP3Transport creates a new HTTP3Transport instance.
|
||||
//
|
||||
// Deprecation warning
|
||||
//
|
||||
// New code should use netxlite.NewHTTP3Transport instead.
|
||||
func NewHTTP3Transport(config Config) model.HTTPTransport {
|
||||
// Rationale for using NoLogger here: previously this code did
|
||||
// not use a logger as well, so it's fine to keep it as is.
|
||||
return netxlite.NewHTTP3Transport(&NoLogger{},
|
||||
config.QUICDialer, config.TLSConfig)
|
||||
}
|
||||
|
||||
type NoLogger struct{}
|
||||
|
||||
func (*NoLogger) Debug(message string) {}
|
||||
|
||||
func (*NoLogger) Debugf(format string, v ...interface{}) {}
|
||||
@@ -1,40 +0,0 @@
|
||||
package httptransport_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/httptransport"
|
||||
"github.com/ooni/probe-cli/v3/internal/model/mocks"
|
||||
)
|
||||
|
||||
func TestNewHTTP3Transport(t *testing.T) {
|
||||
// make sure we can create a working transport using this factory.
|
||||
expected := errors.New("mocked error")
|
||||
txp := httptransport.NewHTTP3Transport(httptransport.Config{
|
||||
QUICDialer: &mocks.QUICDialer{
|
||||
MockDialContext: func(ctx context.Context, network, address string,
|
||||
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
|
||||
return nil, expected
|
||||
},
|
||||
MockCloseIdleConnections: func() {
|
||||
// nothing
|
||||
},
|
||||
},
|
||||
})
|
||||
req, err := http.NewRequest("GET", "https://google.com", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
resp, err := txp.RoundTrip(req)
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("unexpected err", err)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Fatal("expected nil resp")
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"crypto/tls"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
// Config contains the configuration required for constructing an HTTP transport
|
||||
@@ -14,3 +15,25 @@ type Config struct {
|
||||
TLSDialer model.TLSDialer
|
||||
TLSConfig *tls.Config
|
||||
}
|
||||
|
||||
// NewHTTP3Transport creates a new HTTP3Transport instance.
|
||||
//
|
||||
// Deprecation warning
|
||||
//
|
||||
// New code should use netxlite.NewHTTP3Transport instead.
|
||||
func NewHTTP3Transport(config Config) model.HTTPTransport {
|
||||
// Rationale for using NoLogger here: previously this code did
|
||||
// not use a logger as well, so it's fine to keep it as is.
|
||||
return netxlite.NewHTTP3Transport(model.DiscardLogger,
|
||||
config.QUICDialer, config.TLSConfig)
|
||||
}
|
||||
|
||||
// NewSystemTransport creates a new "system" HTTP transport. That is a transport
|
||||
// using the Go standard library with custom dialer and TLS dialer.
|
||||
//
|
||||
// Deprecation warning
|
||||
//
|
||||
// New code should use netxlite.NewHTTPTransport instead.
|
||||
func NewSystemTransport(config Config) model.HTTPTransport {
|
||||
return netxlite.NewOOHTTPBaseTransport(config.Dialer, config.TLSDialer)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@@ -76,7 +77,7 @@ func TestSaverMetadataFailure(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
saver := &trace.Saver{}
|
||||
txp := httptransport.SaverMetadataHTTPTransport{
|
||||
HTTPTransport: httptransport.FakeTransport{
|
||||
HTTPTransport: FakeTransport{
|
||||
Err: expected,
|
||||
},
|
||||
Saver: saver,
|
||||
@@ -161,7 +162,7 @@ func TestSaverTransactionFailure(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
saver := &trace.Saver{}
|
||||
txp := httptransport.SaverTransactionHTTPTransport{
|
||||
HTTPTransport: httptransport.FakeTransport{
|
||||
HTTPTransport: FakeTransport{
|
||||
Err: expected,
|
||||
},
|
||||
Saver: saver,
|
||||
@@ -201,7 +202,7 @@ func TestSaverTransactionFailure(t *testing.T) {
|
||||
func TestSaverBodySuccess(t *testing.T) {
|
||||
saver := new(trace.Saver)
|
||||
txp := httptransport.SaverBodyHTTPTransport{
|
||||
HTTPTransport: httptransport.FakeTransport{
|
||||
HTTPTransport: FakeTransport{
|
||||
Func: func(req *http.Request) (*http.Response, error) {
|
||||
data, err := netxlite.ReadAllContext(context.Background(), req.Body)
|
||||
if err != nil {
|
||||
@@ -272,7 +273,7 @@ func TestSaverBodySuccess(t *testing.T) {
|
||||
func TestSaverBodyRequestReadError(t *testing.T) {
|
||||
saver := new(trace.Saver)
|
||||
txp := httptransport.SaverBodyHTTPTransport{
|
||||
HTTPTransport: httptransport.FakeTransport{
|
||||
HTTPTransport: FakeTransport{
|
||||
Func: func(req *http.Request) (*http.Response, error) {
|
||||
panic("should not be called")
|
||||
},
|
||||
@@ -281,7 +282,7 @@ func TestSaverBodyRequestReadError(t *testing.T) {
|
||||
Saver: saver,
|
||||
}
|
||||
expected := errors.New("mocked error")
|
||||
body := httptransport.FakeBody{Err: expected}
|
||||
body := FakeBody{Err: expected}
|
||||
req, err := http.NewRequest("POST", "http://x.org/y", body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -303,7 +304,7 @@ func TestSaverBodyRoundTripError(t *testing.T) {
|
||||
saver := new(trace.Saver)
|
||||
expected := errors.New("mocked error")
|
||||
txp := httptransport.SaverBodyHTTPTransport{
|
||||
HTTPTransport: httptransport.FakeTransport{
|
||||
HTTPTransport: FakeTransport{
|
||||
Err: expected,
|
||||
},
|
||||
SnapshotSize: 4,
|
||||
@@ -343,11 +344,11 @@ func TestSaverBodyResponseReadError(t *testing.T) {
|
||||
saver := new(trace.Saver)
|
||||
expected := errors.New("mocked error")
|
||||
txp := httptransport.SaverBodyHTTPTransport{
|
||||
HTTPTransport: httptransport.FakeTransport{
|
||||
HTTPTransport: FakeTransport{
|
||||
Func: func(req *http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: httptransport.FakeBody{
|
||||
Body: FakeBody{
|
||||
Err: expected,
|
||||
},
|
||||
}, nil
|
||||
@@ -417,3 +418,55 @@ func TestCloneHeaders(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
type FakeDialer struct {
|
||||
Conn net.Conn
|
||||
Err error
|
||||
}
|
||||
|
||||
func (d FakeDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
time.Sleep(10 * time.Microsecond)
|
||||
return d.Conn, d.Err
|
||||
}
|
||||
|
||||
type FakeTransport struct {
|
||||
Name string
|
||||
Err error
|
||||
Func func(*http.Request) (*http.Response, error)
|
||||
Resp *http.Response
|
||||
}
|
||||
|
||||
func (txp FakeTransport) Network() string {
|
||||
return txp.Name
|
||||
}
|
||||
|
||||
func (txp FakeTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
time.Sleep(10 * time.Microsecond)
|
||||
if txp.Func != nil {
|
||||
return txp.Func(req)
|
||||
}
|
||||
if req.Body != nil {
|
||||
netxlite.ReadAllContext(req.Context(), req.Body)
|
||||
req.Body.Close()
|
||||
}
|
||||
if txp.Err != nil {
|
||||
return nil, txp.Err
|
||||
}
|
||||
txp.Resp.Request = req // non thread safe but it doesn't matter
|
||||
return txp.Resp, nil
|
||||
}
|
||||
|
||||
func (txp FakeTransport) CloseIdleConnections() {}
|
||||
|
||||
type FakeBody struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
func (fb FakeBody) Read(p []byte) (int, error) {
|
||||
time.Sleep(10 * time.Microsecond)
|
||||
return 0, fb.Err
|
||||
}
|
||||
|
||||
func (fb FakeBody) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
package httptransport
|
||||
|
||||
import (
|
||||
oohttp "github.com/ooni/oohttp"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
)
|
||||
|
||||
// NewSystemTransport creates a new "system" HTTP transport. That is a transport
|
||||
// using the Go standard library with custom dialer and TLS dialer.
|
||||
//
|
||||
// Deprecation warning
|
||||
//
|
||||
// New code should use netxlite.NewHTTPTransport instead.
|
||||
func NewSystemTransport(config Config) model.HTTPTransport {
|
||||
txp := oohttp.DefaultTransport.(*oohttp.Transport).Clone()
|
||||
txp.DialContext = config.Dialer.DialContext
|
||||
txp.DialTLSContext = config.TLSDialer.DialTLSContext
|
||||
// Better for Cloudflare DNS and also better because we have less
|
||||
// noisy events and we can better understand what happened.
|
||||
txp.MaxConnsPerHost = 1
|
||||
// The following (1) reduces the number of headers that Go will
|
||||
// automatically send for us and (2) ensures that we always receive
|
||||
// back the true headers, such as Content-Length. This change is
|
||||
// functional to OONI's goal of observing the network.
|
||||
txp.DisableCompression = true
|
||||
return &SystemTransportWrapper{&oohttp.StdlibTransport{Transport: txp}}
|
||||
}
|
||||
|
||||
// SystemTransportWrapper adapts *http.Transport to have the .Network method
|
||||
type SystemTransportWrapper struct {
|
||||
*oohttp.StdlibTransport
|
||||
}
|
||||
|
||||
func (txp *SystemTransportWrapper) Network() string {
|
||||
return "tcp"
|
||||
}
|
||||
|
||||
var _ model.HTTPTransport = &SystemTransportWrapper{}
|
||||
Reference in New Issue
Block a user