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
),