diff options
Diffstat (limited to 'internal/storage')
-rw-r--r-- | internal/storage/file.go | 5 | ||||
-rw-r--r-- | internal/storage/files/file.go | 45 | ||||
-rw-r--r-- | internal/storage/files/reader.go | 9 | ||||
-rw-r--r-- | internal/storage/files/writer.go | 74 | ||||
-rw-r--r-- | internal/storage/interface.go | 19 |
5 files changed, 63 insertions, 89 deletions
diff --git a/internal/storage/file.go b/internal/storage/file.go index f588bf3..38824b6 100644 --- a/internal/storage/file.go +++ b/internal/storage/file.go @@ -1,8 +1,9 @@ package storage import ( - "io" "time" + + "go.alanpearce.eu/website/internal/buffer" ) type File struct { @@ -10,7 +11,7 @@ type File struct { ContentType string LastModified time.Time Etag string - Encodings map[string]io.ReadSeekCloser + Encodings map[string]*buffer.Buffer } func (f *File) AvailableEncodings() []string { diff --git a/internal/storage/files/file.go b/internal/storage/files/file.go index a71811c..b79c43c 100644 --- a/internal/storage/files/file.go +++ b/internal/storage/files/file.go @@ -10,19 +10,18 @@ import ( "strings" "gitlab.com/tozd/go/errors" + "go.alanpearce.eu/website/internal/buffer" "go.alanpearce.eu/website/internal/storage" ) -type File struct { - storage.File -} +type Content io.ReadSeekCloser var encodings = map[string]string{ "br": ".br", "gzip": ".gz", } -func (r *Reader) OpenFile(path string, filename string) (*File, error) { +func (r *Reader) OpenFile(path string, filename string) (*storage.File, error) { f, err := os.Open(filename) if err != nil { return nil, errors.WithMessage(err, "could not open file for reading") @@ -37,15 +36,18 @@ func (r *Reader) OpenFile(path string, filename string) (*File, error) { return nil, errors.WithMessage(err, "could not calculate etag") } - file := &File{ - File: storage.File{ - Path: path, - ContentType: mime.TypeByExtension(filepath.Ext(filename)), - LastModified: stat.ModTime(), - Etag: etag, - Encodings: map[string]io.ReadSeekCloser{ - "identity": f, - }, + buf := new(buffer.Buffer) + if _, err := f.WriteTo(buf); err != nil { + return nil, errors.WithMessage(err, "could not read file") + } + + file := &storage.File{ + Path: path, + ContentType: mime.TypeByExtension(filepath.Ext(filename)), + LastModified: stat.ModTime(), + Etag: etag, + Encodings: map[string]*buffer.Buffer{ + "identity": buf, }, } @@ -58,10 +60,12 @@ func (r *Reader) OpenFile(path string, filename string) (*File, error) { return nil, errors.WithMessagef(err, "could not stat file %s", filename+suffix) } - file.Encodings[enc], err = os.Open(filename + suffix) + bytes, err := os.ReadFile(filename + suffix) if err != nil { return nil, errors.WithMessagef(err, "could not read file %s", filename+suffix) } + buf := buffer.NewBuffer(bytes) + file.Encodings[enc] = buf } return file, nil @@ -76,23 +80,12 @@ func etag(f io.Reader) (string, error) { return fmt.Sprintf(`W/"%x"`, hash.Sum(nil)), nil } -func (f *File) Close() error { - var errs []error - for _, enc := range f.Encodings { - if err := enc.Close(); err != nil { - errs = append(errs, err) - } - } - - return errors.Join(errs...) -} - func pathNameToFileName(pathname string) string { if strings.HasSuffix(pathname, "/") { pathname = pathname + "index.html" } - return pathname + return strings.TrimPrefix(pathname, "/") } func fileNameToPathName(filename string) string { diff --git a/internal/storage/files/reader.go b/internal/storage/files/reader.go index 425436b..fff37da 100644 --- a/internal/storage/files/reader.go +++ b/internal/storage/files/reader.go @@ -5,6 +5,7 @@ import ( "path/filepath" "strings" + "go.alanpearce.eu/website/internal/storage" "go.alanpearce.eu/x/log" "gitlab.com/tozd/go/errors" @@ -13,14 +14,14 @@ import ( type Reader struct { root string log *log.Logger - files map[string]*File + files map[string]*storage.File } func NewReader(path string, log *log.Logger) (*Reader, error) { r := &Reader{ root: path, log: log, - files: make(map[string]*File), + files: make(map[string]*storage.File), } if err := r.registerContentFiles(); err != nil { return nil, errors.WithMessagef(err, "registering content files") @@ -69,8 +70,8 @@ func (r *Reader) registerContentFiles() error { return nil } -func (r *Reader) GetFile(urlPath string) *File { - return r.files[urlPath] +func (r *Reader) GetFile(urlPath string) (*storage.File, error) { + return r.files[urlPath], nil } func (r *Reader) CanonicalisePath(path string) (cPath string, differs bool) { diff --git a/internal/storage/files/writer.go b/internal/storage/files/writer.go index ce498e7..40cf364 100644 --- a/internal/storage/files/writer.go +++ b/internal/storage/files/writer.go @@ -2,14 +2,15 @@ package files import ( "compress/gzip" - "context" "io" "os" "path/filepath" + "time" + "go.alanpearce.eu/website/internal/buffer" + "go.alanpearce.eu/website/internal/storage" "go.alanpearce.eu/x/log" - "github.com/a-h/templ" "github.com/andybalholm/brotli" "gitlab.com/tozd/go/errors" ) @@ -29,66 +30,49 @@ type Options struct { Compress bool } -func NewWriter(outputDirectory string, logger *log.Logger, opts *Options) *Files { +func NewWriter(outputDirectory string, logger *log.Logger, opts *Options) (*Files, error) { return &Files{ outputDirectory: outputDirectory, options: opts, log: logger, + }, nil +} + +func (f *Files) NewFile(path string) *storage.File { + return &storage.File{ + Path: path, + ContentType: "", + LastModified: time.Time{}, + Etag: "", + Encodings: map[string]*buffer.Buffer{ + "identity": nil, + }, } } -func (f *Files) Open(filename string) (io.ReadCloser, error) { +func (f *Files) OpenRead(filename string) (io.ReadCloser, error) { return os.Open(f.join(filename)) } -func (f *Files) OutputToFile(output io.Reader, filename string) error { - if err := f.Mkdirp(filepath.Dir(filename)); err != nil { - return err - } - f.log.Debug("outputting file", "filename", filename) - file, err := f.OpenFileAndVariants(filename) - if err != nil { - return errors.WithMessage(err, "could not open output file") - } - defer file.Close() - - if _, err := io.Copy(file, output); err != nil { - return errors.WithMessage(err, "could not write output file") - } - - return nil +func (f *Files) OpenWrite(filename string) (io.WriteCloser, error) { + return openFileWrite(f.join(filename)) } -func (f *Files) RenderToFile(component templ.Component, filename string) error { - if err := f.Mkdirp(filepath.Dir(filename)); err != nil { - return err - } - f.log.Debug("outputting file", "filename", filename) - file, err := f.OpenFileAndVariants(filename) +func (f *Files) Write(pathname string, content *buffer.Buffer) error { + filename := pathNameToFileName(pathname) + err := f.Mkdirp(filepath.Dir(filename)) if err != nil { - return errors.WithMessage(err, "could not open output file") - } - defer file.Close() - - if err := component.Render(context.TODO(), file); err != nil { - return errors.WithMessage(err, "could not write output file") + return errors.WithMessage(err, "could not create directory") } - return nil -} - -func (f *Files) WriterToFile(writer io.WriterTo, filename string) error { - if err := f.Mkdirp(filepath.Dir(filename)); err != nil { - return err - } - f.log.Debug("outputting file", "filename", filename) - file, err := f.OpenFileAndVariants(filename) + fd, err := openFileWrite(f.join(filename)) if err != nil { - return errors.WithMessage(err, "could not open output file") + return errors.WithMessagef(err, "could not open output file") } - defer file.Close() + defer fd.Close() - if _, err := writer.WriteTo(file); err != nil { + _, err = fd.Write(content.Bytes()) + if err != nil { return errors.WithMessage(err, "could not write output file") } @@ -170,7 +154,7 @@ func (f *Files) OpenFileAndVariants(filename string) (io.WriteCloser, error) { func (f *Files) Mkdirp(dir string) error { f.log.Debug("creating directory", "dir", dir) - err := os.MkdirAll(filepath.Join(f.outputDirectory, dir), 0755) + err := os.MkdirAll(f.join(dir), 0755) return errors.WithMessage(err, "could not create directory") } diff --git a/internal/storage/interface.go b/internal/storage/interface.go index 6c8f3cd..c167a49 100644 --- a/internal/storage/interface.go +++ b/internal/storage/interface.go @@ -1,21 +1,16 @@ package storage import ( - "io" - - "github.com/a-h/templ" + "go.alanpearce.eu/website/internal/buffer" ) +type Reader interface { + GetFile(path string) (*File, error) + CanonicalisePath(path string) (cPath string, differs bool) +} + type Writer interface { Mkdirp(path string) error - Open(filename string) (io.ReadCloser, error) - - OpenFileAndVariants(filename string) (io.WriteCloser, error) - - OutputToFile(output io.Reader, filename string) error - - RenderToFile(component templ.Component, filename string) error - - WriterToFile(writer io.WriterTo, filename string) error + Write(pathname string, content *buffer.Buffer) error } |