shared/storage/files/file.go (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | package files
import (
"errors"
"fmt"
"hash/fnv"
"io"
"os"
"strings"
"github.com/Southclaws/fault"
"github.com/Southclaws/fault/fmsg"
"alin.ovh/homestead/shared/storage"
)
var encodings = map[string]string{
"br": ".br",
"gzip": ".gz",
"zstd": ".zstd",
}
func (r *Reader) OpenFile(path string, filename string) (*storage.File, error) {
file, err := storage.NewFile(path, filename)
if err != nil {
return nil, fault.Wrap(err, fmsg.With("could not init file"))
}
file.Etag, err = etag(file.Encodings["identity"])
if err != nil {
return nil, err
}
for enc, suffix := range encodings {
_, err := os.Stat(filename + suffix)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
continue
}
return nil, fault.Wrap(
err,
fmsg.With(fmt.Sprintf("could not stat file %s", filename+suffix)),
)
}
f, err := os.Open(filename + suffix)
if err != nil {
return nil, fault.Wrap(
err,
fmsg.With(fmt.Sprintf("could not read file %s", filename+suffix)),
)
}
file.Encodings[enc] = f
}
return file, nil
}
func etag(f io.Reader) (string, error) {
hash := fnv.New64a()
if _, err := io.Copy(hash, f); err != nil {
return "", fault.Wrap(err, fmsg.With("could not hash file"))
}
return fmt.Sprintf(`W/"%x"`, hash.Sum(nil)), nil
}
func pathNameToFileName(pathname string) string {
if strings.HasSuffix(pathname, "/") {
pathname += "index.html"
}
return strings.TrimPrefix(pathname, "/")
}
func cutSuffix(s, suffix string) string {
out, _ := strings.CutSuffix(s, suffix)
return out
}
func fileNameToPathName(filename string) string {
return cutSuffix(
cutSuffix(filename, "index.html"),
".html",
)
}
|