Merge branch 'feature/static' into develop
This commit is contained in:
commit
aff4976a40
|
@ -23,7 +23,7 @@ WORKDIR /
|
|||
|
||||
COPY --from=builder /app/home /home
|
||||
|
||||
VOLUME ["/content", "/theme"]
|
||||
VOLUME ["/content", "/theme", "/static"]
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
|
|
|
@ -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
44
main.go
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue