package main import ( "fmt" "html/template" "net/http" "os" "strconv" "strings" "time" "git.send.nrw/sendnrw/b1tsblog/internal/article" ) func getenv(k, d string) string { if v := os.Getenv(k); v != "" { return v } return d } func enabled(k string, def bool) bool { b, err := strconv.ParseBool(strings.ToLower(os.Getenv(k))) if err != nil { return def } return b } func cacheControl(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Cache-Control", "public, max-age=31536000, immutable") next.ServeHTTP(w, r) }) } var ( tplList *template.Template tplArticle *template.Template ) func main() { // --- Verzeichnisse konfigurierbar machen ------------------------- contentDir := os.Getenv("BLOG_CONTENT_DIR") if contentDir == "" { contentDir = "/content" // Fallback für local run } staticDir := os.Getenv("BLOG_STATIC_DIR") if staticDir == "" { staticDir = "/app/internal/web/static" } pagesDir := os.Getenv("BLOG_PAGES_DIR") if staticDir == "" { staticDir = "/pages" } funcs := template.FuncMap{ "now": time.Now, // jetzt‑Zeit bereitstellen } // Basislayout zuerst parsen layout := template.Must( template.New("base").Funcs(funcs). ParseFiles("/app/internal/web/templates/base.html"), ) // LIST‑Seite: base + list.html tplList = template.Must(layout.Clone()) template.Must(tplList.Funcs(funcs).ParseFiles("/app/internal/web/templates/list.html")) // ARTICLE‑Instanz tplArticle = template.Must(layout.Clone()) template.Must(tplArticle.Funcs(funcs).ParseFiles("/app/internal/web/templates/article.html")) tplPage := template.Must(layout.Clone()) template.Must(tplPage.ParseFiles("/app/internal/web/templates/page.html")) mux := http.NewServeMux() articles, err := article.LoadDir(contentDir) if err != nil { fmt.Println(err) } staticPages, err := article.LoadStatic(pagesDir) if err != nil { fmt.Println(err) } else { fmt.Println(staticPages) } // Handler für / mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } if err := tplList.ExecuteTemplate(w, "layout", articles); err != nil { http.Error(w, err.Error(), 500) } }) mux.HandleFunc("/post/", func(w http.ResponseWriter, r *http.Request) { slug := strings.TrimPrefix(r.URL.Path, "/post/") for _, a := range articles { if a.Slug == slug { if err := tplArticle.ExecuteTemplate(w, "layout", a); err != nil { http.Error(w, err.Error(), 500) } return } } http.NotFound(w, r) }) mux.HandleFunc("/page/", func(w http.ResponseWriter, r *http.Request) { slug := strings.TrimPrefix(r.URL.Path, "/page/") p, ok := staticPages[slug] if !ok { http.NotFound(w, r) return } // "layout" kommt aus deinem Template‑Pool (list/article nutzen es ja auch) if err := tplPage.ExecuteTemplate(w, "page", p); err != nil { http.Error(w, err.Error(), 500) } }) mux.Handle("/static/", cacheControl(http.StripPrefix("/static/", http.FileServer(http.Dir(staticDir))))) http.ListenAndServe(":8080", mux) }