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 }