英文:
How to log http server errors in golang?
问题
我正在尝试捕获和记录发生在URL参数未正确编码时的HTTP错误400。
我的服务器实现如下:
router := http.NewServeMux()
router.HandleFunc("/", requestHandler)
s := &http.Server{
Addr: ":8080",
Handler: router,
ErrorLog: myLogger,
}
log.Fatal(s.ListenAndServe())
请求从未到达requestHandler
,并且设置ErrorLog: myLogger
没有任何影响。
英文:
I'm trying to catch and log http error 400 that happens when url params are not encoded properly.
My server implementation looks like:
router := http.NewServeMux()
router.HandleFunc("/", requestHandler)
s := &http.Server{
Addr: ":8080",
Handler: router,
ErrorLog: myLogger,
}
log.Fatal(s.ListenAndServe())
The request never reaches requestHandler
, and having ErrorLog: myLogger
makes no difference.
答案1
得分: 8
你需要创建一个自定义的包装器(Wrapper),用于记录请求处理程序的状态码,并在请求调用处理完成后进行检查。
注意如何将主路由器本身包装起来,使用 WrapHandler(router)
。
package main
import (
"log"
"net/http"
)
type LogRecord struct {
http.ResponseWriter
status int
}
func (r *LogRecord) Write(p []byte) (int, error) {
return r.ResponseWriter.Write(p)
}
func (r *LogRecord) WriteHeader(status int) {
r.status = status
r.ResponseWriter.WriteHeader(status)
}
func WrapHandler(f http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
record := &LogRecord{
ResponseWriter: w,
}
f.ServeHTTP(record, r)
log.Println("Bad Request", record.status)
if record.status == http.StatusBadRequest {
log.Println("Bad Request", r)
}
}
}
func main() {
router := http.NewServeMux()
s := &http.Server{
Addr: ":8080",
Handler: WrapHandler(router),
}
log.Fatal(s.ListenAndServe())
}
这段代码创建了一个名为 LogRecord
的结构体,它包含了一个 http.ResponseWriter
和一个 status
字段。LogRecord
结构体实现了 Write
和 WriteHeader
方法,用于记录状态码。
WrapHandler
函数接受一个 http.Handler
参数,并返回一个 http.HandlerFunc
。在这个函数内部,我们创建了一个 LogRecord
实例,并将其作为参数传递给原始的处理程序 f.ServeHTTP
。然后,我们检查记录的状态码,并根据需要进行日志记录。
在 main
函数中,我们创建了一个新的路由器 router
,并将其作为参数传递给 WrapHandler
函数,然后将返回的处理程序设置为 http.Server
的处理程序。最后,我们使用 s.ListenAndServe()
启动服务器。
这段代码的作用是在处理请求时记录状态码,并在状态码为 http.StatusBadRequest
时进行额外的日志记录。
英文:
You need to create a custom Wrapper around the requestHandler that records the StatusCode
and inspects it after the requestCall has been processed.
Notice how we wrap the main router itself. with WrapHandler(router)
package main
import (
"log"
"net/http"
)
type LogRecord struct {
http.ResponseWriter
status int
}
func (r *LogRecord) Write(p []byte) (int, error) {
return r.ResponseWriter.Write(p)
}
func (r *LogRecord) WriteHeader(status int) {
r.status = status
r.ResponseWriter.WriteHeader(status)
}
func WrapHandler(f http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
record := &LogRecord{
ResponseWriter: w,
}
f.ServeHTTP(record, r)
log.Println("Bad Request ", record.status)
if record.status == http.StatusBadRequest {
log.Println("Bad Request ", r)
}
}
}
func main() {
router := http.NewServeMux()
s := &http.Server{
Addr: ":8080",
Handler: WrapHandler(router),
}
log.Fatal(s.ListenAndServe())
}
答案2
得分: 1
只是为了其他人找到这个问题,你不能使用Go中的net/http拦截400错误。有关更多详细信息,请参阅此答案:
英文:
Just for anyone else finding this, you can't intercept a 400 error using net/http in Go. See this answer for more details:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论