mirror of https://github.com/caddyserver/caddy.git
templates: Use text/template; add experimental notice to docs
Using html/template.HTML like we were doing before caused nested include to be HTML-escaped, which breaks sites. Now we do not escape any of the output; template input is usually trusted, and if it's not, users should employ escaping actions within their templates to keep it safe. The docs already said this.
This commit is contained in:
parent
145aebbba5
commit
437d5095a6
|
@ -33,6 +33,8 @@ func init() {
|
|||
// The syntax is documented in the Go standard library's
|
||||
// [text/template package](https://golang.org/pkg/text/template/).
|
||||
//
|
||||
// ⚠️ Template functions/actions are still experimental, so they are subject to change.
|
||||
//
|
||||
// [All Sprig functions](https://masterminds.github.io/sprig/) are supported.
|
||||
//
|
||||
// In addition to the standard functions and Sprig functions, Caddy adds
|
||||
|
|
|
@ -17,7 +17,6 @@ package templates
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
|
@ -25,6 +24,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"text/template"
|
||||
|
||||
"github.com/Masterminds/sprig/v3"
|
||||
"github.com/alecthomas/chroma/formatters/html"
|
||||
|
@ -57,7 +57,7 @@ func (c templateContext) OriginalReq() http.Request {
|
|||
// Note that included files are NOT escaped, so you should only include
|
||||
// trusted files. If it is not trusted, be sure to use escaping functions
|
||||
// in your template.
|
||||
func (c templateContext) funcInclude(filename string, args ...interface{}) (template.HTML, error) {
|
||||
func (c templateContext) funcInclude(filename string, args ...interface{}) (string, error) {
|
||||
if c.Root == nil {
|
||||
return "", fmt.Errorf("root file system not specified")
|
||||
}
|
||||
|
@ -84,14 +84,14 @@ func (c templateContext) funcInclude(filename string, args ...interface{}) (temp
|
|||
return "", err
|
||||
}
|
||||
|
||||
return template.HTML(bodyBuf.String()), nil
|
||||
return bodyBuf.String(), nil
|
||||
}
|
||||
|
||||
// funcHTTPInclude returns the body of a virtual (lightweight) request
|
||||
// to the given URI on the same server. Note that included bodies
|
||||
// are NOT escaped, so you should only include trusted resources.
|
||||
// If it is not trusted, be sure to use escaping functions yourself.
|
||||
func (c templateContext) funcHTTPInclude(uri string) (template.HTML, error) {
|
||||
func (c templateContext) funcHTTPInclude(uri string) (string, error) {
|
||||
// prevent virtual request loops by counting how many levels
|
||||
// deep we are; and if we get too deep, return an error
|
||||
recursionCount := 1
|
||||
|
@ -132,7 +132,7 @@ func (c templateContext) funcHTTPInclude(uri string) (template.HTML, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
return template.HTML(buf.String()), nil
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func (c templateContext) executeTemplateInBuffer(tplName string, buf *bytes.Buffer) error {
|
||||
|
@ -231,7 +231,7 @@ func (c templateContext) funcStripHTML(s string) string {
|
|||
|
||||
// funcMarkdown renders the markdown body as HTML. The resulting
|
||||
// HTML is NOT escaped so that it can be rendered as HTML.
|
||||
func (c templateContext) funcMarkdown(input interface{}) (template.HTML, error) {
|
||||
func (c templateContext) funcMarkdown(input interface{}) (string, error) {
|
||||
inputStr := toString(input)
|
||||
|
||||
md := goldmark.New(
|
||||
|
@ -259,7 +259,7 @@ func (c templateContext) funcMarkdown(input interface{}) (template.HTML, error)
|
|||
|
||||
md.Convert([]byte(inputStr), buf)
|
||||
|
||||
return template.HTML(buf.String()), nil
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// splitFrontMatter parses front matter out from the beginning of input,
|
||||
|
@ -338,14 +338,12 @@ func toString(input interface{}) string {
|
|||
switch v := input.(type) {
|
||||
case string:
|
||||
return v
|
||||
case template.HTML:
|
||||
return string(v)
|
||||
case fmt.Stringer:
|
||||
return v.String()
|
||||
case error:
|
||||
return v.Error()
|
||||
default:
|
||||
return fmt.Sprintf("%s", input)
|
||||
return fmt.Sprintf("%v", input)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,6 +355,6 @@ var bufPool = sync.Pool{
|
|||
|
||||
// at time of writing, sprig.FuncMap() makes a copy, thus
|
||||
// involves iterating the whole map, so do it just once
|
||||
var sprigFuncMap = sprig.FuncMap()
|
||||
var sprigFuncMap = sprig.TxtFuncMap()
|
||||
|
||||
const recursionPreventionHeader = "Caddy-Templates-Include"
|
||||
|
|
|
@ -31,7 +31,6 @@ package templates
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -48,7 +47,7 @@ func TestMarkdown(t *testing.T) {
|
|||
|
||||
for i, test := range []struct {
|
||||
body string
|
||||
expect template.HTML
|
||||
expect string
|
||||
}{
|
||||
{
|
||||
body: "- str1\n- str2\n",
|
||||
|
|
Loading…
Reference in New Issue