在http.FileServer上记录404错误。

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

Log 404 on http.FileServer

问题

我正在使用http.FileServerdirPath提供JPEG图像:

http.Handle("/o/", http.StripPrefix(
    path.Join("/o", dirPath), http.FileServer(http.Dir(dirPath))))

我不明白的是如何在请求不存在的文件时进行日志记录。当我使用浏览器发出请求时,我可以看到http.FileServer返回404页面未找到,但在服务器控制台上却没有显示。

英文:

I'm serving jpeg images from dirPath using http.FileServer with:

http.Handle("/o/", http.StripPrefix(
    path.Join("/o", dirPath), http.FileServer(http.Dir(dirPath))))

What I don't understand is how to log when a request is made for a file that does not exist. I can see http.FileServer returning 404 page not found when I make a request with the browser, but not on the server console.

答案1

得分: 12

http.StripPrefix()http.FileServer()返回的http.Handler不会记录HTTP 404错误。您需要扩展它们的功能以实现您想要的效果。

我们可以将http.StripPrefix()http.FileServer()返回的http.Handler值包装在另一个http.Handlerhttp.HandlerFunc中。一旦包装了处理程序,当然要注册包装器。

包装器的实现将简单地调用被包装的处理程序,一旦它返回,就可以检查HTTP响应状态码。如果是错误(或特定的HTTP 404 Not Found),可以适当地记录它。

问题是http.ResponseWriter不支持读取响应状态码。我们可以做的是还包装http.ResponseWriter,当写入状态码时,我们将存储它以供以后使用。

我们的http.ResponseWriter包装器:

type StatusRespWr struct {
	http.ResponseWriter // 我们嵌入http.ResponseWriter
	status int
}

func (w *StatusRespWr) WriteHeader(status int) {
	w.status = status // 为我们自己存储状态
	w.ResponseWriter.WriteHeader(status)
}

以及包装http.Handler

func wrapHandler(h http.Handler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		srw := &StatusRespWr{ResponseWriter: w}
		h.ServeHTTP(srw, r)
		if srw.status >= 400 { // 400+代码是错误代码
			log.Printf("在提供路径%s时出现错误状态码:%d",
				srw.status, r.RequestURI)
		}
	}
}

以及创建文件服务器、包装并注册的主要函数:

http.HandleFunc("/o/", wrapHandler(
	http.StripPrefix("/o", http.FileServer(http.Dir("/test")))))
panic(http.ListenAndServe(":8181", nil))

请求不存在文件时的示例输出:

2015/12/01 11:47:40 在提供路径/o/sub/b.txt2时出现错误状态码:404
英文:

The http.Handlers returned by http.StripPrefix() and http.FileServer() do not log HTTP 404 errors. You have to extend their functionality in order to achieve what you want.

We can wrap the http.Handler value returned by http.StripPrefix() or http.FileServer() in another http.Handler or http.HandlerFunc. Once you wrapped the handler, register the wrapper of course.

The wrapper implementation will simply called the wrapped one, and once it returns, can inspect the HTTP response status code. If it is an error (or specifically HTTP 404 Not Found), can log it appropriately.

Problem is http.ResponseWriter does not support reading the response status code. What we can do is we also wrap the http.ResponseWriter and when status code is written, we will store it for later to be available.

Our http.ResponseWriter wrapper:

type StatusRespWr struct {
	http.ResponseWriter // We embed http.ResponseWriter
	status int
}

func (w *StatusRespWr) WriteHeader(status int) {
	w.status = status // Store the status for our own use
	w.ResponseWriter.WriteHeader(status)
}

And wrapping the http.Handler:

func wrapHandler(h http.Handler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		srw := &StatusRespWr{ResponseWriter: w}
		h.ServeHTTP(srw, r)
		if srw.status >= 400 { // 400+ codes are the error codes
			log.Printf("Error status code: %d when serving path: %s",
				srw.status, r.RequestURI)
		}
	}
}

And the main function creating a file server, wrapping it and registering it:

http.HandleFunc("/o/", wrapHandler(
	http.StripPrefix("/o", http.FileServer(http.Dir("/test")))))
panic(http.ListenAndServe(":8181", nil))

Example output when requesting a non-existing file:

2015/12/01 11:47:40 Error status code: 404 when serving path: /o/sub/b.txt2

huangapple
  • 本文由 发表于 2015年12月1日 17:50:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/34017342.html
匿名

发表评论

匿名网友

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

确定