@marcel91200 / caddy Mirror · read-only / commits / 31d75acc
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 13, 01:45 UTC

templates: Add `readFile` action that does not evaluate templates (#5553)

* Create an includeRaw template function to include a file without parsing it as a template. Some formatting fixes * Rename to readFile, various docs adjustments --------- Co-authored-by: Francis Lavoie <lavofr@gmail.com>

kassienull committed May 26, 2023 at 12:16 UTC 31d75acc9ca5529c300be1ff46ae2dd799fbf9d8
2 files changed +49 -8
modules/caddyhttp/templates/templates.go
+29 -6
@@ -88,7 +88,11 @@ func init() {
88 //
89 // ##### `httpInclude`
90 //
91 -// Includes the contents of another file by making a virtual HTTP request (also known as a sub-request). The URI path must exist on the same virtual server because the request does not use sockets; instead, the request is crafted in memory and the handler is invoked directly for increased efficiency.
91 +// Includes the contents of another file, and renders it in-place,
92 +// by making a virtual HTTP request (also known as a sub-request).
93 +// The URI path must exist on the same virtual server because the
94 +// request does not use sockets; instead, the request is crafted in
95 +// memory and the handler is invoked directly for increased efficiency.
96 //
97 // ```
98 // {{httpInclude "/foo/bar?q=val"}}
@@ -96,7 +100,13 @@ func init() {
100 //
101 // ##### `import`
102 //
99 -// Imports the contents of another file and adds any template definitions to the template stack. If there are no defitions, the filepath will be the defition name. Any {{ define }} blocks will be accessible by {{ template }} or {{ block }}. Imports must happen before the template or block action is called
103 +// Reads and returns the contents of another file, and parses it
104 +// as a template, adding any template definitions to the template
105 +// stack. If there are no definitions, the filepath will be the
106 +// definition name. Any {{ define }} blocks will be accessible by
107 +// {{ template }} or {{ block }}. Imports must happen before the
108 +// template or block action is called. Note that the contents are
109 +// NOT escaped, so you should only import trusted template files.
110 //
111 // **filename.html**
112 // ```
@@ -113,13 +123,26 @@ func init() {
123 //
124 // ##### `include`
125 //
116 -// Includes the contents of another file and renders in-place. Optionally can pass key-value pairs as arguments to be accessed by the included file.
126 +// Includes the contents of another file, rendering it in-place.
127 +// Optionally can pass key-value pairs as arguments to be accessed
128 +// by the included file. Note that the contents are NOT escaped,
129 +// so you should only include trusted template files.
130 //
131 // ```
132 // {{include "path/to/file.html"}} // no arguments
133 // {{include "path/to/file.html" "arg1" 2 "value 3"}} // with arguments
134 // ```
135 //
136 +// ##### `readFile`
137 +//
138 +// Reads and returns the contents of another file, as-is.
139 +// Note that the contents are NOT escaped, so you should
140 +// only read trusted files.
141 +//
142 +// ```
143 +// {{readFile "path/to/file.html"}}
144 +// ```
145 +//
146 // ##### `listFiles`
147 //
148 // Returns a list of the files in the given directory, which is relative to the template context's file root.
@@ -130,10 +153,10 @@ func init() {
153 //
154 // ##### `markdown`
155 //
133 -// Renders the given Markdown text as HTML. This uses the
156 +// Renders the given Markdown text as HTML and returns it. This uses the
157 // [Goldmark](https://github.com/yuin/goldmark) library,
135 -// which is CommonMark compliant. It also has these plugins
136 -// enabled: Github Flavored Markdown, Footnote and syntax
158 +// which is CommonMark compliant. It also has these extensions
159 +// enabled: Github Flavored Markdown, Footnote, and syntax
160 // highlighting provided by [Chroma](https://github.com/alecthomas/chroma).
161 //
162 // ```
modules/caddyhttp/templates/tplcontext.go
+20 -2
@@ -30,7 +30,7 @@ import (
30 "time"
31
32 "github.com/Masterminds/sprig/v3"
33 - "github.com/alecthomas/chroma/v2/formatters/html"
33 + chromahtml "github.com/alecthomas/chroma/v2/formatters/html"
34 "github.com/caddyserver/caddy/v2"
35 "github.com/caddyserver/caddy/v2/modules/caddyhttp"
36 "github.com/dustin/go-humanize"
@@ -74,6 +74,7 @@ func (c *TemplateContext) NewTemplate(tplName string) *template.Template {
74 // add our own library
75 c.tpl.Funcs(template.FuncMap{
76 "include": c.funcInclude,
77 + "readFile": c.funcReadFile,
78 "import": c.funcImport,
79 "httpInclude": c.funcHTTPInclude,
80 "stripHTML": c.funcStripHTML,
@@ -123,6 +124,23 @@ func (c TemplateContext) funcInclude(filename string, args ...any) (string, erro
124 return bodyBuf.String(), nil
125 }
126
127 +// funcReadFile returns the contents of a filename relative to the site root.
128 +// Note that included files are NOT escaped, so you should only include
129 +// trusted files. If it is not trusted, be sure to use escaping functions
130 +// in your template.
131 +func (c TemplateContext) funcReadFile(filename string) (string, error) {
132 + bodyBuf := bufPool.Get().(*bytes.Buffer)
133 + bodyBuf.Reset()
134 + defer bufPool.Put(bodyBuf)
135 +
136 + err := c.readFileToBuffer(filename, bodyBuf)
137 + if err != nil {
138 + return "", err
139 + }
140 +
141 + return bodyBuf.String(), nil
142 +}
143 +
144 // readFileToBuffer reads a file into a buffer
145 func (c TemplateContext) readFileToBuffer(filename string, bodyBuf *bytes.Buffer) error {
146 if c.Root == nil {
@@ -315,7 +333,7 @@ func (TemplateContext) funcMarkdown(input any) (string, error) {
333 extension.Footnote,
334 highlighting.NewHighlighting(
335 highlighting.WithFormatOptions(
318 - html.WithClasses(true),
336 + chromahtml.WithClasses(true),
337 ),
338 ),
339 ),