Merge branch 'feature/static' into develop

This commit is contained in:
Maxim Lebedev 2023-11-13 07:25:55 +06:00
commit aff4976a40
Signed by: toby3d
GPG Key ID: 1F14E25B7C119FC5
3 changed files with 20 additions and 28 deletions

View File

@ -23,7 +23,7 @@ WORKDIR /
COPY --from=builder /app/home /home
VOLUME ["/content", "/theme"]
VOLUME ["/content", "/theme", "/static"]
EXPOSE 3000

View File

@ -11,6 +11,7 @@ type Config struct {
ContentDir string `env:"CONTENT_DIR" envDefault:"content/"`
Host string `env:"HOST" envDefault:"0.0.0.0"`
ThemeDir string `env:"THEME_DIR" envDefault:"theme/"`
StaticDir string `env:"STATIC_DIR" envDefault:"static/"`
Port uint16 `env:"PORT" envDefault:"3000"`
}
@ -21,6 +22,7 @@ func TestConfig(tb testing.TB) *Config {
ContentDir: "testdata/content/",
Host: "0.0.0.0",
ThemeDir: "testdata/theme/",
StaticDir: "testdata/static/",
Port: 3000,
}
}

44
main.go
View File

@ -63,20 +63,23 @@ var cpuProfilePath, memProfilePath string
func NewApp(ctx context.Context, config *domain.Config) (*App, error) {
themeDir := os.DirFS(config.ThemeDir)
contentDir := os.DirFS(config.ContentDir)
statics := staticfsrepo.NewFileServerStaticRepository(contentDir)
resources := staticfsrepo.NewFileServerStaticRepository(contentDir)
sites := sitefsrepo.NewFileSystemSiteRepository(contentDir)
siter := siteucase.NewSiteUseCase(sites, statics)
siter := siteucase.NewSiteUseCase(sites, resources)
funcMap, err := templateutil.New(themeDir, siter)
if err != nil {
logger.Fatalln("cannot setup template.FuncMap for templates: %w", err)
}
staticer := staticucase.NewStaticUseCase(statics)
staticDir := os.DirFS(config.StaticDir)
statics := staticfsrepo.NewFileServerStaticRepository(staticDir)
// TODO(toby3d): use exists static use case or split that on static and resource modules?
resourcer := staticucase.NewStaticUseCase(resources)
themes := themefsrepo.NewFileSystemThemeRepository(themeDir, funcMap)
themer := themeucase.NewThemeUseCase(themes)
pages := pagefsrepo.NewFileSystemPageRepository(contentDir)
pager := pageucase.NewPageUseCase(pages, statics)
pager := pageucase.NewPageUseCase(pages, resources)
matcher := language.NewMatcher(message.DefaultCatalog.Languages())
@ -98,32 +101,18 @@ func NewApp(ctx context.Context, config *domain.Config) (*App, error) {
return
}
lang := domain.NewLanguage(head)
if lang == domain.LanguageUnd {
// WARN(toby3d): fetch static resources from separated static directory instead of
// $HOME_CONTENT_DIR?
//
// Looks like what current logic is insecure, because resource from private page in
// content directory '/en/page/file.jpg' by lower use case execution can be accessed
// here by URL '/page/file.jpg'.
res, err := staticer.Do(r.Context(), r.URL.Path)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
http.ServeContent(w, r, res.Name(), domain.ResourceModTime(res), res)
// TODO(toby3d): use exists static use case or split that on static and resource modules?
// INFO(toby3d): any static file is public and unprotected by design, so it's safe to search it
// first before deep down to any page or it's resource which might be secured by middleware or
// something else.
static, err := statics.Get(r.Context(), strings.TrimPrefix(r.URL.Path, "/"))
if err == nil {
http.ServeContent(w, r, static.Name(), domain.ResourceModTime(static), static)
return
}
lang := domain.NewLanguage(head)
r.URL.Path = tail
s, err := siter.Do(r.Context(), lang)
@ -141,7 +130,7 @@ func NewApp(ctx context.Context, config *domain.Config) (*App, error) {
return
}
res, err := staticer.Do(r.Context(), r.URL.Path)
res, err := resourcer.Do(r.Context(), r.URL.Path)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
http.Error(w, err.Error(), http.StatusNotFound)
@ -225,6 +214,7 @@ func main() {
for _, dir := range []*string{
&config.ContentDir,
&config.ThemeDir,
&config.StaticDir,
} {
if *dir, err = filepath.Abs(filepath.Clean(*dir)); err != nil {
logger.Fatalf("cannot format '%s' into absolute path: %s", *dir, err)