I'm working on converting a pet project of mine from Python to Go just to help me get a bit familiar with the language. An issue I am currently facing is that it's escaping my forward slashes. So it will receive a string like:
/location/to/something
and it then becomes
%2flocation%2fto%2fsomething
Now, it's only doing this when it's in a link (from what I've been reading this escaping is contextual) so this is what the line in the HTML template looks like:
<tr><td><a href="/file?file={{.FullFilePath}}">{{.FileName}}</a></td></tr>
If possible, how can I prevent this in either the template or the code itself?
This is what my templating function looks like (yes, I know it's hackish)
func renderTemplate(w http.ResponseWriter, tmpl string) {
t, err := template.ParseFiles(templates_dir+"base.html", templates_dir+tmpl)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if tmpl == "view.html" {
err = t.Execute(w, FileList)
} else {
err = t.Execute(w, nil)
}
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
As the value of
.FullFilePath
, pass a value of typetemplate.URL
instead ofstring
, which will tell thehtml/template
package not to escape it.For example:
Output (try it on the Go Playground):
Note that even though forward slashes
/
are allowed in URLs, the reason why thetemplate
package still encodes them is because it analyses the URL and sees that the value you want to include is the value of a URL parameter (file=XXX
), and so it also encodes the slashes (so that everything you pass in will be part of the value of thefile
URL parameter).If you plan to acquire this file path at the server side from URL parameters, then what the
template
package does is the correct and proper way.But know that by doing this, you'll lose the safety that prevents code injection into URLs. If you're the one providing the values and you know they are safe, there is no problem. But if the data comes from a user input for example, never do this.
Also note that if you pass the whole URL (and not just a part of it), it will work without using
template.URL
(try this variant on the Go Playground):Also note that the recommended way in my opinion would be to include the file path as part of the URL path and not as the value of a parameter, so instead you should create urls like this:
Map your handler (which serves the file content, see this answer as an example) to the
/file/
pattern, and when it is matched and your handler is called, cut off the/file/
prefix from the pathr.URL.Path
, and the rest will be the full file path. If you choose this, you also won't need thetemplate.URL
conversion (because the value you include is not a value of a URL parameter anymore):Try this on the Go Playground.
Also very important: never parse templates in your handler functions! For details see:
It takes too much time when using "template" package to generate a dynamic web page to client in golang
OK, So the solution I've found (and please post if there's a better one) is based on an answer here.
I changed the struct I was using from:
To this:
And moved the html into the FullFilePath name, and then placed that in template.HTML so each FullFilePath name I was generating was done like so:
And my template file line was changed to this: