aboutsummaryrefslogtreecommitdiff
path: root/page
diff options
context:
space:
mode:
Diffstat (limited to 'page')
-rw-r--r--page/checkup.go2
-rw-r--r--page/misc.go48
-rw-r--r--page/page.go24
-rw-r--r--page/render.go61
-rw-r--r--page/renderJson.go77
-rw-r--r--page/renderMarkdown.go32
6 files changed, 114 insertions, 130 deletions
diff --git a/page/checkup.go b/page/checkup.go
index b3b71fc..c6ca447 100644
--- a/page/checkup.go
+++ b/page/checkup.go
@@ -21,7 +21,7 @@ func (p *Page) Checkup() (map[string]PageList, error) {
return err
}
- if !info.IsDir() && strings.HasSuffix(info.Name(), Suffix) {
+ if !info.IsDir() && strings.HasSuffix(info.Name(), Suffix) { //nolint:nestif
p2 := NewPage(strings.ReplaceAll(path, Suffix, ""))
err = p2.Read()
diff --git a/page/misc.go b/page/misc.go
index e603458..4b67945 100644
--- a/page/misc.go
+++ b/page/misc.go
@@ -2,10 +2,58 @@ package page
import (
"encoding/json"
+ "net/http"
+ "path/filepath"
"gopkg.in/yaml.v3"
)
+// logReq just maks that we've done a request in the log, format is roughly:
+// remoteAddr, Method, statusCode, page path.
+func logReq(r *http.Request, statusCode int) {
+ Logger.Printf("%s %s %d %s",
+ r.RemoteAddr,
+ r.Method,
+ statusCode,
+ GetPagePath(r))
+}
+
+// logErr logs messages in the format of:
+// RemoteAddr, Method, path: pagePath, message, error.
+func logErr(r *http.Request, msg string, err error) {
+ Logger.Printf("%s %s path: %s %s: %s",
+ r.RemoteAddr,
+ r.Method,
+ GetPagePath(r),
+ msg,
+ err)
+}
+
+// plainResp sends a text/plain response down to the writer with the appropriate
+// status code and a body of msg.
+func plainResp(w http.ResponseWriter, statusCode int, msg string) {
+ w.Header().Set("Content-type", "text/plain")
+ w.WriteHeader(statusCode)
+ _, _ = w.Write([]byte(msg))
+}
+
+// GetURLPath returns r.URL.Path, unless it's merely a slash, then
+// it returns "index". Usefulf for defining your own handlers.
+func GetURLPath(r *http.Request) string {
+ u := r.URL.Path
+ if u == "/" {
+ u = "/index"
+ }
+
+ return u
+}
+
+// GetPagePath is the same as GetURLPath except that it joins it with
+// the current directory ".". Also useful in defining your own handlers.
+func GetPagePath(r *http.Request) string {
+ return filepath.Join(".", GetURLPath(r))
+}
+
// EncodeYaml is meant to be used in templating functions to encode
// arbitrary information as a yaml string.
func (p Page) EncodeYaml(data interface{}) string {
diff --git a/page/page.go b/page/page.go
index 214021e..03d1f1e 100644
--- a/page/page.go
+++ b/page/page.go
@@ -59,7 +59,7 @@ type Page struct {
Vars map[string]interface{}
// Keys of vars to be included when RenderJson is called, all vars are
// omitted if empty.
- JsonVars []string
+ JSONVars []string
markdown []byte
}
@@ -69,7 +69,7 @@ type Page struct {
var Global interface{}
// Funcs accessible to the templates.
-var Funcs template.FuncMap = template.FuncMap{
+var Funcs = template.FuncMap{
"join": strings.Join,
"split": strings.Split,
"toLower": strings.ToLower,
@@ -191,7 +191,12 @@ func (p *Page) Render(wr io.Writer) error {
t = t.Funcs(Funcs)
- return t.Execute(wr, p)
+ err = t.Execute(wr, p)
+ if err != nil {
+ return fmt.Errorf("while executing template: %w", err)
+ }
+
+ return nil
}
// Read in the special markdown file format for the website off of the disk.
@@ -253,6 +258,7 @@ func (p *Page) Read() error {
// this is called in the base template.
func (p *Page) RenderBody() (string, error) {
s, err := p.GetMarkdown()
+
return string(blackfriday.Run([]byte(s))), err
}
@@ -278,3 +284,15 @@ func (p *Page) GetMarkdown() (string, error) {
func (p Page) String() string {
return fmt.Sprintf("Page: %s", p.path)
}
+
+// setRenderingMarkdownOnly simply sets the special vars field,
+// "RenderingMarkdownOnly" to be true.
+func (p *Page) setRenderingMarkdownOnly() {
+ if p.Vars != nil {
+ p.Vars["RenderingMarkdownOnly"] = true
+ } else {
+ p.Vars = map[string]interface{}{
+ "RenderingMarkdownOnly": true,
+ }
+ }
+}
diff --git a/page/render.go b/page/render.go
index 691a258..0ae5334 100644
--- a/page/render.go
+++ b/page/render.go
@@ -5,43 +5,21 @@ import (
"errors"
"io/fs"
"net/http"
- "path/filepath"
)
-func getURLPath(r *http.Request) string {
- u := r.URL.Path
- if u == "/" {
- u = "/index"
- }
-
- return u
-}
-
// Render5xx is automatically called if any render fails,
// additionally you can call it for your own uses. It will
// try to use the 5xx template but will fall back to a plain
// page if that fails.
func Render5xx(w http.ResponseWriter, r *http.Request,
vars map[string]interface{}, statusCode int) {
- u := getURLPath(r)
-
- Logger.Printf("%s %s %d %s",
- r.RemoteAddr,
- r.Method,
- statusCode,
- u)
-
p := NewPage(TemplateDirectory + "/5xx")
buf := &bytes.Buffer{}
err := p.Render(buf)
if err != nil {
- Logger.Printf("%s %s path: %s while trying 5xx: %s",
- r.RemoteAddr,
- r.Method,
- u,
- err)
+ logErr(r, "while trying 5xx", err)
http.Error(w, "Internal server error", statusCode)
return
@@ -51,32 +29,20 @@ func Render5xx(w http.ResponseWriter, r *http.Request,
_, _ = w.Write(buf.Bytes())
- Logger.Printf("%s %s %d %s", r.RemoteAddr, r.Method, statusCode, u)
+ logReq(r, statusCode)
}
// Render4xx is mostly used to render a 404 page, pulls from 404 template.
// automatically called by Render if a page is missing.
func Render4xx(w http.ResponseWriter, r *http.Request,
vars map[string]interface{}, statusCode int) {
- u := getURLPath(r)
-
- Logger.Printf("%s %s %d %s",
- r.RemoteAddr,
- r.Method,
- statusCode,
- u)
-
p := NewPage(TemplateDirectory + "/4xx")
buf := &bytes.Buffer{}
err := p.Render(buf)
if err != nil {
- Logger.Printf("%s %s path: %s while trying 404: %s",
- r.RemoteAddr,
- r.Method,
- u,
- err)
+ logErr(r, "while trying 404", err)
Render5xx(w, r, vars, http.StatusInternalServerError)
return
@@ -91,17 +57,13 @@ func Render4xx(w http.ResponseWriter, r *http.Request,
return
}
- Logger.Printf("%s %s %d %s", r.RemoteAddr, r.Method, statusCode, u)
+ logReq(r, statusCode)
}
// Render is a lower level option, allowing you to specify local
// variables and the status code in which to return.
func Render(w http.ResponseWriter, r *http.Request,
path string, vars map[string]interface{}, statusCode int) {
- u := getURLPath(r)
-
- u = filepath.Join(".", u)
-
// Sepcifically use the specified path for the page
p := NewPage(path)
@@ -119,11 +81,7 @@ func Render(w http.ResponseWriter, r *http.Request,
return
}
- Logger.Printf("%s %s path: %s rendering encountered: %s",
- r.RemoteAddr,
- r.Method,
- u,
- err)
+ logErr(r, "rendering encountered", err)
Render5xx(w, r, vars, http.StatusInternalServerError)
return
@@ -133,18 +91,13 @@ func Render(w http.ResponseWriter, r *http.Request,
_, err = w.Write(buf.Bytes())
if err != nil {
- Logger.Printf("%s %s %d %s: while writing buf: %s",
- r.RemoteAddr,
- r.Method,
- statusCode,
- u,
- err)
+ logErr(r, "while writing to buf", err)
Render5xx(w, r, nil, http.StatusInternalServerError)
return
}
- Logger.Printf("%s %s %d %s", r.RemoteAddr, r.Method, statusCode, u)
+ logReq(r, statusCode)
}
// RenderWithVars allows you to specify a specific page and whether or not
diff --git a/page/renderJson.go b/page/renderJson.go
index 9359b69..4c03e12 100644
--- a/page/renderJson.go
+++ b/page/renderJson.go
@@ -6,32 +6,28 @@ import (
"errors"
"io/fs"
"net/http"
- "path/filepath"
)
-// RenderJson is analogous to Render, though it renders the page,
+// RenderJSON is analogous to Render, though it renders the page,
// as a JSON key "content", optionally from the YAML it'll include
// additional keys in the json if specified under the 'pageJson' key.
// E.g.
-// ---
-// title: Some page
-// description: Some page desc
-// jsonvars:
-// - includeMeInJSON
-// vars:
-// notIncluded: some value
-// includeMeInJSON:
-// some: arbitrary
-// data: to
-// send: down
-// |--
-// My page content, wee!
-func RenderJson(w http.ResponseWriter, r *http.Request,
+//
+// ---
+// title: Some page
+// description: Some page desc
+// jsonvars:
+// - includeMeInJSON
+// vars:
+// notIncluded: some value
+// includeMeInJSON:
+// some: arbitrary
+// data: to
+// send: down
+// |--
+// My page content, wee!
+func RenderJSON(w http.ResponseWriter, r *http.Request, //nolint:funlen
path string, vars map[string]interface{}, statusCode int) {
- u := getURLPath(r)
-
- u = filepath.Join(".", u)
-
// Sepcifically use the specified path for the page
p := NewPage(path)
@@ -40,22 +36,18 @@ func RenderJson(w http.ResponseWriter, r *http.Request,
}
out := map[string]interface{}{}
-
buf := &bytes.Buffer{}
+
err := p.Render(buf)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
- renderJsonErr(w, r, "Not found", http.StatusNotFound)
+ renderJSONErr(w, "Not found", http.StatusNotFound)
return
}
- Logger.Printf("%s %s path: %s rendering encountered: %s",
- r.RemoteAddr,
- r.Method,
- u,
- err)
- renderJsonErr(w, r, "Internal server error",
+ logErr(r, "rendering JSON encountered", err)
+ renderJSONErr(w, "Internal server error",
http.StatusInternalServerError)
return
@@ -66,13 +58,7 @@ func RenderJson(w http.ResponseWriter, r *http.Request,
}
if r.URL.Query().Get("markdown") == "1" {
- if p.Vars != nil {
- p.Vars["RenderingMarkdownOnly"] = true
- } else {
- p.Vars = map[string]interface{}{
- "RenderingMarkdownOnly": true,
- }
- }
+ p.setRenderingMarkdownOnly()
// Tossing the error, since it would've been revealed above
md, _ := p.GetMarkdown()
out["Markdown"] = md
@@ -80,7 +66,7 @@ func RenderJson(w http.ResponseWriter, r *http.Request,
// Make a "set" of keys
keys := map[string]struct{}{}
- for _, k := range p.JsonVars {
+ for _, k := range p.JSONVars {
keys[k] = struct{}{}
}
@@ -100,26 +86,23 @@ func RenderJson(w http.ResponseWriter, r *http.Request,
err = enc.Encode(out)
if err != nil {
- Logger.Printf("%s %s %d %s: while writing buf: %s",
- r.RemoteAddr,
- r.Method,
- statusCode,
- u,
- err)
+ logErr(r, "while writing to buf", err)
return
}
- Logger.Printf("%s %s %d %s", r.RemoteAddr, r.Method, statusCode, u)
+ logReq(r, statusCode)
}
-func renderJsonErr(w http.ResponseWriter, r *http.Request, msg string,
- statusCode int) {
+func renderJSONErr(w http.ResponseWriter, msg string, statusCode int) {
enc := json.NewEncoder(w)
w.WriteHeader(statusCode)
+
_ = enc.Encode(&struct {
- Status string
+ StatusCode int
+ Msg string
}{
- Status: msg,
+ StatusCode: statusCode,
+ Msg: msg,
})
}
diff --git a/page/renderMarkdown.go b/page/renderMarkdown.go
index 7a365e6..8356e55 100644
--- a/page/renderMarkdown.go
+++ b/page/renderMarkdown.go
@@ -5,19 +5,14 @@ import (
"errors"
"io/fs"
"net/http"
- "path/filepath"
)
// RenderMarkdown is analogous to Render, except it spits out rendered markdown
// as text/plain. It also sets .Vars.RenderingMarkdownOnly so templates can
// vary on whether or not they're plain markdown. For instance, not including
-// some HTML tags
+// some HTML tags.
func RenderMarkdown(w http.ResponseWriter, r *http.Request,
path string, vars map[string]interface{}, statusCode int) {
- u := getURLPath(r)
-
- u = filepath.Join(".", u)
-
// Sepcifically use the specified path for the page
p := NewPage(path)
@@ -38,21 +33,13 @@ func RenderMarkdown(w http.ResponseWriter, r *http.Request,
err := p.Render(buf)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
- w.WriteHeader(http.StatusNotFound)
- w.Header().Set("Content-type", "text/plain")
- w.Write([]byte("Not found"))
+ plainResp(w, http.StatusNotFound, "Not found")
return
}
- Logger.Printf("%s %s path: %s rendering encountered: %s",
- r.RemoteAddr,
- r.Method,
- u,
- err)
- w.WriteHeader(http.StatusInternalServerError)
- w.Header().Set("Content-type", "text/plain")
- w.Write([]byte("Internal server error"))
+ logErr(r, "while rendering", err)
+ plainResp(w, http.StatusInternalServerError, "Internal server error")
return
}
@@ -60,20 +47,15 @@ func RenderMarkdown(w http.ResponseWriter, r *http.Request,
// Error was handled above
md, _ := p.GetMarkdown()
- w.WriteHeader(statusCode)
w.Header().Set("Content-type", "text/plain")
+ w.WriteHeader(statusCode)
_, err = w.Write([]byte(md))
if err != nil {
- Logger.Printf("%s %s %d %s: while writing buf: %s",
- r.RemoteAddr,
- r.Method,
- statusCode,
- u,
- err)
+ logErr(r, "while writing buf", err)
return
}
- Logger.Printf("%s %s %d %s", r.RemoteAddr, r.Method, statusCode, u)
+ logReq(r, statusCode)
}