From 12c4415cd34d21960874e084a3c4769410457837 Mon Sep 17 00:00:00 2001 From: Jan-Lukas Else Date: Fri, 31 Jul 2020 21:02:47 +0200 Subject: [PATCH] Fix rendering, render 404 errors, flatten redirects --- errors.go | 19 +++++++++++++++++++ http.go | 17 +++++++++++------ posts.go | 4 ++-- redirects.go | 29 +++++++++++++++++++---------- render.go | 29 +++++++++++++++++------------ templates/error.gohtml | 14 ++++++++++++++ templates/post.gohtml | 14 +++++++++----- templates/redirect.gohtml | 16 +++++++++------- 8 files changed, 100 insertions(+), 42 deletions(-) create mode 100644 errors.go create mode 100644 templates/error.gohtml diff --git a/errors.go b/errors.go new file mode 100644 index 0000000..8759156 --- /dev/null +++ b/errors.go @@ -0,0 +1,19 @@ +package main + +import ( + "fmt" + "net/http" +) + +type errorData struct { + Title string + Message string +} + +func serve404(w http.ResponseWriter, r *http.Request) { + render(w, templateError, &errorData{ + Title: "404 Not Found", + Message: fmt.Sprintf("`%s` was not found", r.RequestURI), + }) + w.WriteHeader(http.StatusNotFound) +} diff --git a/http.go b/http.go index 5c10dca..b38d4d8 100644 --- a/http.go +++ b/http.go @@ -76,10 +76,12 @@ func buildHandler() (http.Handler, error) { } for _, path := range allRedirectPaths { if path != "" { - r.Get(path, serveRedirect) + r.With(minifier.Middleware).Get(path, serveRedirect) } } + r.With(minifier.Middleware).NotFound(serve404) + return r, nil } @@ -105,9 +107,12 @@ func (d *dynamicHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } func slashTrimmedPath(r *http.Request) string { - path := r.URL.Path - if len(path) > 1 { - path = strings.TrimSuffix(path, "/") - } - return path + return trimSlash(r.URL.Path) +} + +func trimSlash(s string) string { + if len(s) > 1 { + s = strings.TrimSuffix(s, "/") + } + return s } diff --git a/posts.go b/posts.go index ce72267..b239841 100644 --- a/posts.go +++ b/posts.go @@ -21,13 +21,13 @@ func servePost(w http.ResponseWriter, r *http.Request) { path := slashTrimmedPath(r) post, err := getPost(r.Context(), path) if err == errPostNotFound { - http.NotFound(w, r) + serve404(w, r) return } else if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } - render(w, templatePostName, post) + render(w, templatePost, post) } func getPost(context context.Context, path string) (*Post, error) { diff --git a/redirects.go b/redirects.go index 712a780..9ea8f4f 100644 --- a/redirects.go +++ b/redirects.go @@ -10,32 +10,41 @@ import ( var errRedirectNotFound = errors.New("redirect not found") func serveRedirect(w http.ResponseWriter, r *http.Request) { - redirect, err := getRedirect(r.Context(), slashTrimmedPath(r)) + redirect, more, err := getRedirect(r.Context(), slashTrimmedPath(r)) if err == errRedirectNotFound { - http.NotFound(w, r) + serve404(w, r) return } else if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } - w.WriteHeader(http.StatusFound) - _ = templates.ExecuteTemplate(w, templateRedirectName, struct { + // Flatten redirects + if more { + for more == true { + redirect, more, _ = getRedirect(r.Context(), trimSlash(redirect)) + } + } + // Send redirect + w.Header().Set("Location", redirect) + render(w, templateRedirect, struct { Permalink string }{ Permalink: redirect, }) + w.WriteHeader(http.StatusFound) } -func getRedirect(context context.Context, fromPath string) (string, error) { +func getRedirect(context context.Context, fromPath string) (string, bool, error) { var toPath string - row := appDb.QueryRowContext(context, "select toPath from redirects where fromPath=?", fromPath) - err := row.Scan(&toPath) + var moreRedirects int + row := appDb.QueryRowContext(context, "select toPath, (select count(*) from redirects where fromPath=(select toPath from redirects where fromPath=?)) as more from redirects where fromPath=?", fromPath, fromPath) + err := row.Scan(&toPath, &moreRedirects) if err == sql.ErrNoRows { - return "", errRedirectNotFound + return "", false, errRedirectNotFound } else if err != nil { - return "", err + return "", false, err } - return toPath, nil + return toPath, moreRedirects > 0, nil } func allRedirectPaths() ([]string, error) { diff --git a/render.go b/render.go index c723953..ddce80d 100644 --- a/render.go +++ b/render.go @@ -2,18 +2,21 @@ package main import ( "bytes" + "fmt" "html/template" "log" "net/http" ) -const templatePostName = "post.gohtml" -const templateRedirectName = "redirect.gohtml" +const templatePost = "post" +const templateError = "error" +const templateRedirect = "redirect" -var templates *template.Template +var templates map[string]*template.Template +var templateFunctions template.FuncMap func initRendering() { - templateFunctions := template.FuncMap{ + templateFunctions = template.FuncMap{ "blog": func() *configBlog { return appConfig.blog }, @@ -25,23 +28,25 @@ func initRendering() { } return template.HTML(htmlContent) }, - "title": func(post Post) string { - return post.Parameters["title"] + "p": func(post Post, parameter string) string { + return post.Parameters[parameter] }, } - var err error - - templates, err = template.New("templates").Funcs(templateFunctions).ParseGlob("templates/*.gohtml") - if err != nil { - log.Fatal(err) + templates = make(map[string]*template.Template) + for _, name := range []string{templatePost, templateError, templateRedirect} { + templates[name] = loadTemplate(name) } } +func loadTemplate(name string) *template.Template { + return template.Must(template.New(name).Funcs(templateFunctions).ParseFiles("templates/base.gohtml", fmt.Sprintf("templates/%s.gohtml", name))) +} + func render(w http.ResponseWriter, template string, data interface{}) { // We need to use a buffer here to enable minification var buffer bytes.Buffer - err := templates.ExecuteTemplate(&buffer, template, data) + err := templates[template].ExecuteTemplate(&buffer, template, data) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } diff --git a/templates/error.gohtml b/templates/error.gohtml new file mode 100644 index 0000000..a655bf5 --- /dev/null +++ b/templates/error.gohtml @@ -0,0 +1,14 @@ +{{ define "title" }} + {{ with .Title }}{{ . }} - {{end}}{{ blog.Title }} +{{ end }} + +{{ define "main" }} +
+ {{ with .Title }}

{{ . }}

{{ end }} + {{ with .Message }}{{ md . }}{{ end }} +
+{{ end }} + +{{ define "error" }} + {{ template "base" . }} +{{ end }} \ No newline at end of file diff --git a/templates/post.gohtml b/templates/post.gohtml index 43aa5ae..572ce89 100644 --- a/templates/post.gohtml +++ b/templates/post.gohtml @@ -1,14 +1,18 @@ -{{ template "base" . }} - {{ define "title" }} - {{ with title . }}{{ . }} - {{end}}{{ blog.Title }} + {{ with p . "title" }}{{ . }} - {{end}}{{ blog.Title }} {{ end }} {{ define "main" }}
- {{ with title . }}

{{ . }}

{{ end }} -
{{ md .Content }}
+ {{ with p . "title" }}

{{ . }}

{{ end }} + {{ with .Content }} +
{{ md . }}
+ {{ end }}
+{{ end }} + +{{ define "post"}} + {{ template "base" . }} {{ end }} \ No newline at end of file diff --git a/templates/redirect.gohtml b/templates/redirect.gohtml index c9218e0..d5564dc 100644 --- a/templates/redirect.gohtml +++ b/templates/redirect.gohtml @@ -1,7 +1,9 @@ - - - - -{{ .Permalink }} - - \ No newline at end of file +{{ define "redirect" }} + + + + + {{ .Permalink }} + + +{{ end }} \ No newline at end of file