package sqlite
import (
"context"
"database/sql"
"encoding/json"
"strings"
"time"
"alin.ovh/homestead/shared/buffer"
"alin.ovh/homestead/shared/storage"
"alin.ovh/homestead/shared/storage/sqlite/db"
"alin.ovh/x/log"
"github.com/Southclaws/fault"
"github.com/Southclaws/fault/fmsg"
)
type Reader struct {
log *log.Logger
queries *db.Queries
}
func NewReader(conn *sql.DB, log *log.Logger) (*Reader, error) {
r := &Reader{
log: log,
queries: db.New(conn),
}
return r, nil
}
func (r *Reader) GetFile(filename string) (*storage.File, error) {
file := &storage.File{
Encodings: make(map[string]*buffer.Buffer, 1),
}
r.log.Debug("querying db for file", "filename", filename)
rows, err := r.queries.GetFile(context.TODO(), filename)
if err != nil {
return nil, fault.Wrap(err, fmsg.With("querying database"))
}
count := 0
for _, row := range rows {
count++
file.ContentType = row.File.ContentType
file.LastModified = time.Unix(row.File.LastModified, 0)
file.Etag = row.File.Etag
file.Title = row.File.Title
if len(row.File.Headers) > 2 {
err := json.Unmarshal(row.File.Headers, &file.Headers)
if err != nil {
return nil, fault.Wrap(err, fmsg.With("unmarshalling headers"))
}
}
file.Encodings[row.Content.Encoding] = buffer.NewBuffer(row.Content.Body)
}
if count == 0 {
return nil, nil
}
return file, nil
}
func (r *Reader) CanonicalisePath(path string) (cPath string, differs bool) {
cPath = path
switch {
case path == "/":
differs = false
case strings.HasSuffix(path, "/index.xml"):
cPath, differs = strings.TrimSuffix(path, "index.xml")+"atom.xml", true
case strings.HasSuffix(path, "/index.html"):
cPath, differs = strings.CutSuffix(path, "index.html")
case strings.HasSuffix(path, ".html"):
cPath, differs = strings.CutSuffix(path, ".html")
case !strings.HasSuffix(path, "/"):
d, err := r.queries.CheckPath(context.TODO(), cPath+"/")
if err != nil {
r.log.Warn("error canonicalising path", "path", path, "error", err)
return
}
differs = d == 1
if differs {
cPath += "/"
}
case strings.HasSuffix(path, "/"):
tmp := strings.TrimSuffix(path, "/")
d, err := r.queries.CheckPath(context.TODO(), tmp)
if err != nil {
r.log.Warn("error canonicalising path", "path", path, "error", err)
return
}
differs = d == 1
if differs {
cPath = tmp
}
}
return
}
shared/storage/sqlite/reader.go (view raw)