I originally wrote this up as a GitHub issue, but I want to make sure I'm
not missing anything by emailing this list first.

It would be nice if it was easier to rewrite `html/template` files but the
current tools (`html/template` and `x/net/html`) seem to have a gap between
them. Maybe there's a way to do this that I've missed, so let me explain
the problems I wanted to solve in detail.

I'm trying to make it easy to support CSP inline hashing in my templates
without nagging users and requiring them to remember to use some custom
funcs instead of the usual HTML. It'd also be nice to have form-based CSRF
protection which would be implemented in a similar way. I'm sure there are
other similar rewrites, but these security-focused ones were the first I've
run into.

Both CSP inline hashing and form-based CSRF protection involve a developer
adding additional attributes or elements to a template. In the CSP inline
hashing case, it's an attribute or nonce added `script` tags. In form-based
CSRF protection, it can be a hidden `input` that sends up a per-request
token inside a `form` tag.

It would be nice to be able to, at parse time, not execution time, pull
apart a `html/template` template, inspect it for the relevant tags, and
then change the template for the user instead of returning an error if they
forgot the important elements. At parse time, the code has all the data it
needs to adjust the template. Similar to why `gofmt` is capable of
rewriting a file, not just telling a developer how to adjust the file,
adjusting a template automatically instead of telling them they made an
error would a much nicer experience for the developer.

In the form-based CSRF case, the template rewrite would be adding a `input`
tag that calls a template func (or struct value) that has the token data.
In the CSP inline hashing case, the rewrite would be detecting if the
`script` tag contained only static information and adding the hash
automatically, or returning an error if the developer needs to get involved
(usually, to handle the case of requesting javascript files from elsewhere
on the web).

However, `html/template` only has `text/template/parse` as its AST which
doesn't suffice for working at the level of HTML semantics. Folks have
offered up `x/net/html`'s `ParseFragment` as a solution but that doesn't
work well.

One problem is that `x/net/html`'s `ParseFragment` makes it difficult to
render exactly back what was in a template. Without providing a context
`*html.Node`, you'll get back a tree with additional bogus nodes added
around the outside. This doesn't work well because rewriting code may need
to behave differently depending on what context `*html.Node` is in play
instead of guessing that all templates are in `body` or whatever. But
calculating that context `*html.Node` is difficult since a template can be
loaded from other templates. That would involve writing similar template
loading code to what is already inside `text/template`.

A second problem since some of those templates will be called in different
escaping contexts, folks using `ParseFragment` have to re-do the escape
context code in `html/template` within `x/net/html`'s AST.

I haven't found a way to make my templates better without requiring the
developer to handle more of what would otherwise be easily automated
problems. Is there an obvious solution I'm missing that doesn't involve
giving up context escaping and the other goodies by using an alternate
templating library?

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to