Store permanent redirects
This commit is contained in:
parent
a94dd6fb44
commit
34fffa9d37
96
main.go
96
main.go
|
@ -6,6 +6,7 @@ import (
|
|||
"log"
|
||||
"sort"
|
||||
"time"
|
||||
"bufio"
|
||||
"errors"
|
||||
"context"
|
||||
"strings"
|
||||
|
@ -21,6 +22,7 @@ import (
|
|||
var (
|
||||
hosts tofu.KnownHosts
|
||||
hostsfile *tofu.HostWriter
|
||||
predirs map[string]*url.URL
|
||||
)
|
||||
|
||||
func xdgDataHome() string {
|
||||
|
@ -41,6 +43,75 @@ func init() {
|
|||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = populatePRedirs()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func populatePRedirs() error {
|
||||
file, err := os.OpenFile(filepath.Join(xdgDataHome(), "konbata", "predirs"), os.O_RDONLY|os.O_CREATE, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
scanner := bufio.NewScanner(file)
|
||||
predirs = make(map[string]*url.URL)
|
||||
for scanner.Scan() {
|
||||
urls := strings.Split(scanner.Text(), " ")
|
||||
if len(urls) != 2 {
|
||||
continue
|
||||
}
|
||||
url0, err := url.Parse(urls[0])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if url0.Scheme != "gemini" {
|
||||
continue
|
||||
}
|
||||
url1, err := url.Parse(urls[1])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if url1.Scheme != "gemini" {
|
||||
continue
|
||||
}
|
||||
predirs[url0.String()] = url1
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func savePRedirs() error {
|
||||
file, err := os.OpenFile(filepath.Join(xdgDataHome(), "konbata", "predirs"), os.O_WRONLY|os.O_CREATE, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
err = file.Truncate(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
writer := bufio.NewWriter(file)
|
||||
for url0, url1 := range predirs {
|
||||
_, err = writer.WriteString(url0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = writer.WriteRune(' ')
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = writer.WriteString(url1.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = writer.WriteRune('\n')
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return writer.Flush()
|
||||
}
|
||||
|
||||
func trustCertificate(hostname string, cert *x509.Certificate) error {
|
||||
|
@ -60,11 +131,36 @@ func trustCertificate(hostname string, cert *x509.Certificate) error {
|
|||
}
|
||||
|
||||
func do(client gemini.Client, ctx context.Context, req *gemini.Request, via []*gemini.Request) (*gemini.Response, *gemini.Request, error) {
|
||||
if target, exists := predirs[req.URL.String()]; exists {
|
||||
via = append(via, req)
|
||||
if len(via) > 5 {
|
||||
return nil, req, errors.New("too many redirects")
|
||||
}
|
||||
|
||||
redirect := *req
|
||||
redirect.URL = target
|
||||
return do(client, ctx, &redirect, via)
|
||||
}
|
||||
resp, err := client.Do(ctx, req)
|
||||
if err != nil {
|
||||
return resp, req, err
|
||||
}
|
||||
|
||||
if resp.Status == gemini.StatusPermanentRedirect {
|
||||
target, err := url.Parse(resp.Meta)
|
||||
if err != nil {
|
||||
return resp, req, err
|
||||
}
|
||||
if target.Scheme != "gemini" && target.Scheme != "" {
|
||||
return resp, req, errors.New(fmt.Sprintf("tried to redirect to scheme %s", target.Scheme))
|
||||
}
|
||||
target = req.URL.ResolveReference(target)
|
||||
predirs[req.URL.String()] = target
|
||||
err = savePRedirs()
|
||||
if err != nil {
|
||||
return resp, req, err
|
||||
}
|
||||
}
|
||||
if resp.Status.Class() == gemini.StatusRedirect {
|
||||
via = append(via, req)
|
||||
if len(via) > 5 {
|
||||
|
|
Loading…
Reference in New Issue