mirror of https://github.com/jlelse/GoBlog
Fix rendering, render 404 errors, flatten redirects
This commit is contained in:
parent
0175ce1729
commit
12c4415cd3
|
@ -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)
|
||||
}
|
17
http.go
17
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
|
||||
}
|
||||
|
|
4
posts.go
4
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) {
|
||||
|
|
29
redirects.go
29
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) {
|
||||
|
|
29
render.go
29
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)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
{{ define "title" }}
|
||||
<title>{{ with .Title }}{{ . }} - {{end}}{{ blog.Title }}</title>
|
||||
{{ end }}
|
||||
|
||||
{{ define "main" }}
|
||||
<main>
|
||||
{{ with .Title }}<h1>{{ . }}</h1>{{ end }}
|
||||
{{ with .Message }}{{ md . }}{{ end }}
|
||||
</main>
|
||||
{{ end }}
|
||||
|
||||
{{ define "error" }}
|
||||
{{ template "base" . }}
|
||||
{{ end }}
|
|
@ -1,14 +1,18 @@
|
|||
{{ template "base" . }}
|
||||
|
||||
{{ define "title" }}
|
||||
<title>{{ with title . }}{{ . }} - {{end}}{{ blog.Title }}</title>
|
||||
<title>{{ with p . "title" }}{{ . }} - {{end}}{{ blog.Title }}</title>
|
||||
{{ end }}
|
||||
|
||||
{{ define "main" }}
|
||||
<main class=h-entry>
|
||||
<article>
|
||||
{{ with title . }}<h1 class=p-name>{{ . }}</h1>{{ end }}
|
||||
<div class=e-content>{{ md .Content }}</div>
|
||||
{{ with p . "title" }}<h1 class=p-name>{{ . }}</h1>{{ end }}
|
||||
{{ with .Content }}
|
||||
<div class=e-content>{{ md . }}</div>
|
||||
{{ end }}
|
||||
</article>
|
||||
</main>
|
||||
{{ end }}
|
||||
|
||||
{{ define "post"}}
|
||||
{{ template "base" . }}
|
||||
{{ end }}
|
|
@ -1,7 +1,9 @@
|
|||
<!doctype html>
|
||||
<html lang={{ blog.Lang }}>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="robots" content="noindex">
|
||||
<title>{{ .Permalink }}</title>
|
||||
<link rel="canonical" href="{{ .Permalink }}"/>
|
||||
<meta http-equiv="refresh" content="0; url={{ .Permalink }}"/>
|
||||
{{ define "redirect" }}
|
||||
<!doctype html>
|
||||
<html lang={{ blog.Lang }}>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="robots" content="noindex">
|
||||
<title>{{ .Permalink }}</title>
|
||||
<link rel="canonical" href="{{ .Permalink }}"/>
|
||||
<meta http-equiv="refresh" content="0; url={{ .Permalink }}"/>
|
||||
{{ end }}
|
Loading…
Reference in New Issue