Gorilla mux,最好的“捕获”响应代码的方法是什么?

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

Gorilla mux, best way to 'catch' response codes

问题

我正在使用Gorilla mux进行路由。现在我的应用程序运行良好,我想找到一种方法将所有的响应代码记录到-statds(例如)。我找到了这个包:https://godoc.org/github.com/gorilla/handlers#LoggingHandler

它允许我将所有的响应输出为Apache格式。虽然这很好,但并不完全符合我的要求。我只想"提取"响应状态并将它们发送到statds。那么实现这个的最佳/最简单的方法是什么?

package main

import (
	"log"
	"net/http"
	"os"

	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
	"github.com/rogierlommers/mux-status-handler/articles"
	"github.com/rogierlommers/mux-status-handler/users"
)

func main() {
	r := mux.NewRouter()
	r.HandleFunc("/products", articles.Handler)
	r.HandleFunc("/users", users.Handler)

	loggedRouter := handlers.LoggingHandler(os.Stdout, r)
	log.Println("listening on 8080")
	http.ListenAndServe(":8080", loggedRouter)
}

上面的代码给出了这个输出:

Gorilla mux,最好的“捕获”响应代码的方法是什么?

所以我正在寻找类似的东西,但是不是将Apache访问日志输出到stdout,而是希望能够"对响应代码做些什么"。我还创建了一个包含示例代码的简单存储库,你可以在这里找到它。

英文:

I'm using Gorilla mux for all my routing. Now my app is working fine, I want to find a way to log all my response codes to -for example- statds. I have found this package: https://godoc.org/github.com/gorilla/handlers#LoggingHandler

Which allows me to output all responses into apache format. Although this is nice, it's not 100% what I want. I just want to extract the response statusses and send them to statds. Now what's the best/easiest way to achieve this?

package main

import (
	"log"
	"net/http"
	"os"

	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
	"github.com/rogierlommers/mux-status-handler/articles"
	"github.com/rogierlommers/mux-status-handler/users"
)

func main() {
	r := mux.NewRouter()
	r.HandleFunc("/products", articles.Handler)
	r.HandleFunc("/users", users.Handler)

	loggedRouter := handlers.LoggingHandler(os.Stdout, r)
	log.Println("listening on 8080")
	http.ListenAndServe(":8080", loggedRouter)
}

Above code gives me this:

Gorilla mux,最好的“捕获”响应代码的方法是什么?

So I'm looking for something similar, but instead of outputting the Apache access logs to stdout, I would like to be able to "do something" with the response code. I have also created a simple repo which contains my sample code. You can find it here.

答案1

得分: 7

我找到了Tim Andersson的这篇有用的博客文章。首先,他构建了一个满足接口要求的新结构体:

type loggingResponseWriter struct {
    http.ResponseWriter
    statusCode int
}

func NewLoggingResponseWriter(w http.ResponseWriter) *loggingResponseWriter {
    return &loggingResponseWriter{w, http.StatusOK}
}

func (lrw *loggingResponseWriter) WriteHeader(code int) {
    lrw.statusCode = code
    lrw.ResponseWriter.WriteHeader(code)
}

然后,他将其用作包装器(或中间件):

func wrapHandlerWithLogging(wrappedHandler http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
        log.Printf("--> %s %s", req.Method, req.URL.Path)

        lrw := NewLoggingResponseWriter(w)
        wrappedHandler.ServeHTTP(lrw, req)

        statusCode := lrw.statusCode
        log.Printf("<-- %d %s", statusCode, http.StatusText(statusCode))
    })
}

这是他的博客文章链接

英文:

I found this useful Blog post from Tim Andersson.
First he builds a new struct that satisfies the interface:

type loggingResponseWriter struct {
    http.ResponseWriter
    statusCode int
}

func NewLoggingResponseWriter(w http.ResponseWriter) *loggingResponseWriter {
    return &amp;loggingResponseWriter{w, http.StatusOK}
}

func (lrw *loggingResponseWriter) WriteHeader(code int) {
    lrw.statusCode = code
    lrw.ResponseWriter.WriteHeader(code)
}

Then he's using it as a wrapper (or middleware):

func wrapHandlerWithLogging(wrappedHandler http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
        log.Printf(&quot;--&gt; %s %s&quot;, req.Method, req.URL.Path)

        lrw := NewLoggingResponseWriter(w)
        wrappedHandler.ServeHTTP(lrw, req)

        statusCode := lrw.statusCode
        log.Printf(&quot;&lt;-- %d %s&quot;, statusCode, http.StatusText(statusCode))
    })
}

答案2

得分: 0

这是使用violetear制作的示例代码,可能可以给你关于如何处理处理程序中的状态码的提示:

package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/nbari/violetear"
)

func handleGET(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("I handle GET requests\n"))
	// 在这里可以处理状态码
	cw := w.(*violetear.ResponseWriter)
	fmt.Printf("状态码是:%d\n", cw.Status())
}

func main() {
	router := violetear.New()
	router.HandleFunc("/", handleGET, "GET")
	log.Fatal(http.ListenAndServe(":8080", router))
}

通过使用cw := w.(*violetear.ResponseWriter),你可以访问violetear.ResponseWriter,通过cw.Status()方法获取状态码。

英文:

This is how it can be made with violetear, probably can give you a hint about how to deal with the status code within the handler:

<!-- language: go -->

package main

import (
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;net/http&quot;

	&quot;github.com/nbari/violetear&quot;
)

func handleGET(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte(&quot;I handle GET requests\n&quot;))
	// do anything here with the Status code
	cw := w.(*violetear.ResponseWriter)
	fmt.Printf(&quot;The status code is: %d\n&quot;, cw.Status())
}

func main() {
	router := violetear.New()
	router.HandleFunc(&quot;/&quot;, handleGET, &quot;GET&quot;)
	log.Fatal(http.ListenAndServe(&quot;:8080&quot;, router))
}

By using:

cw := w.(*violetear.ResponseWriter)

You can access the violetear.ResponseWriter which exposes the status code by using cw.Status()

答案3

得分: -1

你可以编写自己的中间件,这是一个非常基本的示例:

package main

import (
	"log"
	"net/http"

	"github.com/gorilla/mux"
	"github.com/rogierlommers/mux-status-handler/articles"
	"github.com/rogierlommers/mux-status-handler/users"
)

// middleWare ...
func middleWare(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// 目前,这个中间件只是像 "github.com/gorilla/handlers" 一样记录日志
		log.Printf("%s %s %s", r.RemoteAddr, r.Method, r.URL)
		// 但是由于这是中间件,你可以让它做其他事情
		// 例如,验证用户、写入文件、重定向、处理恐慌等等
		// 如果你想要将日志记录到statds,可以添加相应的代码,如果不需要log.Printf,可以将其删除

		handler.ServeHTTP(w, r)
	})
}

func main() {
	r := mux.NewRouter()
	r.HandleFunc("/products", articles.Handler)
	r.HandleFunc("/users", users.Handler)

	log.Println("listening on 8080")
	http.ListenAndServe(":8080", middleWare(r))
}

希望对你有帮助!

英文:

You can write your own middleware, here's a very base example

package main

import (
	&quot;log&quot;
	&quot;net/http&quot;

	&quot;github.com/gorilla/mux&quot;
	&quot;github.com/rogierlommers/mux-status-handler/articles&quot;
	&quot;github.com/rogierlommers/mux-status-handler/users&quot;
)

// middleWare ...
func middleWare(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// right not all this does is log like
		// &quot;github.com/gorilla/handlers&quot;
		log.Printf(&quot;%s %s %s&quot;, r.RemoteAddr, r.Method, r.URL)
		// However since this is middleware you can have it do other things
        // Examples, auth users, write to file, redirects, handle panics, ect
		// add code to log to statds, remove log.Printf if you want


		handler.ServeHTTP(w, r)
	})
}

func main() {
	r := mux.NewRouter()
	r.HandleFunc(&quot;/products&quot;, articles.Handler)
	r.HandleFunc(&quot;/users&quot;, users.Handler)

	log.Println(&quot;listening on 8080&quot;)
	http.ListenAndServe(&quot;:8080&quot;, middleWare(r))
}

huangapple
  • 本文由 发表于 2017年2月10日 22:48:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/42162211.html
匿名

发表评论

匿名网友

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

确定