flounder

A simple gemini site builder
Log | Files | Refs | README | LICENSE

commit 832bd12921a131206263bf1374e07b5164b1c143
parent d532133620d1957ecf44ffc3fcf274ae137d33c2
Author: alex wennerberg <alex@alexwennerberg.com>
Date:   Sun, 31 Oct 2021 00:19:34 -0700

Upgrade go-gemini

Diffstat:
Mgemini.go | 56+++++++++++++++++++++++---------------------------------
Mgo.mod | 2+-
Mgo.sum | 7++-----
Mlog.go | 43++++---------------------------------------
Mproxy.go | 17+++++++++++++----
5 files changed, 43 insertions(+), 82 deletions(-)

diff --git a/gemini.go b/gemini.go @@ -2,10 +2,7 @@ package main import ( "bytes" - "crypto/tls" - "crypto/x509/pkix" - gmi "git.sr.ht/~adnano/go-gemini" - "git.sr.ht/~adnano/go-gemini/certificate" + "context" "io" "io/ioutil" "log" @@ -15,6 +12,9 @@ import ( "strings" "text/template" "time" + + gmi "git.sr.ht/~adnano/go-gemini" + "git.sr.ht/~adnano/go-gemini/certificate" ) var gt *template.Template @@ -54,7 +54,6 @@ func generateFolderPage(fullpath string) string { } func gmiIndex(w gmi.ResponseWriter, r *gmi.Request) { - logGemini(r) // TODO move into wrapper t, err := template.ParseFiles("templates/index.gmi") if err != nil { log.Fatal(err) @@ -63,7 +62,7 @@ func gmiIndex(w gmi.ResponseWriter, r *gmi.Request) { users, err := getActiveUserNames() if err != nil { log.Println(err) - w.Status(gmi.StatusTemporaryFailure) + w.WriteHeader(gmi.StatusTemporaryFailure, "Server Error") } data := struct { Host string @@ -79,8 +78,13 @@ func gmiIndex(w gmi.ResponseWriter, r *gmi.Request) { t.Execute(w, data) } -func gmiPage(w gmi.ResponseWriter, r *gmi.Request) { - logGemini(r) // TODO move into wrapper +func gmiPage(_ context.Context, w gmi.ResponseWriter, r *gmi.Request) { + // redundant + hostname := strings.SplitN(c.Host, ":", 2)[0] + if strings.HasPrefix(r.Host, hostname) { + gmiIndex(w, r) + return + } var userName string custom := domains[r.URL.Host] if custom != "" { @@ -92,21 +96,21 @@ func gmiPage(w gmi.ResponseWriter, r *gmi.Request) { if fileName == "/" { fileName = "index.gmi" } else if strings.HasPrefix(fileName, "/"+HiddenFolder) { - w.Status(gmi.StatusNotFound) + w.WriteHeader(gmi.StatusNotFound, "Not found") return } fullPath := path.Join(c.FilesDirectory, userName, fileName) if fileName == "/gemlog" { // temp hack _, err := os.Stat(path.Join(fullPath, "index.gmi")) if err != nil { - w.Meta("text/gemini") + w.WriteHeader(gmi.StatusSuccess, "text/gemini") io.Copy(w, strings.NewReader(generateGemfeedPage(userName))) return } } else if fileName == "/gemlog/atom.xml" { _, err := os.Stat(fullPath) if err != nil { - w.Meta("application/atom+xml") + w.WriteHeader(gmi.StatusSuccess, "application/atom+xml") feed := generateFeedFromUser(userName) atomString := feed.toAtomFeed() io.Copy(w, strings.NewReader(atomString)) @@ -114,7 +118,7 @@ func gmiPage(w gmi.ResponseWriter, r *gmi.Request) { } } - gmi.ServeFile(w, gmi.Dir(path.Join(c.FilesDirectory, userName)), fileName) + gmi.ServeFile(w, os.DirFS(path.Join(c.FilesDirectory, userName)), fileName) } func runGeminiServer() { @@ -130,30 +134,16 @@ func runGeminiServer() { hostname := strings.SplitN(c.Host, ":", 2)[0] // is this necc? - err = server.Certificates.Load(c.GeminiCertStore) - if err != nil { - } - server.GetCertificate = func(h string) (tls.Certificate, error) { - log.Println("Generating certificate for", h) - return certificate.Create(certificate.CreateOptions{ - Subject: pkix.Name{ - CommonName: h, - }, - DNSNames: []string{h}, - Duration: time.Hour * 8760 * 100, // 100 years - }) - } + certificates := &certificate.Store{} + certificates.Register("*." + hostname) + server.GetCertificate = certificates.Get - var mux gmi.ServeMux - // replace with wildcard cert - mux.HandleFunc("/", gmiIndex) + var mux gmi.Mux - var wildcardMux gmi.ServeMux - wildcardMux.HandleFunc("/", gmiPage) - server.Handle(hostname, &mux) - server.Handle("*", &wildcardMux) + mux.HandleFunc("/", gmiPage) + server.Handler = gmi.LoggingMiddleware(&mux) - err = server.ListenAndServe() + err = server.ListenAndServe(context.Background()) if err != nil { log.Fatal(err) } diff --git a/go.mod b/go.mod @@ -3,7 +3,7 @@ module github.com/alexwennerberg/flounder go 1.15 require ( - git.sr.ht/~adnano/go-gemini v0.1.14-0.20210214021019-595b0d049034 + git.sr.ht/~adnano/go-gemini v0.2.2 git.sr.ht/~aw/gorilla-feeds v1.1.3 github.com/BurntSushi/toml v0.3.1 github.com/gorilla/handlers v1.5.1 diff --git a/go.sum b/go.sum @@ -1,5 +1,5 @@ -git.sr.ht/~adnano/go-gemini v0.1.14-0.20210214021019-595b0d049034 h1:duv1TxH0cWtX8IVffgOKIjO0qaRAaDce2MlTCoqk6V4= -git.sr.ht/~adnano/go-gemini v0.1.14-0.20210214021019-595b0d049034/go.mod h1:hQ75Y0i5jSFL+FQ7AzWVAYr5LQsaFC7v3ZviNyj46dY= +git.sr.ht/~adnano/go-gemini v0.2.2 h1:p2owKzrQ1wTgvPS5CZCPYArQyNUL8ZgYOHHrTjH9sdI= +git.sr.ht/~adnano/go-gemini v0.2.2/go.mod h1:hQ75Y0i5jSFL+FQ7AzWVAYr5LQsaFC7v3ZviNyj46dY= git.sr.ht/~aw/gorilla-feeds v1.1.3 h1:cotKXVrfTVGWFxkd6pvPgLJRtzzXyDUBQJkHK3PEUmI= git.sr.ht/~aw/gorilla-feeds v1.1.3/go.mod h1:VLpbtNDEWoaJKU41Crj6r3ChvlqYvBm56c0O6IM457g= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= @@ -38,7 +38,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -48,12 +47,10 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/log.go b/log.go @@ -4,8 +4,6 @@ import ( "bufio" "database/sql" "fmt" - gmi "git.sr.ht/~adnano/go-gemini" - "github.com/gorilla/handlers" "io" "log" "net" @@ -17,6 +15,8 @@ import ( "strings" "time" "unicode/utf8" + + "github.com/gorilla/handlers" ) // Copy pasted from gorilla handler library, modified slightly @@ -154,29 +154,6 @@ func appendQuoted(buf []byte, s string) []byte { return buf } -// Parse logs and write to database - -// Anonymize user and IP? - -func logGemini(r *gmi.Request) { - var ipAddr string - if r.RemoteAddr != nil { - ipAddr = r.RemoteAddr.String() - } else { - ipAddr = "" - } - host, _, err := net.SplitHostPort(ipAddr) - if err != nil { - host = ipAddr - } - line := fmt.Sprintf("gemini %s - [%s] %s %s\n", host, - time.Now().Format(apacheTS), - r.URL.Host, - r.URL.Path) - buf := []byte(line) - log.Writer().Write(buf) -} - // notall fields set for both protocols type LogLine struct { Timestamp time.Time @@ -198,28 +175,16 @@ values (?, ?, ?, ?, ?, ?, ?, ?, ?)`, ll.Timestamp.Format(time.RFC3339), ll.Proto } } +// TODO remove this junk, just use prometheus const httpLogRegex = `^(.*?) - (.*?) \[(.*?)\] (.*?) \"(.*) (.*) .*\" - (.*) - (\d*)` -const geminiLogRegex = `^gemini (.*?) - \[(.*?)\] (.*?) (.*)` var rxHttp *regexp.Regexp = regexp.MustCompile(httpLogRegex) -var rxGemini *regexp.Regexp = regexp.MustCompile(geminiLogRegex) func lineToLogLine(line string) (*LogLine, error) { result := LogLine{} var ts string if strings.HasPrefix(line, "gemini") { - matches := rxGemini.FindStringSubmatch(line) - if len(matches) < 5 { - return nil, nil // TODO better error - } else { - result.ReqIP = matches[1] - ts = matches[2] - result.Timestamp, _ = time.Parse(apacheTS, ts) - result.DestHost = matches[3] - result.Path = matches[4] - result.Protocol = "gemini" - // etc - } + // nul } else { matches := rxHttp.FindStringSubmatch(line) if len(matches) < 8 { diff --git a/proxy.go b/proxy.go @@ -2,6 +2,7 @@ package main import ( + "context" "fmt" "html/template" "io" @@ -41,15 +42,23 @@ func proxyGemini(w http.ResponseWriter, r *http.Request) { req.URL, err = url.Parse(fmt.Sprintf("gemini://%s/", spath[1])) } req.URL.RawQuery = r.URL.RawQuery - client := gemini.Client{ - Timeout: 60 * time.Second, - } + client := gemini.Client{} if h := (url.URL{Host: req.Host}); h.Port() == "" { req.Host += ":1965" } - resp, err := client.Do(&req) + d := time.Now().Add(1 * time.Minute) + ctx, cancel := context.WithDeadline(context.Background(), d) + defer cancel() + select { + case <-time.After(1 * time.Minute): + fmt.Println("overslept") + case <-ctx.Done(): + fmt.Println(ctx.Err()) + } + + resp, err := client.Do(ctx, &req) if err != nil { w.WriteHeader(http.StatusBadGateway) fmt.Fprintf(w, "Gateway error: %v", err)