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  }