You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@casbin.apache.org by hs...@apache.org on 2026/08/18 10:22:52 UTC
(casbin-gateway) branch master updated: fix: route outbound requests through the configured httpProxy
This is an automated email from the ASF dual-hosted git repository.
hsluoyz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/casbin-gateway.git
The following commit(s) were added to refs/heads/master by this push:
new d83c6ba fix: route outbound requests through the configured httpProxy
d83c6ba is described below
commit d83c6bad291dd8bae3edd325b952d44ec0c02133
Author: Yang Luo <hs...@gmail.com>
AuthorDate: Tue Aug 18 18:22:24 2026 +0800
fix: route outbound requests through the configured httpProxy
---
controllers/proxy.go | 3 +-
object/cert_whois.go | 6 ---
object/channel.go | 4 +-
object/site_cert_account.go | 3 +-
proxy/proxy.go | 103 +++++++++++++++++++++-----------------------
5 files changed, 57 insertions(+), 62 deletions(-)
diff --git a/controllers/proxy.go b/controllers/proxy.go
index 892d29a..45b9dc1 100644
--- a/controllers/proxy.go
+++ b/controllers/proxy.go
@@ -27,6 +27,7 @@ import (
"time"
"github.com/apache/casbin-gateway/object"
+ "github.com/apache/casbin-gateway/proxy"
"github.com/beego/beego"
)
@@ -77,7 +78,7 @@ type openaiErrorDetail struct {
var proxyClient = &http.Client{
CheckRedirect: func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse },
Transport: &http.Transport{
- Proxy: http.ProxyFromEnvironment,
+ Proxy: proxy.Proxy,
DialContext: (&net.Dialer{
Timeout: 10 * time.Second,
KeepAlive: 30 * time.Second,
diff --git a/object/cert_whois.go b/object/cert_whois.go
index 9513a8a..85c678a 100644
--- a/object/cert_whois.go
+++ b/object/cert_whois.go
@@ -47,12 +47,6 @@ func getDomainExpireTime(domainName string) (string, error) {
}
client := whois.NewClient()
- //if server != "whois.cnnic.cn" && server != "grs-whois.hichina.com" {
- // dialer := proxy.GetProxyDialer()
- // if dialer != nil {
- // client.SetDialer(dialer)
- // }
- //}
data, err := client.Whois(domainName, server)
if err != nil {
diff --git a/object/channel.go b/object/channel.go
index a638b47..b11489c 100644
--- a/object/channel.go
+++ b/object/channel.go
@@ -23,6 +23,7 @@ import (
"strings"
"time"
+ "github.com/apache/casbin-gateway/proxy"
"github.com/apache/casbin-gateway/util"
"github.com/xorm-io/core"
)
@@ -304,7 +305,8 @@ func TestChannelConnectivity(channel *Channel) (bool, int, string) {
}
client := &http.Client{
- Timeout: 10 * time.Second,
+ Timeout: 10 * time.Second,
+ Transport: proxy.Transport(),
// Do not follow redirects, so the reported status is the one the
// configured base URL actually returns.
CheckRedirect: func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse },
diff --git a/object/site_cert_account.go b/object/site_cert_account.go
index 5755f70..5a1f546 100644
--- a/object/site_cert_account.go
+++ b/object/site_cert_account.go
@@ -17,6 +17,7 @@ package object
import (
"crypto"
"fmt"
+ "net/http"
"github.com/apache/casbin-gateway/proxy"
"github.com/beego/beego"
@@ -70,7 +71,7 @@ func getLegoClientAndAccount(email string, privateKey string, devMode bool, useP
if useProxy {
config.HTTPClient = proxy.ProxyHttpClient
} else {
- config.HTTPClient = proxy.DefaultHttpClient
+ config.HTTPClient = http.DefaultClient
}
client, err := lego.NewClient(config)
diff --git a/proxy/proxy.go b/proxy/proxy.go
index 0b2535e..ff955fb 100644
--- a/proxy/proxy.go
+++ b/proxy/proxy.go
@@ -12,83 +12,80 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// Package proxy routes every outbound request through the proxy configured as
+// httpProxy in conf/app.conf, falling back to the HTTP_PROXY / HTTPS_PROXY
+// environment variables when that setting is empty.
package proxy
import (
"fmt"
- "net"
"net/http"
- "time"
+ "net/url"
+ "strings"
+ "sync"
"github.com/beego/beego"
- "golang.org/x/net/proxy"
)
-var DefaultHttpClient *http.Client
+// ProxyHttpClient sends its requests through the configured proxy.
var ProxyHttpClient *http.Client
-func InitHttpClient() {
- // not use proxy
- DefaultHttpClient = http.DefaultClient
-
- // use proxy
- ProxyHttpClient = getProxyHttpClient()
-}
-
-func isAddressOpen(address string) bool {
- timeout := time.Millisecond * 100
- conn, err := net.DialTimeout("tcp", address, timeout)
- if err != nil {
- // cannot connect to address, proxy is not active
- return false
- }
+var (
+ proxyUrlOnce sync.Once
+ proxyUrl *url.URL
- if conn != nil {
- defer conn.Close()
- fmt.Printf("Socks5 proxy enabled: %s\n", address)
- return true
- }
+ transportOnce sync.Once
+ transport *http.Transport
+)
- return false
+func InitHttpClient() {
+ proxyUrlOnce.Do(initProxyUrl)
+ ProxyHttpClient = &http.Client{Transport: Transport()}
}
-func getProxyHttpClient() *http.Client {
- httpProxy := beego.AppConfig.String("httpProxy")
- if httpProxy == "" {
- return &http.Client{}
- }
-
- if !isAddressOpen(httpProxy) {
- return &http.Client{}
- }
-
- // https://stackoverflow.com/questions/33585587/creating-a-go-socks5-client
- dialer, err := proxy.SOCKS5("tcp", httpProxy, nil, proxy.Direct)
- if err != nil {
- panic(err)
+// Proxy picks the proxy to reach req through. It is meant to be assigned to
+// http.Transport.Proxy, which calls it per request, so the httpProxy setting is
+// read on first use instead of at package initialization: in -tags embed builds
+// the embedded conf/app.conf is only loaded once main's init() runs, after every
+// imported package has already initialized its own variables.
+func Proxy(req *http.Request) (*url.URL, error) {
+ proxyUrlOnce.Do(initProxyUrl)
+ if proxyUrl == nil {
+ return http.ProxyFromEnvironment(req)
}
+ return proxyUrl, nil
+}
- tr := &http.Transport{Dial: dialer.Dial}
- return &http.Client{
- Transport: tr,
- }
+// Transport returns the shared transport for outbound requests. Sharing one
+// instance keeps the connection pool shared as well.
+func Transport() *http.Transport {
+ transportOnce.Do(func() {
+ transport = http.DefaultTransport.(*http.Transport).Clone()
+ transport.Proxy = Proxy
+ })
+ return transport
}
-func GetProxyDialer() *net.Dialer {
- httpProxy := beego.AppConfig.String("httpProxy")
+// initProxyUrl parses the httpProxy setting. A bare "host:port" means SOCKS5,
+// which is what the setting has always been taken to mean; "socks5://",
+// "socks5h://", "http://" and "https://" addresses are honoured as written, and
+// may carry credentials.
+func initProxyUrl() {
+ httpProxy := strings.TrimSpace(beego.AppConfig.String("httpProxy"))
if httpProxy == "" {
- return nil
+ return
}
- if !isAddressOpen(httpProxy) {
- return nil
+ if !strings.Contains(httpProxy, "://") {
+ httpProxy = "socks5://" + httpProxy
}
- // https://stackoverflow.com/questions/33585587/creating-a-go-socks5-client
- dialer, err := proxy.SOCKS5("tcp", httpProxy, nil, proxy.Direct)
- if err != nil {
- panic(err)
+ parsedUrl, err := url.Parse(httpProxy)
+ if err != nil || parsedUrl.Host == "" {
+ fmt.Printf("httpProxy is not a valid proxy address, outbound traffic is left unproxied: %s\n", httpProxy)
+ return
}
- return dialer.(*net.Dialer)
+ proxyUrl = parsedUrl
+ fmt.Printf("Proxy enabled for outbound traffic: %s\n", proxyUrl.Redacted())
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@casbin.apache.org
For additional commands, e-mail: commits-help@casbin.apache.org