diff options
| author | Mitchell Riedstra <mitch@riedstra.dev> | 2023-01-07 13:31:23 -0500 |
|---|---|---|
| committer | Mitchell Riedstra <mitch@riedstra.dev> | 2023-01-07 13:31:23 -0500 |
| commit | ca33a035c779ae14fb6330c8801c75f49dd1bb79 (patch) | |
| tree | deaabaf15d6d91079a68f247e46070399e4343ee /page | |
| parent | 97dd660925434be537cd9a49a1d0c893b223e357 (diff) | |
| download | go-website-ca33a035c779ae14fb6330c8801c75f49dd1bb79.tar.gz go-website-ca33a035c779ae14fb6330c8801c75f49dd1bb79.tar.xz | |
Add an internal caching option. It performs quite well.v0.0.22
Also refactor and clean up most linter warnings.
Diffstat (limited to 'page')
| -rw-r--r-- | page/checkup.go | 2 | ||||
| -rw-r--r-- | page/misc.go | 48 | ||||
| -rw-r--r-- | page/page.go | 24 | ||||
| -rw-r--r-- | page/render.go | 61 | ||||
| -rw-r--r-- | page/renderJson.go | 77 | ||||
| -rw-r--r-- | page/renderMarkdown.go | 32 |
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) } |
