Store permanent errors
This commit is contained in:
parent
34fffa9d37
commit
280703edd8
99
main.go
99
main.go
|
@ -9,6 +9,7 @@ import (
|
|||
"bufio"
|
||||
"errors"
|
||||
"context"
|
||||
"strconv"
|
||||
"strings"
|
||||
"net/url"
|
||||
"crypto/x509"
|
||||
|
@ -23,6 +24,7 @@ var (
|
|||
hosts tofu.KnownHosts
|
||||
hostsfile *tofu.HostWriter
|
||||
predirs map[string]*url.URL
|
||||
perrors map[string]PError
|
||||
)
|
||||
|
||||
func xdgDataHome() string {
|
||||
|
@ -48,6 +50,11 @@ func init() {
|
|||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = populatePErrors()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func populatePRedirs() error {
|
||||
|
@ -114,6 +121,80 @@ func savePRedirs() error {
|
|||
return writer.Flush()
|
||||
}
|
||||
|
||||
func populatePErrors() error {
|
||||
file, err := os.OpenFile(filepath.Join(xdgDataHome(), "konbata", "perrors"), os.O_RDONLY|os.O_CREATE, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
scanner := bufio.NewScanner(file)
|
||||
perrors = make(map[string]PError)
|
||||
unescaper := strings.NewReplacer("\\n", "\n", "\\\\", "\\")
|
||||
for scanner.Scan() {
|
||||
values := strings.SplitN(scanner.Text(), " ", 3)
|
||||
if len(values) != 3 {
|
||||
continue
|
||||
}
|
||||
url, err := url.Parse(values[0])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if url.Scheme != "gemini" {
|
||||
continue
|
||||
}
|
||||
code, err := strconv.Atoi(values[1])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
perrors[url.String()] = PError{
|
||||
code: gemini.Status(code),
|
||||
message: unescaper.Replace(values[2]),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func savePErrors() error {
|
||||
file, err := os.OpenFile(filepath.Join(xdgDataHome(), "konbata", "perrors"), 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)
|
||||
escaper := strings.NewReplacer("\\", "\\\\", "\n", "\\n")
|
||||
for url, perror := range perrors {
|
||||
_, err = writer.WriteString(url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = writer.WriteRune(' ')
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = writer.WriteString(strconv.Itoa(int(perror.code)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = writer.WriteRune(' ')
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = escaper.WriteString(writer, perror.message)
|
||||
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 {
|
||||
host := tofu.NewHost(hostname, cert.Raw)
|
||||
knownHost, ok := hosts.Lookup(hostname)
|
||||
|
@ -141,6 +222,9 @@ func do(client gemini.Client, ctx context.Context, req *gemini.Request, via []*g
|
|||
redirect.URL = target
|
||||
return do(client, ctx, &redirect, via)
|
||||
}
|
||||
if perror, exists := perrors[req.URL.String()]; exists {
|
||||
return nil, req, errors.New(fmt.Sprintf("%d %s", perror.code, perror.message))
|
||||
}
|
||||
resp, err := client.Do(ctx, req)
|
||||
if err != nil {
|
||||
return resp, req, err
|
||||
|
@ -161,6 +245,16 @@ func do(client gemini.Client, ctx context.Context, req *gemini.Request, via []*g
|
|||
return resp, req, err
|
||||
}
|
||||
}
|
||||
if resp.Status.Class() == gemini.StatusPermanentFailure {
|
||||
perrors[req.URL.String()] = PError{
|
||||
code: resp.Status,
|
||||
message: resp.Meta,
|
||||
}
|
||||
err = savePErrors()
|
||||
if err != nil {
|
||||
return resp, req, err
|
||||
}
|
||||
}
|
||||
if resp.Status.Class() == gemini.StatusRedirect {
|
||||
via = append(via, req)
|
||||
if len(via) > 5 {
|
||||
|
@ -304,6 +398,11 @@ func (a ByTime) Swap(i, j int) {
|
|||
a[i], a[j] = a[j], a[i]
|
||||
}
|
||||
|
||||
type PError struct {
|
||||
code gemini.Status
|
||||
message string
|
||||
}
|
||||
|
||||
type AtomWriter struct {
|
||||
Title string
|
||||
Items []FeedItem
|
||||
|
|
Loading…
Reference in New Issue