英文:
Templates break http HEAD method
问题
考虑以下代码:当我使用GET方法访问http://localhost:8080/
或http://localhost:8080/foo
时,一切都按预期工作。但是当我使用HEAD方法访问http://localhost:8080/foo
时,它可以正常工作,但是访问http://localhost:8080/
时出错(主程序退出并显示错误信息:'template: main.html:1:0: executing "main.html" at <"homeHandler">: http: request method or response status code does not allow body')。这两者之间的区别在于一个情况下使用了模板(/
),另一个情况下使用了简单的字符串(/foo
)。
在我的代码中,我广泛使用模板,所以看起来我必须显式地请求方法并返回"200"(或适当的代码)。是否有一种方法可以同时使用模板和自动处理HEAD方法?
我尝试了以下测试:curl http://localhost:8080/foo -I
(-I
用于HEAD方法)。
package main
import (
"html/template"
"log"
"net/http"
)
var (
templates *template.Template
)
// OK, HEAD + GET work fine
func fooHandler(w http.ResponseWriter, req *http.Request) {
w.Write([]byte("fooHandler"))
}
// GET works fine, HEAD results in an error:
// template: main.html:1:0: executing "main.html" at <"homeHandler">:
// http: request method or response status code does not allow body
func homeHandler(w http.ResponseWriter, req *http.Request) {
err := templates.ExecuteTemplate(w, "main.html", nil)
if err != nil {
log.Fatal(err)
}
}
func main() {
var err error
templates, err = template.ParseGlob("templates/*.html")
if err != nil {
log.Fatal("Loading template: ", err)
}
http.HandleFunc("/", homeHandler)
http.HandleFunc("/foo", fooHandler)
http.ListenAndServe(":8080", nil)
}
子目录templates
中的文件main.html
只包含字符串homeHandler
。
英文:
Consider this code: when I GET http://localhost:8080/
or http://localhost:8080/foo
everything works as expected. But when I use the HEAD http method, http://localhost:8080/foo
works but http://localhost:8080/
breaks (the main program exits and I get this error: 'template: main.html:1:0: executing "main.html" at <"homeHandler">: http: request method or response status code does not allow body'). The difference between those two is the use of the template in one case (/
) and a simple string in the other(/foo
).
In my code I use templates extensively, so it looks like I have to ask explicitly for the method and return "200" (or the appropriate code). Is there a way to have templates and the automatic handling of the HEAD method?
I have tried these to test: curl http://localhost:8080/foo -I
(-I
for the HEAD method).
package main
import (
"html/template"
"log"
"net/http"
)
var (
templates *template.Template
)
// OK, HEAD + GET work fine
func fooHandler(w http.ResponseWriter, req *http.Request) {
w.Write([]byte("fooHandler"))
}
// GET works fine, HEAD results in an error:
// template: main.html:1:0: executing "main.html" at <"homeHandler">:
// http: request method or response status code does not allow body
func homeHandler(w http.ResponseWriter, req *http.Request) {
err := templates.ExecuteTemplate(w, "main.html", nil)
if err != nil {
log.Fatal(err)
}
}
func main() {
var err error
templates, err = template.ParseGlob("templates/*.html")
if err != nil {
log.Fatal("Loading template: ", err)
}
http.HandleFunc("/", homeHandler)
http.HandleFunc("/foo", fooHandler)
http.ListenAndServe(":8080", nil)
}
The file main.html
in the subdirectory templates
is just this string: homeHandler
答案1
得分: 3
错误是自我解释的:
> 请求方法或响应状态码不允许有主体
HEAD请求只允许将HTTP头作为响应发送回来。真正的问题是为什么你能够在fooHandler
中写入主体。
编辑:
fooHandler
也不会写入任何内容,你忽略了它返回的错误,即http.ErrBodyNotAllowed
。
英文:
The error is self-explaining:
> request method or response status code does not allow body
A HEAD request only allows HTTP headers to be sent back as response.
The real question is why you are able to write to the body in fooHandler
.
EDIT:
fooHandler
won't write anything either, you are omiting the error it is returning which is http.ErrBodyNotAllowed
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论