github.com/yaling888/clash@v1.53.0/listener/http/utils.go (about)

     1  package http
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/base64"
     6  	"errors"
     7  	"net"
     8  	"net/http"
     9  	"strings"
    10  )
    11  
    12  var basicAuthSep = []byte(":")
    13  
    14  // removeProxyHeaders remove Proxy-* headers
    15  func removeProxyHeaders(header http.Header) {
    16  	header.Del("Proxy-Connection")
    17  	header.Del("Proxy-Authenticate")
    18  	header.Del("Proxy-Authorization")
    19  }
    20  
    21  // RemoveHopByHopHeaders remove hop-by-hop header
    22  func RemoveHopByHopHeaders(header http.Header) {
    23  	// Strip hop-by-hop header based on RFC:
    24  	// http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1
    25  	// https://www.mnot.net/blog/2011/07/11/what_proxies_must_do
    26  
    27  	removeProxyHeaders(header)
    28  
    29  	header.Del("TE")
    30  	header.Del("Trailers")
    31  	header.Del("Transfer-Encoding")
    32  	header.Del("Upgrade")
    33  
    34  	connections := header.Get("Connection")
    35  	header.Del("Connection")
    36  	if len(connections) == 0 {
    37  		return
    38  	}
    39  	for _, h := range strings.Split(connections, ",") {
    40  		header.Del(strings.TrimSpace(h))
    41  	}
    42  }
    43  
    44  // RemoveExtraHTTPHostPort remove extra host port (example.com:80 --> example.com)
    45  // It resolves the behavior of some HTTP servers that do not handle host:80 (e.g. baidu.com)
    46  func RemoveExtraHTTPHostPort(req *http.Request) {
    47  	host := req.Host
    48  	if host == "" {
    49  		host = req.URL.Host
    50  	}
    51  
    52  	if pHost, port, err := net.SplitHostPort(host); err == nil && (port == "80" || port == "443") {
    53  		host = pHost
    54  	}
    55  
    56  	req.Host = host
    57  	req.URL.Host = host
    58  }
    59  
    60  // parseBasicProxyAuthorization parse header Proxy-Authorization and return base64-encoded credential
    61  func parseBasicProxyAuthorization(request *http.Request) string {
    62  	value := request.Header.Get("Proxy-Authorization")
    63  	if !strings.HasPrefix(value, "Basic ") {
    64  		return ""
    65  	}
    66  
    67  	return value[6:] // value[len("Basic "):]
    68  }
    69  
    70  // decodeBasicProxyAuthorization decode base64-encoded credential
    71  func decodeBasicProxyAuthorization(credential string) ([]byte, []byte, error) {
    72  	plain, err := base64.StdEncoding.DecodeString(credential)
    73  	if err != nil {
    74  		return nil, nil, err
    75  	}
    76  
    77  	user, pass, found := bytes.Cut(plain, basicAuthSep)
    78  	if !found {
    79  		return nil, nil, errors.New("invalid login")
    80  	}
    81  
    82  	return user, pass, nil
    83  }