github.com/searKing/golang/go@v1.2.117/net/http/proxy.go (about) 1 // Copyright 2020 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 http 6 7 import ( 8 "net/http" 9 "net/url" 10 "regexp" 11 ) 12 13 var ( 14 reForwardedHost = regexp.MustCompile(`host=([^,]+)`) 15 reForwardedProto = regexp.MustCompile(`proto=(https?)`) 16 ) 17 18 // GetProxySchemeAndHost extracts the host and used protocol (either HTTP or HTTPS) 19 // from the given request. If `allowForwarded` is set, the X-Forwarded-Host, 20 // X-Forwarded-Proto and Forwarded headers will also be checked to 21 // support proxies. 22 func GetProxySchemeAndHost(r *http.Request, allowForwarded bool) (scheme, host string) { 23 if r == nil { 24 return 25 } 26 if r.TLS != nil { 27 scheme = "https" 28 } else { 29 scheme = "http" 30 } 31 32 host = r.Host 33 34 if !allowForwarded { 35 return 36 } 37 38 if h := r.Header.Get("X-Forwarded-Host"); h != "" { 39 host = h 40 } 41 42 if h := r.Header.Get("X-Forwarded-Proto"); h == "http" || h == "https" { 43 scheme = h 44 } 45 46 if h := r.Header.Get("Forwarded"); h != "" { 47 if r := reForwardedHost.FindStringSubmatch(h); len(r) == 2 { 48 host = r[1] 49 } 50 51 if r := reForwardedProto.FindStringSubmatch(h); len(r) == 2 { 52 scheme = r[1] 53 } 54 } 55 56 return 57 } 58 59 // ResolveProxyUrl resolves a URI reference to a URI from 60 // a URI u and origin [scheme,host] forwarded behind proxy in r. 61 // ResolveProxyUrl always returns a new URL instance, 62 // even if the returned URL is identical to either the 63 // base or reference. 64 func ResolveProxyUrl(u *url.URL, r *http.Request, allowForwarded bool) *url.URL { 65 if u == nil { 66 return nil 67 } 68 u2 := *u 69 scheme, host := GetProxySchemeAndHost(r, allowForwarded) 70 u2.Scheme = scheme 71 u2.Host = host 72 return &u2 73 }