1
0
mirror of https://github.com/makew0rld/amfora.git synced 2024-12-04 14:46:29 -05:00

Support mutiple proxies per-scheme - fixes #80

This commit is contained in:
makeworld 2020-09-01 16:22:44 -04:00
parent 30873e1b0b
commit 1d3e309556
3 changed files with 63 additions and 30 deletions

View File

@ -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
}

View File

@ -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

View File

@ -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