Skip to content

Commit 1d3e309

Browse files
committed
✨ Support mutiple proxies per-scheme - fixes #80
1 parent 30873e1 commit 1d3e309

File tree

3 files changed

+63
-30
lines changed

3 files changed

+63
-30
lines changed

client/client.go

+20-9
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,43 @@
22
package client
33

44
import (
5+
"net"
56
"net/url"
67

7-
"github.com/makeworld-the-better-one/amfora/config"
88
"github.com/makeworld-the-better-one/go-gemini"
9-
"github.com/spf13/viper"
109
)
1110

1211
// Fetch returns response data and an error.
1312
// The error text is human friendly and should be displayed.
1413
func Fetch(u string) (*gemini.Response, error) {
15-
var res *gemini.Response
16-
var err error
1714

18-
if config.GemProxy == nil {
19-
res, err = gemini.Fetch(u)
20-
} else {
21-
res, err = gemini.FetchWithHost(viper.GetString("proxies.gemini"), u)
22-
}
15+
res, err := gemini.Fetch(u)
2316
if err != nil {
2417
return nil, err
2518
}
2619

2720
parsed, _ := url.Parse(u)
21+
2822
ok := handleTofu(parsed.Hostname(), parsed.Port(), res.Cert)
2923
if !ok {
3024
return res, ErrTofu
3125
}
26+
3227
return res, err
3328
}
29+
30+
// FetchWithProxy is the same as Fetch, but uses a proxy.
31+
func FetchWithProxy(proxyHostname, proxyPort, u string) (*gemini.Response, error) {
32+
res, err := gemini.FetchWithHost(net.JoinHostPort(proxyHostname, proxyPort), u)
33+
if err != nil {
34+
return nil, err
35+
}
36+
37+
// Only associate the returned cert with the proxy
38+
ok := handleTofu(proxyHostname, proxyPort, res.Cert)
39+
if !ok {
40+
return res, ErrTofu
41+
}
42+
43+
return res, nil
44+
}

config/config.go

-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package config
22

33
import (
44
"fmt"
5-
"net/url"
65
"os"
76
"path/filepath"
87
"runtime"
@@ -34,8 +33,6 @@ var bkmkPath string
3433

3534
var DownloadsDir string
3635

37-
var GemProxy *url.URL
38-
3936
//nolint:golint,goerr113
4037
func Init() error {
4138
home, err := homedir.Dir()
@@ -181,10 +178,6 @@ func Init() error {
181178
return err
182179
}
183180

184-
if viper.GetString("proxies.gemini") != "" {
185-
GemProxy, _ = url.Parse(viper.GetString("proxies.gemini"))
186-
}
187-
188181
// Setup downloads dir
189182
if viper.GetString("a-general.downloads") == "" {
190183
// Find default Downloads dir

display/private.go

+43-14
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"errors"
66
"fmt"
77
"io"
8+
"net"
89
"net/url"
910
"os/exec"
1011
"strconv"
@@ -163,7 +164,7 @@ func handleHTTP(u string, showInfo bool) {
163164
}
164165

165166
// handleOther is used by handleURL.
166-
// It opens or proxies links other than Gemini and HTTP and displays Error modals.
167+
// It opens links other than Gemini and HTTP and displays Error modals.
167168
func handleOther(u string) {
168169
// The URL should have a scheme due to a previous call to normalizeURL
169170
parsed, _ := url.Parse(u)
@@ -331,15 +332,38 @@ func handleURL(t *tab, u string, numRedirects int) (string, bool) {
331332
return ret("", false)
332333
}
333334

335+
proxy := strings.TrimSpace(viper.GetString("proxies." + parsed.Scheme))
336+
usingProxy := false
337+
338+
proxyHostname, proxyPort, err := net.SplitHostPort(proxy)
339+
if err != nil {
340+
// Error likely means there's no port in the host
341+
proxyHostname = proxy
342+
proxyPort = "1965"
343+
}
344+
334345
if strings.HasPrefix(u, "http") {
335-
handleHTTP(u, true)
336-
return ret("", false)
346+
if proxy == "" || proxy == "off" {
347+
// No proxy available
348+
handleHTTP(u, true)
349+
return ret("", false)
350+
} else {
351+
usingProxy = true
352+
}
337353
}
338-
if !strings.HasPrefix(u, "gemini") {
339-
handleOther(u)
340-
return ret("", false)
354+
355+
if !strings.HasPrefix(u, "http") && !strings.HasPrefix(u, "gemini") {
356+
// Not a Gemini URL
357+
if proxy == "" || proxy == "off" {
358+
// No proxy available
359+
handleOther(u)
360+
return ret("", false)
361+
} else {
362+
usingProxy = true
363+
}
341364
}
342-
// Gemini URL
365+
366+
// Gemini URL, or one with a Gemini proxy available
343367

344368
// Load page from cache if possible
345369
page, ok := cache.GetPage(u)
@@ -353,28 +377,33 @@ func handleURL(t *tab, u string, numRedirects int) (string, bool) {
353377
t.mode = tabModeLoading
354378
App.Draw()
355379

356-
res, err := client.Fetch(u)
380+
var res *gemini.Response
381+
if usingProxy {
382+
res, err = client.FetchWithProxy(proxyHostname, proxyPort, u)
383+
} else {
384+
res, err = client.Fetch(u)
385+
}
357386

358387
// Loading may have taken a while, make sure tab is still valid
359388
if !isValidTab(t) {
360389
return ret("", false)
361390
}
362391

363392
if errors.Is(err, client.ErrTofu) {
364-
if config.GemProxy == nil {
365-
if Tofu(parsed.Host, client.GetExpiry(parsed.Hostname(), parsed.Port())) {
393+
if usingProxy {
394+
// They are using a proxy
395+
if Tofu(proxy, client.GetExpiry(proxyHostname, proxyPort)) {
366396
// They want to continue anyway
367-
client.ResetTofuEntry(parsed.Hostname(), parsed.Port(), res.Cert)
397+
client.ResetTofuEntry(proxyHostname, proxyPort, res.Cert)
368398
// Response can be used further down, no need to reload
369399
} else {
370400
// They don't want to continue
371401
return ret("", false)
372402
}
373403
} else {
374-
// They are using a proxy
375-
if Tofu(config.GemProxy.Host, client.GetExpiry(config.GemProxy.Hostname(), config.GemProxy.Port())) {
404+
if Tofu(parsed.Host, client.GetExpiry(parsed.Hostname(), parsed.Port())) {
376405
// They want to continue anyway
377-
client.ResetTofuEntry(config.GemProxy.Hostname(), config.GemProxy.Port(), res.Cert)
406+
client.ResetTofuEntry(parsed.Hostname(), parsed.Port(), res.Cert)
378407
// Response can be used further down, no need to reload
379408
} else {
380409
// They don't want to continue

0 commit comments

Comments
 (0)