🏗️ Serve static from HOME_STATIC_DIR first

This commit is contained in:
Maxim Lebedev 2023-11-13 07:15:39 +06:00
parent 43126b3d92
commit 495d49dada
Signed by: toby3d
GPG Key ID: 1F14E25B7C119FC5
1 changed files with 17 additions and 27 deletions

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 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(), r.URL.Path[1:])
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)