teafolio/router.go

111 lines
3.1 KiB
Go

package main
import (
"embed"
"encoding/base64"
"fmt"
"net/http"
"net/url"
"strings"
)
//go:embed static/*
var StaticFiles embed.FS
func (this *Application) ServeStatic(w http.ResponseWriter, r *http.Request) {
http.FileServer(http.FS(StaticFiles)).ServeHTTP(w, r)
// http.StripPrefix(`/static/`, http.FileServer(http.FS(StaticFiles))).ServeHTTP(w, r)
}
func (this *Application) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.Method == `GET` {
if r.URL.Path == `/` {
this.Homepage(w, r)
} else if r.URL.Path == `/favicon.ico` {
w.Header().Set(`Location`, `/static/logo.png`)
w.WriteHeader(301)
} else if r.URL.Path == `/robots.txt` {
http.Error(w, "not found", 404)
} else if parts := this.rxRepoImage.FindStringSubmatch(r.URL.Path); parts != nil {
this.Bannerpage(w, r, parts[1])
} else if parts := this.rxRepoPage.FindStringSubmatch(r.URL.Path); parts != nil {
// Support /repo.html URIs for backward compatibility
if strings.HasSuffix(parts[1], `.html`) {
w.Header().Set(`Location`, r.URL.Path[0:len(r.URL.Path)-5])
w.WriteHeader(301)
return
}
// The regexp supports an optional trailing slash
// Redirect to canonical no-trailing-slash
if strings.HasSuffix(r.URL.Path, `/`) {
w.Header().Set(`Location`, `/`+parts[1]) // n.b. parts[1] isn't urldecoded yet
w.WriteHeader(301)
return
}
// Proper decoding of special characters in repo path component
repoName, err := url.PathUnescape(parts[1])
if err != nil {
http.Error(w, "malformed url encoding in repository name", 400)
return
}
// Maybe it's a redirected project (alternative name)
if rename, ok := this.cfg.Redirect[repoName]; ok {
w.Header().Set(`Location`, `/`+url.PathEscape(rename))
w.WriteHeader(301)
return
}
this.Repopage(w, r, repoName)
} else if strings.HasPrefix(r.URL.Path, `/static/`) {
if r.URL.Path == `/static/logo.png` && this.cfg.Template.CustomLogoPngBase64 != "" {
logoPng, err := base64.StdEncoding.DecodeString(this.cfg.Template.CustomLogoPngBase64)
if err != nil {
this.internalError(w, r, fmt.Errorf("parsing base64 logo: %w", err))
return
}
w.Header().Set(`Content-Length`, fmt.Sprintf("%d", len(logoPng)))
w.Header().Set(`Content-Type`, `image/png`)
w.WriteHeader(200)
w.Write(logoPng)
return
}
// Embedded resource
// r.URL.Path = r.URL.Path[8:]
this.ServeStatic(w, r)
} else if r.URL.Query().Get("go-get") == "1" {
// This wasn't one of our standard `/repo` paths, but there is the ?go-get=1 parameter
// It must be a subpackage request
// We can't serve the proper go-import meta tag immediately because
// we haven't looked up the go.mod yet. Just redirect to the root
// package - `go get` will follow redirects and the resulting meta tag is correct
slashParts := strings.SplitN(r.URL.Path, `/`, 3) // len === 3 is guaranteed from earlier if cases
w.Header().Set(`Location`, `/`+slashParts[1])
w.WriteHeader(301)
return
} else {
http.Error(w, "not found", 404)
}
} else {
http.Error(w, "invalid method", 400)
}
}