60 lines
1.3 KiB
Go
60 lines
1.3 KiB
Go
package fs
|
|
|
|
import (
|
|
"io/fs"
|
|
"mime"
|
|
"strings"
|
|
|
|
"tildegit.org/tjp/gus"
|
|
)
|
|
|
|
// ResolveFile finds a file from a filesystem based on a request path.
|
|
//
|
|
// It only returns a non-nil file if a file is found - not a directory.
|
|
// If there is any other sort of filesystem access error, it will be
|
|
// returned.
|
|
func ResolveFile(request *gus.Request, fileSystem fs.FS) (string, fs.File, error) {
|
|
filepath := strings.TrimPrefix(request.Path, "/")
|
|
file, err := fileSystem.Open(filepath)
|
|
if isNotFound(err) {
|
|
return "", nil, nil
|
|
}
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
|
|
isDir, err := fileIsDir(file)
|
|
if err != nil {
|
|
_ = file.Close()
|
|
return "", nil, err
|
|
}
|
|
|
|
if isDir {
|
|
_ = file.Close()
|
|
return "", nil, nil
|
|
}
|
|
|
|
return filepath, file, nil
|
|
}
|
|
|
|
func mediaType(filePath string) string {
|
|
if strings.HasSuffix(filePath, ".gmi") {
|
|
// This may not be present in the listings searched by mime.TypeByExtension,
|
|
// so provide a dedicated fast path for it here.
|
|
return "text/gemini"
|
|
}
|
|
|
|
slashIdx := strings.LastIndex(filePath, "/")
|
|
dotIdx := strings.LastIndex(filePath[slashIdx+1:], ".")
|
|
if dotIdx == -1 {
|
|
return "application/octet-stream"
|
|
}
|
|
ext := filePath[slashIdx+1+dotIdx:]
|
|
|
|
mtype := mime.TypeByExtension(ext)
|
|
if mtype == "" {
|
|
return "application/octet-stream"
|
|
}
|
|
return mtype
|
|
}
|