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