From 1d3e30955674e10f5b9f1bb0bcbeac66948afa24 Mon Sep 17 00:00:00 2001 From: makeworld Date: Tue, 1 Sep 2020 16:22:44 -0400 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Support=20mutiple=20proxies=20per-s?= =?UTF-8?q?cheme=20-=20fixes=20#80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/client.go | 29 +++++++++++++++-------- config/config.go | 7 ------ display/private.go | 57 ++++++++++++++++++++++++++++++++++------------ 3 files changed, 63 insertions(+), 30 deletions(-) diff --git a/client/client.go b/client/client.go index 150782b..4bc1557 100644 --- a/client/client.go +++ b/client/client.go @@ -2,32 +2,43 @@ package client import ( + "net" "net/url" - "github.com/makeworld-the-better-one/amfora/config" "github.com/makeworld-the-better-one/go-gemini" - "github.com/spf13/viper" ) // Fetch returns response data and an error. // The error text is human friendly and should be displayed. func Fetch(u string) (*gemini.Response, error) { - var res *gemini.Response - var err error - if config.GemProxy == nil { - res, err = gemini.Fetch(u) - } else { - res, err = gemini.FetchWithHost(viper.GetString("proxies.gemini"), u) - } + res, err := gemini.Fetch(u) if err != nil { return nil, err } parsed, _ := url.Parse(u) + ok := handleTofu(parsed.Hostname(), parsed.Port(), res.Cert) if !ok { return res, ErrTofu } + return res, err } + +// FetchWithProxy is the same as Fetch, but uses a proxy. +func FetchWithProxy(proxyHostname, proxyPort, u string) (*gemini.Response, error) { + res, err := gemini.FetchWithHost(net.JoinHostPort(proxyHostname, proxyPort), u) + if err != nil { + return nil, err + } + + // Only associate the returned cert with the proxy + ok := handleTofu(proxyHostname, proxyPort, res.Cert) + if !ok { + return res, ErrTofu + } + + return res, nil +} diff --git a/config/config.go b/config/config.go index 12861d0..c2ba270 100644 --- a/config/config.go +++ b/config/config.go @@ -2,7 +2,6 @@ package config import ( "fmt" - "net/url" "os" "path/filepath" "runtime" @@ -34,8 +33,6 @@ var bkmkPath string var DownloadsDir string -var GemProxy *url.URL - //nolint:golint,goerr113 func Init() error { home, err := homedir.Dir() @@ -181,10 +178,6 @@ func Init() error { return err } - if viper.GetString("proxies.gemini") != "" { - GemProxy, _ = url.Parse(viper.GetString("proxies.gemini")) - } - // Setup downloads dir if viper.GetString("a-general.downloads") == "" { // Find default Downloads dir diff --git a/display/private.go b/display/private.go index efda217..acfab15 100644 --- a/display/private.go +++ b/display/private.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "net" "net/url" "os/exec" "strconv" @@ -163,7 +164,7 @@ func handleHTTP(u string, showInfo bool) { } // handleOther is used by handleURL. -// It opens or proxies links other than Gemini and HTTP and displays Error modals. +// It opens links other than Gemini and HTTP and displays Error modals. func handleOther(u string) { // The URL should have a scheme due to a previous call to normalizeURL parsed, _ := url.Parse(u) @@ -331,15 +332,38 @@ func handleURL(t *tab, u string, numRedirects int) (string, bool) { return ret("", false) } + proxy := strings.TrimSpace(viper.GetString("proxies." + parsed.Scheme)) + usingProxy := false + + proxyHostname, proxyPort, err := net.SplitHostPort(proxy) + if err != nil { + // Error likely means there's no port in the host + proxyHostname = proxy + proxyPort = "1965" + } + if strings.HasPrefix(u, "http") { - handleHTTP(u, true) - return ret("", false) + if proxy == "" || proxy == "off" { + // No proxy available + handleHTTP(u, true) + return ret("", false) + } else { + usingProxy = true + } } - if !strings.HasPrefix(u, "gemini") { - handleOther(u) - return ret("", false) + + if !strings.HasPrefix(u, "http") && !strings.HasPrefix(u, "gemini") { + // Not a Gemini URL + if proxy == "" || proxy == "off" { + // No proxy available + handleOther(u) + return ret("", false) + } else { + usingProxy = true + } } - // Gemini URL + + // Gemini URL, or one with a Gemini proxy available // Load page from cache if possible page, ok := cache.GetPage(u) @@ -353,7 +377,12 @@ func handleURL(t *tab, u string, numRedirects int) (string, bool) { t.mode = tabModeLoading App.Draw() - res, err := client.Fetch(u) + var res *gemini.Response + if usingProxy { + res, err = client.FetchWithProxy(proxyHostname, proxyPort, u) + } else { + res, err = client.Fetch(u) + } // Loading may have taken a while, make sure tab is still valid if !isValidTab(t) { @@ -361,20 +390,20 @@ func handleURL(t *tab, u string, numRedirects int) (string, bool) { } if errors.Is(err, client.ErrTofu) { - if config.GemProxy == nil { - if Tofu(parsed.Host, client.GetExpiry(parsed.Hostname(), parsed.Port())) { + if usingProxy { + // They are using a proxy + if Tofu(proxy, client.GetExpiry(proxyHostname, proxyPort)) { // They want to continue anyway - client.ResetTofuEntry(parsed.Hostname(), parsed.Port(), res.Cert) + client.ResetTofuEntry(proxyHostname, proxyPort, res.Cert) // Response can be used further down, no need to reload } else { // They don't want to continue return ret("", false) } } else { - // They are using a proxy - if Tofu(config.GemProxy.Host, client.GetExpiry(config.GemProxy.Hostname(), config.GemProxy.Port())) { + if Tofu(parsed.Host, client.GetExpiry(parsed.Hostname(), parsed.Port())) { // They want to continue anyway - client.ResetTofuEntry(config.GemProxy.Hostname(), config.GemProxy.Port(), res.Cert) + client.ResetTofuEntry(parsed.Hostname(), parsed.Port(), res.Cert) // Response can be used further down, no need to reload } else { // They don't want to continue