code.gitea.io/gitea@v1.19.3/modules/proxy/proxy.go (about)

     1  // Copyright 2021 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package proxy
     5  
     6  import (
     7  	"net/http"
     8  	"net/url"
     9  	"os"
    10  	"strings"
    11  	"sync"
    12  
    13  	"code.gitea.io/gitea/modules/log"
    14  	"code.gitea.io/gitea/modules/setting"
    15  
    16  	"github.com/gobwas/glob"
    17  )
    18  
    19  var (
    20  	once         sync.Once
    21  	hostMatchers []glob.Glob
    22  )
    23  
    24  // GetProxyURL returns proxy url
    25  func GetProxyURL() string {
    26  	if !setting.Proxy.Enabled {
    27  		return ""
    28  	}
    29  
    30  	if setting.Proxy.ProxyURL == "" {
    31  		if os.Getenv("http_proxy") != "" {
    32  			return os.Getenv("http_proxy")
    33  		}
    34  		return os.Getenv("https_proxy")
    35  	}
    36  	return setting.Proxy.ProxyURL
    37  }
    38  
    39  // Match return true if url needs to be proxied
    40  func Match(u string) bool {
    41  	if !setting.Proxy.Enabled {
    42  		return false
    43  	}
    44  
    45  	// enforce do once
    46  	Proxy()
    47  
    48  	for _, v := range hostMatchers {
    49  		if v.Match(u) {
    50  			return true
    51  		}
    52  	}
    53  	return false
    54  }
    55  
    56  // Proxy returns the system proxy
    57  func Proxy() func(req *http.Request) (*url.URL, error) {
    58  	if !setting.Proxy.Enabled {
    59  		return func(req *http.Request) (*url.URL, error) {
    60  			return nil, nil
    61  		}
    62  	}
    63  	if setting.Proxy.ProxyURL == "" {
    64  		return http.ProxyFromEnvironment
    65  	}
    66  
    67  	once.Do(func() {
    68  		for _, h := range setting.Proxy.ProxyHosts {
    69  			if g, err := glob.Compile(h); err == nil {
    70  				hostMatchers = append(hostMatchers, g)
    71  			} else {
    72  				log.Error("glob.Compile %s failed: %v", h, err)
    73  			}
    74  		}
    75  	})
    76  
    77  	return func(req *http.Request) (*url.URL, error) {
    78  		for _, v := range hostMatchers {
    79  			if v.Match(req.URL.Host) {
    80  				return http.ProxyURL(setting.Proxy.ProxyURLFixed)(req)
    81  			}
    82  		}
    83  		return http.ProxyFromEnvironment(req)
    84  	}
    85  }
    86  
    87  // EnvWithProxy returns os.Environ(), with a https_proxy env, if the given url
    88  // needs to be proxied.
    89  func EnvWithProxy(u *url.URL) []string {
    90  	envs := os.Environ()
    91  	if strings.EqualFold(u.Scheme, "http") || strings.EqualFold(u.Scheme, "https") {
    92  		if Match(u.Host) {
    93  			envs = append(envs, "https_proxy="+GetProxyURL())
    94  		}
    95  	}
    96  
    97  	return envs
    98  }