To demonstrate this, let's create a new blog entry by adding this SQL command to your MySQL command line:
INSERT INTO `pages` (`id`, `page_guid`, `page_title`, page_content`, `page_date`)
VALUES:
(2, 'a-new-blog', 'A New Blog', 'I hope you enjoyed the last blog! Well brace yourself, because my latest blog is even <i>better</i> than the last!', '2015-04-29 02:16:19'),
Another thrilling piece of content, for sure. Note, however that we have some embedded HTML in this when we attempt to italicize the word better.
Debates about how formatting should be stored notwithstanding, this allows us to take a look at how Go's templates handle this by default. If we visit http://localhost:9500/page/a-new-blog
we'll see something similar to this:
As you can see, Go automatically sanitizes our data for output. There are a lot of very, very wise reasons to do this, which is why it's the default behavior. The biggest one, of course, is to avoid XSS and code-injection attack vectors from untrusted sources of input, such as the general users of the site and so on.
But ostensibly we are creating this content and should be considered trusted. So in order to validate this as trusted HTML, we need to change the type of template.HTML
:
type Page struct { Title string Content template.HTML Date string }
If you attempt to simply scan the resulting SQL string value into a template.HTML
you'll find the following error:
sql: Scan error on column index 1: unsupported driver -> Scan pair: []uint8 -> *template.HTML
The easiest way to work around this is to retain the string value in RawContent
and assign it back to Content
:
type Page struct { Title string RawContent string Content template.HTML Date string } err := database.QueryRow("SELECT page_title,page_content,page_date FROM pages WHERE page_guid=?", pageGUID).Scan(&thisPage.Title, &thisPage.RawContent, &thisPage.Date) thisPage.Content = template.HTML(thisPage.RawContent)
If we go run
this again, we'll see our HTML as trusted: