如何在Golang中记录HTTP服务器错误?

huangapple go评论79阅读模式
英文:

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 结构体实现了 WriteWriteHeader 方法,用于记录状态码。

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错误。有关更多详细信息,请参阅此答案:

https://stackoverflow.com/questions/45802492/how-can-i-customize-golang-http-400-responses-for-parse-errors/45802962#45802962

英文:

Just for anyone else finding this, you can't intercept a 400 error using net/http in Go. See this answer for more details:

https://stackoverflow.com/questions/45802492/how-can-i-customize-golang-http-400-responses-for-parse-errors/45802962#45802962

huangapple
  • 本文由 发表于 2014年8月23日 06:25:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/25456390.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定