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) } }