1
0
mirror of https://github.com/makew0rld/amfora.git synced 2024-06-19 19:25:24 +00:00

⬆️ go-gemini v0.9.3

Timeout when header takes too long, downloading uses proxies if appropriate
This commit is contained in:
makeworld 2020-11-23 21:09:48 -05:00
parent 8cc240bb4e
commit c53c36a4d0
7 changed files with 73 additions and 27 deletions

View File

@ -9,11 +9,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Opening local files with `file://` URIs (#103, #117) - Opening local files with `file://` URIs (#103, #117)
### Changed ### Changed
- Updated [go-gemini](https://github.com/makeworld-the-better-one/go-gemini) to v0.9.1 to support CN-only wildcard certs - Updated [go-gemini](https://github.com/makeworld-the-better-one/go-gemini) to v0.9.3
- Supports CN-only wildcard certs
- Time out when header takes too long
- Preformatted text is now light yellow by default - Preformatted text is now light yellow by default
### Fixed ### Fixed
- Single quotes are used in the default config for commands and paths so that Windows paths with backslashes will be parsed correctly - Single quotes are used in the default config for commands and paths so that Windows paths with backslashes will be parsed correctly
- Downloading now uses proxies when appropriate
## [1.6.0] - 2020-11-04 ## [1.6.0] - 2020-11-04

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/makeworld-the-better-one/amfora/client"
"github.com/makeworld-the-better-one/amfora/config" "github.com/makeworld-the-better-one/amfora/config"
"github.com/makeworld-the-better-one/amfora/display" "github.com/makeworld-the-better-one/amfora/display"
) )
@ -43,6 +44,8 @@ func main() {
os.Exit(1) os.Exit(1)
} }
client.Init()
display.Init() display.Init()
display.NewTab() display.NewTab()
display.NewTab() // Open extra tab and close it to fully initialize the app and wrapping display.NewTab() // Open extra tab and close it to fully initialize the app and wrapping

View File

@ -5,13 +5,29 @@ import (
"io/ioutil" "io/ioutil"
"net" "net"
"net/url" "net/url"
"time"
"github.com/makeworld-the-better-one/go-gemini" "github.com/makeworld-the-better-one/go-gemini"
"github.com/mitchellh/go-homedir" "github.com/mitchellh/go-homedir"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
var certCache = make(map[string][][]byte) var (
certCache = make(map[string][][]byte)
fetchClient *gemini.Client
dlClient *gemini.Client // For downloading
)
func Init() {
fetchClient = &gemini.Client{
ConnectTimeout: 10 * time.Second, // Default is 15
ReadTimeout: time.Duration(viper.GetInt("a-general.page_max_time")) * time.Second,
}
dlClient = &gemini.Client{
ConnectTimeout: 10 * time.Second, // Default is 15
// No read timeout, download can take as long as it needs
}
}
func clientCert(host string) ([]byte, []byte) { func clientCert(host string) ([]byte, []byte) {
if cert := certCache[host]; cert != nil { if cert := certCache[host]; cert != nil {
@ -53,18 +69,16 @@ func HasClientCert(host string) bool {
return cert != nil return cert != nil
} }
// Fetch returns response data and an error. func fetch(u string, c *gemini.Client) (*gemini.Response, error) {
// The error text is human friendly and should be displayed.
func Fetch(u string) (*gemini.Response, error) {
parsed, _ := url.Parse(u) parsed, _ := url.Parse(u)
cert, key := clientCert(parsed.Host) cert, key := clientCert(parsed.Host)
var res *gemini.Response var res *gemini.Response
var err error var err error
if cert != nil { if cert != nil {
res, err = gemini.FetchWithCert(u, cert, key) res, err = c.FetchWithCert(u, cert, key)
} else { } else {
res, err = gemini.Fetch(u) res, err = c.Fetch(u)
} }
if err != nil { if err != nil {
return nil, err return nil, err
@ -78,17 +92,27 @@ func Fetch(u string) (*gemini.Response, error) {
return res, err return res, err
} }
// FetchWithProxy is the same as Fetch, but uses a proxy. // Fetch returns response data and an error.
func FetchWithProxy(proxyHostname, proxyPort, u string) (*gemini.Response, error) { // The error text is human friendly and should be displayed.
func Fetch(u string) (*gemini.Response, error) {
return fetch(u, fetchClient)
}
// Download is the same as Fetch but with no read timeout.
func Download(u string) (*gemini.Response, error) {
return fetch(u, dlClient)
}
func fetchWithProxy(proxyHostname, proxyPort, u string, c *gemini.Client) (*gemini.Response, error) {
parsed, _ := url.Parse(u) parsed, _ := url.Parse(u)
cert, key := clientCert(parsed.Host) cert, key := clientCert(parsed.Host)
var res *gemini.Response var res *gemini.Response
var err error var err error
if cert != nil { if cert != nil {
res, err = gemini.FetchWithHostAndCert(net.JoinHostPort(proxyHostname, proxyPort), u, cert, key) res, err = c.FetchWithHostAndCert(net.JoinHostPort(proxyHostname, proxyPort), u, cert, key)
} else { } else {
res, err = gemini.FetchWithHost(net.JoinHostPort(proxyHostname, proxyPort), u) res, err = c.FetchWithHost(net.JoinHostPort(proxyHostname, proxyPort), u)
} }
if err != nil { if err != nil {
return nil, err return nil, err
@ -102,3 +126,13 @@ func FetchWithProxy(proxyHostname, proxyPort, u string) (*gemini.Response, error
return res, nil return res, nil
} }
// FetchWithProxy is the same as Fetch, but uses a proxy.
func FetchWithProxy(proxyHostname, proxyPort, u string) (*gemini.Response, error) {
return fetchWithProxy(proxyHostname, proxyPort, u, fetchClient)
}
// DownloadWithProxy is the same as FetchWithProxy but with no read timeout.
func DownloadWithProxy(proxyHostname, proxyPort, u string) (*gemini.Response, error) {
return fetchWithProxy(proxyHostname, proxyPort, u, dlClient)
}

View File

@ -452,24 +452,35 @@ func handleURL(t *tab, u string, numRedirects int) (string, bool) {
return ret("", false) return ret("", false)
} }
var res2 *gemini.Response
var dlErr error
if errors.Is(err, renderer.ErrTooLarge) { if errors.Is(err, renderer.ErrTooLarge) {
// Make new request for downloading purposes // Make new request for downloading purposes
res, clientErr := client.Fetch(u) if usingProxy {
if clientErr != nil && !errors.Is(clientErr, client.ErrTofu) { res2, dlErr = client.DownloadWithProxy(proxyHostname, proxyPort, u)
} else {
res2, dlErr = client.Download(u)
}
if dlErr != nil && !errors.Is(dlErr, client.ErrTofu) {
Error("URL Fetch Error", err.Error()) Error("URL Fetch Error", err.Error())
return ret("", false) return ret("", false)
} }
go dlChoice("That page is too large. What would you like to do?", u, res) go dlChoice("That page is too large. What would you like to do?", u, res2)
return ret("", false) return ret("", false)
} }
if errors.Is(err, renderer.ErrTimedOut) { if errors.Is(err, renderer.ErrTimedOut) {
// Make new request for downloading purposes // Make new request for downloading purposes
res, clientErr := client.Fetch(u) if usingProxy {
if clientErr != nil && !errors.Is(clientErr, client.ErrTofu) { res2, dlErr = client.DownloadWithProxy(proxyHostname, proxyPort, u)
} else {
res2, dlErr = client.Download(u)
}
if dlErr != nil && !errors.Is(dlErr, client.ErrTofu) {
Error("URL Fetch Error", err.Error()) Error("URL Fetch Error", err.Error())
return ret("", false) return ret("", false)
} }
go dlChoice("Loading that page timed out. What would you like to do?", u, res) go dlChoice("Loading that page timed out. What would you like to do?", u, res2)
return ret("", false) return ret("", false)
} }
if err != nil { if err != nil {

2
go.mod
View File

@ -7,7 +7,7 @@ require (
github.com/fsnotify/fsnotify v1.4.9 // indirect github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/gdamore/tcell v1.3.1-0.20200608133353-cb1e5d6fa606 github.com/gdamore/tcell v1.3.1-0.20200608133353-cb1e5d6fa606
github.com/google/go-cmp v0.5.0 // indirect github.com/google/go-cmp v0.5.0 // indirect
github.com/makeworld-the-better-one/go-gemini v0.9.1 github.com/makeworld-the-better-one/go-gemini v0.9.3
github.com/makeworld-the-better-one/go-isemoji v1.1.0 github.com/makeworld-the-better-one/go-isemoji v1.1.0
github.com/makeworld-the-better-one/progressbar/v3 v3.3.5-0.20200710151429-125743e22b4f github.com/makeworld-the-better-one/progressbar/v3 v3.3.5-0.20200710151429-125743e22b4f
github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-homedir v1.1.0

4
go.sum
View File

@ -125,8 +125,8 @@ github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tW
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/makeworld-the-better-one/go-gemini v0.9.1 h1:/Vc6Y4Y1aOi4lZIBA1wDe+4N2xAI8EQ0CIjip2NUQkk= github.com/makeworld-the-better-one/go-gemini v0.9.3 h1:vpJc1u4LYpEI5h7GcOE2zSfOmpE9gQzt0vEayp/ilWc=
github.com/makeworld-the-better-one/go-gemini v0.9.1/go.mod h1:P7/FbZ+IEIbA/d+A0Y3w2GNgD8SA2AcNv7aDGJbaWG4= github.com/makeworld-the-better-one/go-gemini v0.9.3/go.mod h1:P7/FbZ+IEIbA/d+A0Y3w2GNgD8SA2AcNv7aDGJbaWG4=
github.com/makeworld-the-better-one/go-isemoji v1.1.0 h1:wZBHOKB5zAIgaU2vaWnXFDDhatebB8TySrNVxjVV84g= github.com/makeworld-the-better-one/go-isemoji v1.1.0 h1:wZBHOKB5zAIgaU2vaWnXFDDhatebB8TySrNVxjVV84g=
github.com/makeworld-the-better-one/go-isemoji v1.1.0/go.mod h1:FBjkPl9rr0G4vlZCc+Mr+QcnOfGCTbGWYW8/1sp06I0= github.com/makeworld-the-better-one/go-isemoji v1.1.0/go.mod h1:FBjkPl9rr0G4vlZCc+Mr+QcnOfGCTbGWYW8/1sp06I0=
github.com/makeworld-the-better-one/progressbar/v3 v3.3.5-0.20200710151429-125743e22b4f h1:YEUlTs5gb35UlBLTgqrub9axWTYB3d7/8TxrkJDZpRI= github.com/makeworld-the-better-one/progressbar/v3 v3.3.5-0.20200710151429-125743e22b4f h1:YEUlTs5gb35UlBLTgqrub9axWTYB3d7/8TxrkJDZpRI=

View File

@ -5,8 +5,8 @@ import (
"errors" "errors"
"io" "io"
"mime" "mime"
"os"
"strings" "strings"
"time"
"github.com/makeworld-the-better-one/amfora/structs" "github.com/makeworld-the-better-one/amfora/structs"
"github.com/makeworld-the-better-one/go-gemini" "github.com/makeworld-the-better-one/go-gemini"
@ -63,18 +63,13 @@ func MakePage(url string, res *gemini.Response, width, leftMargin int, proxied b
} }
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
go func() {
time.Sleep(time.Duration(viper.GetInt("a-general.page_max_time")) * time.Second)
res.Body.Close()
}()
_, err := io.CopyN(buf, res.Body, viper.GetInt64("a-general.page_max_size")+1) _, err := io.CopyN(buf, res.Body, viper.GetInt64("a-general.page_max_size")+1)
res.Body.Close() res.Body.Close()
if err == nil { if err == nil {
// Content was larger than max size // Content was larger than max size
return nil, ErrTooLarge return nil, ErrTooLarge
} else if err != io.EOF { } else if err != io.EOF {
if strings.HasSuffix(err.Error(), "use of closed network connection") { if errors.Is(err, os.ErrDeadlineExceeded) {
// Timed out // Timed out
return nil, ErrTimedOut return nil, ErrTimedOut
} }