Store permanent redirects

This commit is contained in:
blank X 2021-08-10 15:26:26 +07:00
parent a94dd6fb44
commit 34fffa9d37
Signed by: blankie
GPG Key ID: CC15FC822C7F61F5
1 changed files with 96 additions and 0 deletions

96
main.go
View File

@ -6,6 +6,7 @@ import (
"log" "log"
"sort" "sort"
"time" "time"
"bufio"
"errors" "errors"
"context" "context"
"strings" "strings"
@ -21,6 +22,7 @@ import (
var ( var (
hosts tofu.KnownHosts hosts tofu.KnownHosts
hostsfile *tofu.HostWriter hostsfile *tofu.HostWriter
predirs map[string]*url.URL
) )
func xdgDataHome() string { func xdgDataHome() string {
@ -41,6 +43,75 @@ func init() {
if err != nil { if err != nil {
log.Fatal(err) 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 { 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) { 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) resp, err := client.Do(ctx, req)
if err != nil { if err != nil {
return resp, req, err 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 { if resp.Status.Class() == gemini.StatusRedirect {
via = append(via, req) via = append(via, req)
if len(via) > 5 { if len(via) > 5 {