feat: Add static path and per-template style.css #3

Open
chanbakjsd wants to merge 1 commits from chanbakjsd/blgo:master into master
5 changed files with 82 additions and 3 deletions

1
.gitignore vendored

@ -1,2 +1,3 @@
config.json
content/
static/

@ -1,6 +1,12 @@
package handler
import "net/http"
import (
"fmt"
"net/http"
"os"
)
var fs = http.FileServer(http.Dir("static/"))
// Index is the handler that displays the index page.
func Index(w http.ResponseWriter, r *http.Request) {
@ -13,5 +19,45 @@ func Handler(w http.ResponseWriter, r *http.Request) {
Index(w, r)
return
}
if r.URL.Path == "/style.css" {
TemplateStyle(w, r)
return
}
if Static(w, r) {
return
}
Post(w, r)
}
// TemplateStyle is a handler that servers the style of the current template.
func TemplateStyle(w http.ResponseWriter, r *http.Request) {
if themeCSS == nil {
// 404 if the theme CSS doesn't exist as it's optional.
CurrentTheme.ExecuteTemplate(w, "404.tmpl", nil)
return
}
w.Header().Add("Content-Type", "text/css")
_, _ = w.Write(themeCSS)
}
// Static is a handler that serves static content if available.
// If it has served something (the static file or an error), it returns true.
func Static(w http.ResponseWriter, r *http.Request) bool {
fileName := "static" + r.URL.Path
// Check if the file exists and is not a directory.
info, err := os.Stat(fileName)
if os.IsNotExist(err) || (info != nil && info.IsDir()) {
return false
}
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
CurrentTheme.ExecuteTemplate(w, "500.tmpl", fmt.Errorf("error reading static folder: %w", err))
return true
}
// The file probably exist now. Even if there's a mismatch, the malicious attacker can only get a
// 404 or a directory listing.
fs.ServeHTTP(w, r)
return true
}

@ -1,6 +1,7 @@
package handler
import (
"fmt"
"net/http"
"os"
)
@ -18,7 +19,7 @@ func Post(w http.ResponseWriter, r *http.Request) {
}
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
CurrentTheme.ExecuteTemplate(w, "500.tmpl", err)
CurrentTheme.ExecuteTemplate(w, "500.tmpl", fmt.Errorf("error reading content folder: %w", err))
return
}

@ -1,10 +1,19 @@
package handler
import "html/template"
import (
"html/template"
"io/ioutil"
"os"
"github.com/sirupsen/logrus"
)
// CurrentTheme is the set of template being used.
var CurrentTheme *template.Template
// themeCSS is the CSS of the current theme.
var themeCSS []byte
// SetTheme parses the provided theme name and sets it as the current theme.
func SetTheme(themeName string) error {
var err error
@ -17,5 +26,25 @@ func SetTheme(themeName string) error {
folder+"post.tmpl", // Page for posts.
)
if err != nil {
return err
}
// Check if the style CSS exists and is not a directory.
info, err := os.Stat(folder + "style.css")
if os.IsNotExist(err) || (info != nil && info.IsDir()) {
return nil
}
f, err := os.Open(folder + "style.css")
if err != nil {
return err
}
defer func() {
err := f.Close()
if err != nil {
logrus.Fatalf("Error while closing theme CSS file: %v", err)
}
}()
themeCSS, err = ioutil.ReadAll(f)
return err
}

@ -0,0 +1,2 @@
body { margin: 0 }
/* This is style.css of the debug template. */