github.com/searKing/golang/go@v1.2.117/net/http/httpproxy/proxy.go (about)

     1  // Copyright 2022 The searKing Author. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package httpproxy
     6  
     7  import (
     8  	"context"
     9  	"fmt"
    10  	"net/url"
    11  
    12  	"github.com/searKing/golang/go/net/resolver"
    13  )
    14  
    15  // unique type to prevent assignment.
    16  type proxyContextKey struct{}
    17  
    18  // Proxy specifies ProxyUrl and ProxyTarget to return a dynamic proxy.
    19  type Proxy struct {
    20  	// ProxyUrl is proxy's url, like socks5://127.0.0.1:8080
    21  	ProxyUrl string
    22  	// ProxyTarget is as like gRPC Naming for proxy service discovery, with Host in ProxyUrl replaced if not empty.
    23  	ProxyTarget string
    24  
    25  	// ProxyAddrResolved is the proxy's addr resolved and picked from resolver.
    26  	ProxyAddrResolved resolver.Address
    27  }
    28  
    29  // ContextProxy returns the Proxy associated with the
    30  // provided context. If none, it returns nil.
    31  func ContextProxy(ctx context.Context) *Proxy {
    32  	proxy, _ := ctx.Value(proxyContextKey{}).(*Proxy)
    33  	return proxy
    34  }
    35  
    36  // WithProxy returns a new context based on the provided parent
    37  // ctx. HTTP client requests made with the returned context will use
    38  // the provided proxy hooks
    39  func WithProxy(ctx context.Context, proxy *Proxy) context.Context {
    40  	if proxy == nil {
    41  		panic("nil proxy")
    42  	}
    43  	return context.WithValue(ctx, proxyContextKey{}, proxy)
    44  }
    45  
    46  func ParseProxyUrl(proxy string) (*url.URL, error) {
    47  	if proxy == "" {
    48  		return nil, nil
    49  	}
    50  
    51  	proxyURL, err := url.Parse(proxy)
    52  	if err != nil ||
    53  		(proxyURL.Scheme != "http" &&
    54  			proxyURL.Scheme != "https" &&
    55  			proxyURL.Scheme != "socks5") {
    56  		// proxy was bogus. Try prepending "http://" to it and
    57  		// see if that parses correctly. If not, we fall
    58  		// through and complain about the original one.
    59  		if proxyURL, err := url.Parse("http://" + proxy); err == nil {
    60  			return proxyURL, nil
    61  		}
    62  	}
    63  	if err != nil {
    64  		return nil, fmt.Errorf("invalid proxy address %q: %v", proxy, err)
    65  	}
    66  	return proxyURL, nil
    67  }