// LogHeader logs a header func LogHeader(log termlog.Logger, h http.Header) { max := 0 for k := range h { if len(k) > max { max = len(k) } } for k, vals := range h { for _, v := range vals { pad := fmt.Sprintf(fmt.Sprintf("%%%ds", max-len(k)+1), " ") log.SayAs( "headers", "\t%s%s%s", color.BlueString(k)+":", pad, v, ) } } }
// name is '/'-separated, not filepath.Separator. func (fserver *FileServer) serveFile( logger termlog.Logger, w http.ResponseWriter, r *http.Request, name string, redirect bool, ) { const indexPage = "/index.html" // redirect .../index.html to .../ // can't use Redirect() because that would make the path absolute, // which would be a problem running under StripPrefix if strings.HasSuffix(r.URL.Path, indexPage) { logger.SayAs( "debug", "debug fileserver: redirecting %s -> ./", indexPage, ) localRedirect(w, r, "./") return } f, err := fserver.Root.Open(name) if err != nil { logger.WarnAs("debug", "debug fileserver: %s", err) if err := fserver.notFound(logger, w, r, name, nil); err != nil { logger.Shout("Internal error: %s", err) } return } defer func() { _ = f.Close() }() d, err1 := f.Stat() if err1 != nil { logger.WarnAs("debug", "debug fileserver: %s", err) if err := fserver.notFound(logger, w, r, name, nil); err != nil { logger.Shout("Internal error: %s", err) } return } if redirect { // redirect to canonical path: / at end of directory url url := r.URL.Path if !strings.HasPrefix(url, "/") { url = "/" + url } if d.IsDir() { if url[len(url)-1] != '/' { localRedirect(w, r, path.Base(url)+"/") return } } else if url[len(url)-1] == '/' { localRedirect(w, r, "../"+path.Base(url)) return } } // use contents of index.html for directory, if present if d.IsDir() { index := name + indexPage ff, err := fserver.Root.Open(index) if err == nil { defer func() { _ = ff.Close() }() dd, err := ff.Stat() if err == nil { name = index d = dd f = ff } } } // Still a directory? (we didn't find an index.html file) if d.IsDir() { if err := fserver.notFound(logger, w, r, name, &f); err != nil { logger.Shout("Internal error: %s", err) } return } // serverContent will check modification time sizeFunc := func() (int64, error) { return d.Size(), nil } err = serveContent(fserver.Inject, w, r, d.Name(), d.ModTime(), sizeFunc, f) if err != nil { logger.Warn("Error serving file: %s", err) } }