防止在模板中转义正斜杠 [英] Prevent escaping forward slashes in templates
问题描述
我正在努力将我的一个宠物项目从Python转换为Go,以帮助我熟悉该语言。我目前面临的一个问题是它正在逃避我的正斜杠。所以它会收到一个字符串:
/ location / to / something
然后变成
%2flocation%2fto% 2fsomething
现在,只有当它在链接中时才会这样做(从我一直在阅读的内容转义是上下文的),所以这就是HTML模板中的行:
< tr>< td><< ; a href =/ file?file = {{.FullFilePath}}> {{.FileName}}< / a>< / td>< / tr>
如果可能的话,我该如何在模板或代码本身中防止它?
这就是我的模板函数的样子(是的,我知道它是黑客)
pre $ func renderTemplate(w http.ResponseWriter,tmpl字符串){
t,err:= template.ParseFiles(templates_dir +base.html,templates_dir + tmpl)
if err!= nil {
http.Error(w,err.Error(),http.StatusInternalServerError)
返回
}
如果tmpl ==view.html{
err = t.Execute( w,FileList)
} else {
err = t.Execute(w,nil)
}
if err!= nil {
http.Error(w, err.Error(),http.StatusInternalServerError)
}
}
作为 .FullFilePath
的值,传递一个 template.URL
而不是 string
,它会告诉 html / template
包不要转义它。
例如:
func main(){
t:= template.Must(template.New()。Parse(templ))
m:= map [string] interface {} {
FileName:something.txt,
FileFullPath:template.URL(/ location / to / something) ,
}
if err:= t.Execute(os.Stdout,m); err!= nil {
panic(err)
}
}
const templ =`< tr>< td>< a href =/文件?文件= {{.FileFullPath}}> {{.FileName}}< / a>< / td>< / tr>`
输出(尝试在 Go Playground ):
< tr>< td>< a href =/ file?file = /位置/到/东西> something.txt< / A>< / TD>< / TR>
请注意,即使正斜杠 如果您打算从URL参数获取服务器端的此文件路径,那么 但是要知道,通过这样做,您将失去防止代码注入URL的安全性。如果你是提供价值的人,并且你知道他们是安全的,那么没有问题。但是,如果数据来自用户输入,例如,不要这样做。 另外请注意,如果您传递整个URL(而不仅仅是它的一部分),它可以在不使用 另外请注意,我认为推荐的方法是将文件路径作为URL路径的一部分,而不是作为参数的值,所以您应该像这样创建urls: 映射您的处理程序(提供文件内容,请参阅此答案为例)到 在去游乐场试试这个。 同样非常重要:永远不要在处理函数中解析模板!详情请看: 使用模板时花费太多时间。包在golang中为客户端生成一个动态网页 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: and it then becomes 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: 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)
As the value of For example: Output (try it on the Go Playground): Note that even though forward slashes If you plan to acquire this file path at the server side from URL parameters, then what the 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 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 Try this on the Go Playground. Also very important: never parse templates in your handler functions! For details see: 这篇关于防止在模板中转义正斜杠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! /
是允许在URL中,模板
包仍然对其进行编码的原因是因为它分析了URL并且发现要包含的值是URL参数的值( file = XXX
),所以它也编码了斜线(这样你传入的所有东西都将成为文件的一部分$ c
$ b 模板 code> package does not the correct and proper way。
template.URL
的情况下工作(在 Go Playground ):
func main(){$ b $:bt:= template.Must template.New()。Parse(templ))
$ bm:bm:= map [string] interface {} {
FileName:something.txt,
FileURL:/ file?file = / location / to / something,
}
if err:= t.Execute(os.Stdout,m); err!= nil {
panic(err)
}
}
const templ =`< tr>< td>< a href ={ {.FileURL}}> {{.FileName}}< / a>< / td>< / tr>`
/ file / location / to / something
/ file /
模式,当它匹配并且你的处理程序被调用时,切断 / file /
前缀从路径 r.URL.Path
,其余的将是完整的文件路径。如果你选择这个,你也不需要 template.URL
转换(因为你包含的值不再是URL参数的值):
$ p $ func main(){
t:= template.Must(template.New()。Parse(templ))
m:= map [string] interface {} {
FileName:something.txt,
FileFullPath:/ location / to / something,
}
if err:= t.Execute(os.Stdout,m); err!= nil {
panic(err)
}
}
const templ =`< tr>< td>< a href =/ file {{FileFullPath}}> {{.FileName}}< / a>< / td>< / tr>`
/location/to/something
%2flocation%2fto%2fsomething
<tr><td><a href="/file?file={{.FullFilePath}}">{{.FileName}}</a></td></tr>
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)
}
}
.FullFilePath
, pass a value of type template.URL
instead of string
, which will tell the html/template
package not to escape it.func main() {
t := template.Must(template.New("").Parse(templ))
m := map[string]interface{}{
"FileName": "something.txt",
"FileFullPath": template.URL("/location/to/something"),
}
if err := t.Execute(os.Stdout, m); err != nil {
panic(err)
}
}
const templ = `<tr><td><a href="/file?file={{.FileFullPath}}">{{.FileName}}</a></td></tr>`
<tr><td><a href="/file?file=/location/to/something">something.txt</a></td></tr>
/
are allowed in URLs, the reason why the template
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 the file
URL parameter).template
package does is the correct and proper way.template.URL
(try this variant on the Go Playground):func main() {
t := template.Must(template.New("").Parse(templ))
m := map[string]interface{}{
"FileName": "something.txt",
"FileURL": "/file?file=/location/to/something",
}
if err := t.Execute(os.Stdout, m); err != nil {
panic(err)
}
}
const templ = `<tr><td><a href="{{.FileURL}}">{{.FileName}}</a></td></tr>`
/file/location/to/something
/file/
pattern, and when it is matched and your handler is called, cut off the /file/
prefix from the path r.URL.Path
, and the rest will be the full file path. If you choose this, you also won't need the template.URL
conversion (because the value you include is not a value of a URL parameter anymore):func main() {
t := template.Must(template.New("").Parse(templ))
m := map[string]interface{}{
"FileName": "something.txt",
"FileFullPath": "/location/to/something",
}
if err := t.Execute(os.Stdout, m); err != nil {
panic(err)
}
}
const templ = `<tr><td><a href="/file{{.FileFullPath}}">{{.FileName}}</a></td></tr>`