Repository: caddyserver/caddy
File: modules/caddyhttp/fileserver/staticfiles.go (Go)

Code before:
func (fsrv *FileServer) notFound(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
	if fsrv.PassThru {
		return next.ServeHTTP(w, r)
	}
	return caddyhttp.Error(http.StatusNotFound, nil)
}

// calculateEtag produces a strong etag by default, although, for
// efficiency reasons, it does not actually consume the contents
// of the file to make a hash of all the bytes. ¯\_(ツ)_/¯
// Prefix the etag with "W/" to convert it into a weak etag.
// See: https://tools.ietf.org/html/rfc7232#section-2.3
func calculateEtag(d os.FileInfo) string {
	mtime := d.ModTime().Unix()
	if mtime == 0 || mtime == 1 {
		return "" // not useful anyway; see issue #5548
	}
	t := strconv.FormatInt(mtime, 36)
	s := strconv.FormatInt(d.Size(), 36)
	return `"` + t + s + `"`
}

// Finds the first corresponding etag file for a given file in the file system and return its content
func getEtagFromFile(fileSystem fs.FS, etagSuffixes []string, filename string) (string, error) {
	for _, suffix := range etagSuffixes {
		etagFilename := filename + "." + suffix
		_, err := fs.Stat(fileSystem, etagFilename)
		if err != nil {
			continue
		}
		etag, err := fs.ReadFile(fileSystem, etagFilename)
		if err != nil {
			return "", fmt.Errorf("cannot read etag from file %s: %v", etagFilename, err)
		}
		return string(etag), nil
	}
	return "", nil
}

// redirect performs a redirect to a given path. The 'toPath' parameter
// MUST be solely a path, and MUST NOT include a query.
func redirect(w http.ResponseWriter, r *http.Request, toPath string) error {
	for strings.HasPrefix(toPath, "//") {
		// prevent path-based open redirects
		toPath = strings.TrimPrefix(toPath, "/")
	}
	// preserve the query string if present
	if r.URL.RawQuery != "" {
		toPath += "?" + r.URL.RawQuery
	}
	http.Redirect(w, r, toPath, http.StatusPermanentRedirect)

Review comment (suggestion):
I actually wonder if the extensions should have the dot included. So like the user would configure `.sha256` instead of `sha256`. That feels more conventional to me.

Code after:

// notFound returns a 404 error or, if pass-thru is enabled,
// it calls the next handler in the chain.
func (fsrv *FileServer) notFound(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
	if fsrv.PassThru {
		return next.ServeHTTP(w, r)
	}
	return caddyhttp.Error(http.StatusNotFound, nil)
}

// calculateEtag produces a strong etag by default, although, for
// efficiency reasons, it does not actually consume the contents
// of the file to make a hash of all the bytes. ¯\_(ツ)_/¯
// Prefix the etag with "W/" to convert it into a weak etag.
// See: https://tools.ietf.org/html/rfc7232#section-2.3
func calculateEtag(d os.FileInfo) string {
	mtime := d.ModTime().Unix()
	if mtime == 0 || mtime == 1 {
		return "" // not useful anyway; see issue #5548
	}
	t := strconv.FormatInt(mtime, 36)
	s := strconv.FormatInt(d.Size(), 36)
	return `"` + t + s + `"`
}

// Finds the first corresponding etag file for a given file in the file system and return its content
func (fsrv *FileServer) getEtagFromFile(fileSystem fs.FS, filename string) (string, error) {
	for _, suffix := range fsrv.EtagFileExtensions {
		etagFilename := filename + suffix
		etag, err := fs.ReadFile(fileSystem, etagFilename)
		if errors.Is(err, fs.ErrNotExist) {
			continue
		}
		if err != nil {
			return "", fmt.Errorf("cannot read etag from file %s: %v", etagFilename, err)
		}
		return string(etag), nil
	}
	return "", nil
}

// redirect performs a redirect to a given path. The 'toPath' parameter
// MUST be solely a path, and MUST NOT include a query.
func redirect(w http.ResponseWriter, r *http.Request, toPath string) error {
	for strings.HasPrefix(toPath, "//") {
		// prevent path-based open redirects
		toPath = strings.TrimPrefix(toPath, "/")
	}
	// preserve the query string if present
	if r.URL.RawQuery != "" {
		toPath += "?" + r.URL.RawQuery