openFile opens the file at the given filename. If there was an error, the response is configured to inform the client how to best handle it and a well-described handler error is returned (do not wrap the returned error value).
(fileSystem fs.FS, filename string, w http.ResponseWriter)
| 600 | // and a well-described handler error is returned (do not wrap the |
| 601 | // returned error value). |
| 602 | func (fsrv *FileServer) openFile(fileSystem fs.FS, filename string, w http.ResponseWriter) (fs.File, error) { |
| 603 | file, err := fileSystem.Open(filename) |
| 604 | if err != nil { |
| 605 | err = fsrv.mapDirOpenError(fileSystem, err, filename) |
| 606 | if errors.Is(err, fs.ErrNotExist) { |
| 607 | if c := fsrv.logger.Check(zapcore.DebugLevel, "file not found"); c != nil { |
| 608 | c.Write(zap.String("filename", filename), zap.Error(err)) |
| 609 | } |
| 610 | return nil, caddyhttp.Error(http.StatusNotFound, err) |
| 611 | } else if errors.Is(err, fs.ErrPermission) { |
| 612 | if c := fsrv.logger.Check(zapcore.DebugLevel, "permission denied"); c != nil { |
| 613 | c.Write(zap.String("filename", filename), zap.Error(err)) |
| 614 | } |
| 615 | return nil, caddyhttp.Error(http.StatusForbidden, err) |
| 616 | } |
| 617 | // maybe the server is under load and ran out of file descriptors? |
| 618 | // have client wait arbitrary seconds to help prevent a stampede |
| 619 | //nolint:gosec |
| 620 | backoff := weakrand.IntN(maxBackoff-minBackoff) + minBackoff |
| 621 | w.Header().Set("Retry-After", strconv.Itoa(backoff)) |
| 622 | if c := fsrv.logger.Check(zapcore.DebugLevel, "retry after backoff"); c != nil { |
| 623 | c.Write(zap.String("filename", filename), zap.Int("backoff", backoff), zap.Error(err)) |
| 624 | } |
| 625 | return nil, caddyhttp.Error(http.StatusServiceUnavailable, err) |
| 626 | } |
| 627 | return file, nil |
| 628 | } |
| 629 | |
| 630 | // mapDirOpenError maps the provided non-nil error from opening name |
| 631 | // to a possibly better non-nil error. In particular, it turns OS-specific errors |