From 28b2235ddb92aaf22429a33eab604fa8ee1e1c44 Mon Sep 17 00:00:00 2001 From: makeworld Date: Sat, 25 Jul 2020 20:26:40 -0400 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Permanent=20redirects=20are=20cache?= =?UTF-8?q?d=20-=20fixes=20#22?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 ++ README.md | 2 +- cache/cache.go | 3 ++- cache/redir.go | 60 ++++++++++++++++++++++++++++++++++++++++++++++ display/private.go | 4 ++++ go.mod | 4 ++-- go.sum | 8 +++---- 7 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 cache/redir.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 169d1d4..51806e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Tab now also enters link selecting mode, like Enter (#48) - Number keys can be pressed to navigate to links 1 through 10 (#47) +- Permanent redirects are cached for the session (#22) ### Fixed - You can't change link selection while the page is loading @@ -27,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Pages are rewrapped dynamically, whenever the terminal size changes (#33) - TOFU warning message mentions how long the previous cert was still valid for (#34) +- Update [cview](https://gitlab.com/tslocum/cview/) to latest commit ### Fixed - Many potential network and display race conditions eliminated diff --git a/README.md b/README.md index 2da8fae..d9ce81e 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Amfora aims to be the best looking [Gemini](https://gemini.circumlunar.space/) client with the most features... all in the terminal. It does not support Gopher or other non-Web protocols - check out [Bombadillo](http://bombadillo.colorfield.space/) for that. -It also aims to be completely cross platform, with full Windows support. If you're on Windows, I would not recommend using the default terminal software. Maybe use [Cmder](https://cmder.net/) instead. Note that some of the application colors will not display correctly on most Windows terminals, but all functionality will still work. +It also aims to be completely cross platform, with full Windows support. If you're on Windows, I would not recommend using the default terminal software. Maybe use Powershell (comes with Windows) or [Cmder](https://cmder.net/) instead. Note that some of the application colors will not display correctly on most Windows terminals, but all functionality will still work. It fully passes Sean Conman's client torture test, including the new Unicode tests. It mostly passes the Egsam test. diff --git a/cache/cache.go b/cache/cache.go index 833b95a..3f6dbff 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -1,5 +1,6 @@ -// Package cache provides an interface for a cache of strings, aka text/gemini pages. +// Package cache provides an interface for a cache of strings, aka text/gemini pages, and redirects. // It is fully thread safe. +// The redirect cache is not limited. package cache import ( diff --git a/cache/redir.go b/cache/redir.go new file mode 100644 index 0000000..4e56fcc --- /dev/null +++ b/cache/redir.go @@ -0,0 +1,60 @@ +package cache + +import ( + "sync" +) + +// Functions for caching redirects. + +var redirUrls = make(map[string]string) // map original URL to redirect +var redirMut = sync.RWMutex{} + +// AddRedir adds a original-to-redirect pair to the cache. +func AddRedir(og, redir string) { + redirMut.Lock() + defer redirMut.Unlock() + + for k, v := range redirUrls { + if og == v { + // The original URL param is the redirect URL for `k`. + // This means there is a chain: k -> og -> redir + // The chain should be removed + redirUrls[k] = redir + } + if redir == k { + // There's a loop + // The newer version is preferred + delete(redirUrls, k) + } + } + redirUrls[og] = redir +} + +// ClearRedirs removes all redirects from the cache. +func ClearRedirs() { + redirMut.Lock() + defer redirMut.Unlock() + redirUrls = make(map[string]string) +} + +// Redirect takes the provided URL and returns a redirected version, if a redirect +// exists for that URL in the cache. +// If one does not then the original URL is returned. +func Redirect(u string) string { + redirMut.RLock() + defer redirMut.RUnlock() + + // A single lookup is enough, because AddRedir + // removes loops and chains. + redir, ok := redirUrls[u] + if ok { + return redir + } + return u +} + +func NumRedirs() int { + redirMut.RLock() + defer redirMut.RUnlock() + return len(redirUrls) +} diff --git a/display/private.go b/display/private.go index 11c5138..07d2837 100644 --- a/display/private.go +++ b/display/private.go @@ -198,6 +198,7 @@ func handleURL(t *tab, u string) (string, bool) { } u = normalizeURL(u) + u = cache.Redirect(u) parsed, err := url.Parse(u) if err != nil { @@ -306,6 +307,9 @@ func handleURL(t *tab, u string) (string, bool) { } redir := parsed.ResolveReference(parsedMeta).String() if YesNo("Follow redirect?\n" + redir) { + if res.Status == gemini.StatusRedirectPermanent { + go cache.AddRedir(u, redir) + } return handleURL(t, redir) } return ret("", false) diff --git a/go.mod b/go.mod index 5948e96..51e7de0 100644 --- a/go.mod +++ b/go.mod @@ -17,8 +17,8 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.7.0 github.com/stretchr/testify v1.6.0 - gitlab.com/tslocum/cview v1.4.8-0.20200614211415-f477be8ba472 - golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 // indirect + gitlab.com/tslocum/cview v1.4.8-0.20200713214710-cc7796c4ca44 + golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c // indirect golang.org/x/text v0.3.3 gopkg.in/ini.v1 v1.57.0 // indirect gopkg.in/yaml.v3 v3.0.0-20200603094226-e3079894b1e8 // indirect diff --git a/go.sum b/go.sum index 05e91b1..c3f7d70 100644 --- a/go.sum +++ b/go.sum @@ -211,8 +211,8 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= gitlab.com/tslocum/cbind v0.1.1 h1:JXXtxMWHgWLvoF+QkrvcNvOQ59juy7OE1RhT7hZfdt0= gitlab.com/tslocum/cbind v0.1.1/go.mod h1:rX7vkl0pUSg/yy427MmD1FZAf99S7WwpUlxF/qTpPqk= -gitlab.com/tslocum/cview v1.4.8-0.20200614211415-f477be8ba472 h1:lvLn/TWWgqG1gJAd1a8DOSPgkrQEWaMg+AQhM5/PdzY= -gitlab.com/tslocum/cview v1.4.8-0.20200614211415-f477be8ba472/go.mod h1:QctoEJaR2AqZTy0KKo12P1ZjHgQJyVkAXaeDanBBhlE= +gitlab.com/tslocum/cview v1.4.8-0.20200713214710-cc7796c4ca44 h1:YddMqXJ6jI3SkP8Nfxc+S2pcvI5o8mmXmHL2D9hkwQI= +gitlab.com/tslocum/cview v1.4.8-0.20200713214710-cc7796c4ca44/go.mod h1:QctoEJaR2AqZTy0KKo12P1ZjHgQJyVkAXaeDanBBhlE= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -282,8 +282,8 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200610111108-226ff32320da h1:bGb80FudwxpeucJUjPYJXuJ8Hk91vNtfvrymzwiei38= golang.org/x/sys v0.0.0-20200610111108-226ff32320da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c h1:UIcGWL6/wpCfyGuJnRFJRurA+yj8RrW7Q6x2YMCXt6c= +golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=