net

package
v0.13.37 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 27, 2021 License: Apache-2.0, MIT Imports: 12 Imported by: 7

Documentation

Overview

Package net provides generic network related functions used across Skipper, which might be useful also in other contexts than Skipper.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func RemoteHost

func RemoteHost(r *http.Request) net.IP

RemoteHost returns the remote address of the client. When the 'X-Forwarded-For' header is set, then it is used instead. This is how most often proxies behave. Wikipedia shows the format https://en.wikipedia.org/wiki/X-Forwarded-For#Format

Example:

X-Forwarded-For: client, proxy1, proxy2

func RemoteHostFromLast added in v0.9.164

func RemoteHostFromLast(r *http.Request) net.IP

RemoteHostFromLast returns the remote address of the client. When the 'X-Forwarded-For' header is set, then it is used instead. This is known to be true for AWS Application LoadBalancer. AWS docs https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/x-forwarded-headers.html

Example:

X-Forwarded-For: ip-address-1, ip-address-2, client-ip-address

Types

type Client added in v0.11.42

type Client struct {
	// contains filtered or unexported fields
}

Client adds additional features like Bearer token injection, and opentracing to the wrapped http.Client with the same interface as http.Client from the stdlib.

Example
tracer := lightstep.NewTracer(lightstep.Options{})

cli := net.NewClient(net.Options{
	Tracer:                     tracer,
	OpentracingComponentTag:    "testclient",
	OpentracingSpanName:        "clientSpan",
	BearerTokenRefreshInterval: 10 * time.Second,
	BearerTokenFile:            "/tmp/foo.token",
	IdleConnTimeout:            2 * time.Second,
})
defer cli.Close()

srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	log.Printf("Authorization: %s", r.Header.Get("Authorization"))
	log.Printf("Ot-Tracer-Sampled: %s", r.Header.Get("Ot-Tracer-Sampled"))
	log.Printf("Ot-Tracer-Traceid: %s", r.Header.Get("Ot-Tracer-Traceid"))
	log.Printf("Ot-Tracer-Spanid: %s", r.Header.Get("Ot-Tracer-Spanid"))
	w.WriteHeader(http.StatusOK)
}))
defer srv.Close()

u := "http://" + srv.Listener.Addr().String() + "/"

for i := 0; i < 15; i++ {
	rsp, err := cli.Get(u)
	if err != nil {
		log.Fatalf("Failed to do request: %v", err)
	}
	log.Printf("rsp code: %v", rsp.StatusCode)
	time.Sleep(1 * time.Second)
}
Output:

Example (FileSecretsReader)
tracer := lightstep.NewTracer(lightstep.Options{})

sp := secrets.NewSecretPaths(10 * time.Second)
if err := sp.Add("/tmp/bar.token"); err != nil {
	log.Fatalf("failed to read secret: %v", err)
}

cli := net.NewClient(net.Options{
	Tracer:                  tracer,
	OpentracingComponentTag: "testclient",
	OpentracingSpanName:     "clientSpan",
	SecretsReader:           sp,
	IdleConnTimeout:         2 * time.Second,
})
defer cli.Close()

srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	log.Printf("Authorization: %s", r.Header.Get("Authorization"))
	log.Printf("Ot-Tracer-Sampled: %s", r.Header.Get("Ot-Tracer-Sampled"))
	log.Printf("Ot-Tracer-Traceid: %s", r.Header.Get("Ot-Tracer-Traceid"))
	log.Printf("Ot-Tracer-Spanid: %s", r.Header.Get("Ot-Tracer-Spanid"))
	w.WriteHeader(http.StatusOK)
}))
defer srv.Close()

u := "http://" + srv.Listener.Addr().String() + "/"

for i := 0; i < 15; i++ {
	rsp, err := cli.Get(u)
	if err != nil {
		log.Fatalf("Failed to do request: %v", err)
	}
	log.Printf("rsp code: %v", rsp.StatusCode)
	time.Sleep(1 * time.Second)
}
Output:

Example (HostSecret)
tracer := lightstep.NewTracer(lightstep.Options{})
sec := []byte("mysecret")

cli := net.NewClient(net.Options{
	Tracer:                  tracer,
	OpentracingComponentTag: "testclient",
	OpentracingSpanName:     "clientSpan",
	SecretsReader: secrets.NewHostSecret(
		newTestSecretsReader(
			map[string][]byte{
				"key": sec,
			},
		),
		map[string]string{
			"127.0.0.1": "key",
		},
	),
	IdleConnTimeout: 2 * time.Second,
})
defer cli.Close()

srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	log.Printf("Authorization: %s", r.Header.Get("Authorization"))
	log.Printf("Ot-Tracer-Sampled: %s", r.Header.Get("Ot-Tracer-Sampled"))
	log.Printf("Ot-Tracer-Traceid: %s", r.Header.Get("Ot-Tracer-Traceid"))
	log.Printf("Ot-Tracer-Spanid: %s", r.Header.Get("Ot-Tracer-Spanid"))
	w.WriteHeader(http.StatusOK)
}))
defer srv.Close()

u := "http://" + srv.Listener.Addr().String() + "/"

for i := 0; i < 15; i++ {
	rsp, err := cli.Get(u)
	if err != nil {
		log.Fatalf("Failed to do request: %v", err)
	}
	log.Printf("rsp code: %v", rsp.StatusCode)
	time.Sleep(1 * time.Second)
}
Output:

Example (StaticDelegateSecret)
tracer := lightstep.NewTracer(lightstep.Options{})
sec := []byte("mysecret")

cli := net.NewClient(net.Options{
	Tracer:                  tracer,
	OpentracingComponentTag: "testclient",
	OpentracingSpanName:     "clientSpan",
	SecretsReader: secrets.NewStaticDelegateSecret(
		newTestSecretsReader(
			map[string][]byte{
				"key": sec,
			},
		),
		"key",
	),
	IdleConnTimeout: 2 * time.Second,
})
defer cli.Close()

srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	log.Printf("Authorization: %s", r.Header.Get("Authorization"))
	log.Printf("Ot-Tracer-Sampled: %s", r.Header.Get("Ot-Tracer-Sampled"))
	log.Printf("Ot-Tracer-Traceid: %s", r.Header.Get("Ot-Tracer-Traceid"))
	log.Printf("Ot-Tracer-Spanid: %s", r.Header.Get("Ot-Tracer-Spanid"))
	w.WriteHeader(http.StatusOK)
}))
defer srv.Close()

u := "http://" + srv.Listener.Addr().String() + "/"

for i := 0; i < 15; i++ {
	rsp, err := cli.Get(u)
	if err != nil {
		log.Fatalf("Failed to do request: %v", err)
	}
	log.Printf("rsp code: %v", rsp.StatusCode)
	time.Sleep(1 * time.Second)
}
Output:

Example (StaticSecret)
tracer := lightstep.NewTracer(lightstep.Options{})
sec := []byte("mysecret")
cli := net.NewClient(net.Options{
	Tracer:                  tracer,
	OpentracingComponentTag: "testclient",
	OpentracingSpanName:     "clientSpan",
	SecretsReader:           secrets.StaticSecret(sec),
	IdleConnTimeout:         2 * time.Second,
})
defer cli.Close()

srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	log.Printf("Authorization: %s", r.Header.Get("Authorization"))
	log.Printf("Ot-Tracer-Sampled: %s", r.Header.Get("Ot-Tracer-Sampled"))
	log.Printf("Ot-Tracer-Traceid: %s", r.Header.Get("Ot-Tracer-Traceid"))
	log.Printf("Ot-Tracer-Spanid: %s", r.Header.Get("Ot-Tracer-Spanid"))
	w.WriteHeader(http.StatusOK)
}))
defer srv.Close()

u := "http://" + srv.Listener.Addr().String() + "/"

for i := 0; i < 15; i++ {
	rsp, err := cli.Get(u)
	if err != nil {
		log.Fatalf("Failed to do request: %v", err)
	}
	log.Printf("rsp code: %v", rsp.StatusCode)
	time.Sleep(1 * time.Second)
}
Output:

func NewClient added in v0.11.42

func NewClient(o Options) *Client

NewClient creates a wrapped http.Client and uses Transport to support OpenTracing. On teardown you have to use Close() to not leak a goroutine.

If secrets.SecretsReader is nil, but BearerTokenFile is not empty string, it creates StaticDelegateSecret with a wrapped secrets.SecretPaths, which can be used with Kubernetes secrets to read from the secret an automatically updated Bearer token.

func (*Client) Close added in v0.11.42

func (c *Client) Close()

func (*Client) CloseIdleConnections added in v0.11.42

func (c *Client) CloseIdleConnections()

CloseIdleConnections delegates the call to the underlying http.Client.

func (*Client) Do added in v0.11.42

func (c *Client) Do(req *http.Request) (*http.Response, error)

Do delegates the given http.Request to the underlying http.Client and adds a Bearer token to the authorization header, if Client has a secrets.SecretsReader and the request does not contain an Authorization header.

func (*Client) Get added in v0.11.42

func (c *Client) Get(url string) (*http.Response, error)

func (*Client) Head added in v0.11.42

func (c *Client) Head(url string) (*http.Response, error)

func (*Client) Post added in v0.11.42

func (c *Client) Post(url, contentType string, body io.Reader) (*http.Response, error)

func (*Client) PostForm added in v0.11.42

func (c *Client) PostForm(url string, data url.Values) (*http.Response, error)

type Options added in v0.11.19

type Options struct {
	// Proxy see https://golang.org/pkg/net/http/#Transport.Proxy
	Proxy func(req *http.Request) (*url.URL, error)
	// DisableKeepAlives see https://golang.org/pkg/net/http/#Transport.DisableKeepAlives
	DisableKeepAlives bool
	// DisableCompression see https://golang.org/pkg/net/http/#Transport.DisableCompression
	DisableCompression bool
	// ForceAttemptHTTP2 see https://golang.org/pkg/net/http/#Transport.ForceAttemptHTTP2
	ForceAttemptHTTP2 bool
	// MaxIdleConns see https://golang.org/pkg/net/http/#Transport.MaxIdleConns
	MaxIdleConns int
	// MaxIdleConnsPerHost see https://golang.org/pkg/net/http/#Transport.MaxIdleConnsPerHost
	MaxIdleConnsPerHost int
	// MaxConnsPerHost see https://golang.org/pkg/net/http/#Transport.MaxConnsPerHost
	MaxConnsPerHost int
	// WriteBufferSize see https://golang.org/pkg/net/http/#Transport.WriteBufferSize
	WriteBufferSize int
	// ReadBufferSize see https://golang.org/pkg/net/http/#Transport.ReadBufferSize
	ReadBufferSize int
	// MaxResponseHeaderBytes see
	// https://golang.org/pkg/net/http/#Transport.MaxResponseHeaderBytes
	MaxResponseHeaderBytes int64
	// Timeout sets all Timeouts, that are set to 0 to the given
	// value. Basically it's the default timeout value.
	Timeout time.Duration
	// TLSHandshakeTimeout see
	// https://golang.org/pkg/net/http/#Transport.TLSHandshakeTimeout,
	// if not set or set to 0, its using Options.Timeout.
	TLSHandshakeTimeout time.Duration
	// IdleConnTimeout see
	// https://golang.org/pkg/net/http/#Transport.IdleConnTimeout,
	// if not set or set to 0, its using Options.Timeout.
	IdleConnTimeout time.Duration
	// ResponseHeaderTimeout see
	// https://golang.org/pkg/net/http/#Transport.ResponseHeaderTimeout,
	// if not set or set to 0, its using Options.Timeout.
	ResponseHeaderTimeout time.Duration
	// ExpectContinueTimeout see
	// https://golang.org/pkg/net/http/#Transport.ExpectContinueTimeout,
	// if not set or set to 0, its using Options.Timeout.
	ExpectContinueTimeout time.Duration
	// Tracer instance, can be nil to not enable tracing
	Tracer opentracing.Tracer

	// BearerTokenFile injects bearer token read from file, which
	// file path is the given string. In case SecretsReader is
	// provided, BearerTokenFile will be ignored.
	BearerTokenFile string
	// BearerTokenRefreshInterval refresh bearer from
	// BearerTokenFile. In case SecretsReader is provided,
	// BearerTokenFile will be ignored.
	BearerTokenRefreshInterval time.Duration
	// SecretsReader is used to read and refresh bearer tokens
	SecretsReader secrets.SecretsReader

	// Log is used for error logging
	Log logging.Logger

	// OpentracingComponentTag sets component tag for all requests
	OpentracingComponentTag string
	// OpentracingSpanName sets span name for all requests
	OpentracingSpanName string
}

Options are mostly passed to the http.Transport of the same name. Options.Timeout can be used as default for all timeouts, that are not set. You can pass an opentracing.Tracer https://godoc.org/github.com/opentracing/opentracing-go#Tracer, which can be nil to get the https://godoc.org/github.com/opentracing/opentracing-go#NoopTracer.

type Transport added in v0.11.19

type Transport struct {
	// contains filtered or unexported fields
}

Transport wraps an http.Transport and adds support for tracing and bearerToken injection.

Example
tracer := lightstep.NewTracer(lightstep.Options{})

cli := net.NewTransport(net.Options{
	Tracer: tracer,
})
defer cli.Close()
cli = net.WithSpanName(cli, "myspan")
cli = net.WithBearerToken(cli, "mytoken")

srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	log.Printf("Authorization: %s", r.Header.Get("Authorization"))
	log.Printf("Ot-Tracer-Sampled: %s", r.Header.Get("Ot-Tracer-Sampled"))
	log.Printf("Ot-Tracer-Traceid: %s", r.Header.Get("Ot-Tracer-Traceid"))
	log.Printf("Ot-Tracer-Spanid: %s", r.Header.Get("Ot-Tracer-Spanid"))
	w.WriteHeader(http.StatusOK)
}))
defer srv.Close()

u := "http://" + srv.Listener.Addr().String() + "/"
req, err := http.NewRequest("GET", u, nil)
if err != nil {
	log.Fatalf("Failed to create request: %v", err)
}

rsp, err := cli.RoundTrip(req)
if err != nil {
	log.Fatalf("Failed to do request: %v", err)
}
log.Printf("rsp code: %v", rsp.StatusCode)
Output:

func NewTransport added in v0.11.19

func NewTransport(options Options) *Transport

NewTransport creates a wrapped http.Transport, with regular DNS lookups using CloseIdleConnections on every IdleConnTimeout. You can optionally add tracing. On teardown you have to use Close() to not leak a goroutine.

func WithBearerToken added in v0.11.19

func WithBearerToken(t *Transport, bearerToken string) *Transport

WithBearerToken adds an Authorization header with "Bearer " prefix and add the given bearerToken as value to all requests. To regular update your token you need to call this method and use the returned Transport.

func WithComponentTag added in v0.11.19

func WithComponentTag(t *Transport, componentName string) *Transport

WithComponentTag sets the component name, if you have an enabled tracing Transport.

func WithSpanName added in v0.11.19

func WithSpanName(t *Transport, spanName string) *Transport

WithSpanName sets the name of the span, if you have an enabled tracing Transport.

func (*Transport) Close added in v0.11.19

func (t *Transport) Close()

func (*Transport) CloseIdleConnections added in v0.11.42

func (t *Transport) CloseIdleConnections()

func (*Transport) RoundTrip added in v0.11.19

func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error)

RoundTrip the request with tracing, bearer token injection and add client tracing: DNS, TCP/IP, TLS handshake, connection pool access. Client traces are added as logs into the created span.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL