Golang中的服务器头中间件

时间:2014-08-13 17:07:12

标签: http go http-headers

我正在尝试在每个响应中设置服务器标头。我正在尝试使用Middleware for Gin来实现这一目标。但是,出于某种原因,这不会设置标头。到目前为止,我已经尝试调试这个,我无法理解为什么这不起作用。可能我在这里遗漏了一些东西。

这是代码

package main

import "fmt"
import "github.com/gin-gonic/gin"

const SERVER_INFO = "Some-Play-Server"

type ServerHeader struct {
    gin.ResponseWriter
    ServerInfo string
}

func (w *ServerHeader) Write(data []byte) (int, error) {
    if w.Header().Get("Server") == "" {
        w.Header().Add("Server", w.ServerInfo)
    }

    return w.ResponseWriter.Write(data)
}

func InitServerHeader() gin.HandlerFunc {
    return func(c *gin.Context) {
        writer := &ServerHeader{c.Writer, SERVER_INFO}
        c.Writer = writer
        c.Next()
    }
}

func main() {
    mux := gin.Default()
    mux.Use(InitServerHeader())
    mux.GET("/", func(c *gin.Context) {
        c.String(200, "OK")
    })

    fmt.Println("Server Listening on 0.0.0.0:8080")
    mux.Run(":8080")
}

而且,这是测试输出

❯ curl -v http://localhost:8080/
* About to connect() to localhost port 8080 (#0)
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8080
> Accept: */*
> 
< HTTP/1.1 200 OK
< Content-Type: text/plain
< Date: Wed, 13 Aug 2014 16:54:21 GMT
< Content-Length: 2
< 
OK

4 个答案:

答案 0 :(得分:3)

我不熟悉杜松子酒,但是使用内置的http服务器,这样做相当简单:

const SERVER_INFO = "Some-Play-Server"
var extra = map[string]string{
    "Server": SERVER_INFO,
}

func HeaderSetter(fn func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
    return func(rw http.ResponseWriter, req *http.Request) {
        for k, v := range extra {
            rw.Header().Set(k, v)
        }
        fn(rw, req)
    }
}

func main() {
    fn := func(rw http.ResponseWriter, req *http.Request) {
        io.WriteString(rw, "Hello: "+req.URL.String()+"\n")
    }
    http.HandleFunc("/", HeaderSetter(fn))
    log.Panic(http.ListenAndServe(":9020", nil))
}

@elithrar在评论中提到的另一种方法是返回http.Handler

func HeaderSetter(fn http.Handler) http.Handler {
    return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
        for k, v := range extra {
            rw.Header().Set(k, v)
        }
        fn(rw, req)
    })
}

playground

答案 1 :(得分:3)

这里是Gin的创建者:不要覆盖c.Writer,这是太多的开销和不必要的复杂性。如果您想支持透明的gzip压缩或缓存,请写入作者(请参阅gzip中间件)。如果您想添加标题,请执行以下操作:

func main() {
    mux := gin.Default()
    mux.Use(serverHeader)
    mux.GET("/", func(c *gin.Context) {
        c.String(200, "OK")
    })    
    mux.Run(":8080")
}

func serverHeader(c *gin.Context) {
    // shortcut for c.Writer.Header().Set("Server", "Some-Play-Server")
    c.Header("Server", "Some-Play-Server")
}

完成!由于它作为全局中间件附加,所有响应都将包括Server头,即使在提供静态文件时也是如此!

答案 2 :(得分:2)

你不必这样做。 你必须这样做:

func main() {
    mux := gin.Default()
    mux.Use(func(c *gin.Context) {
        c.Writer.Header().Set("Server", "Some-Play-Server")
    })

    mux.GET("/", func(c *gin.Context) {
        c.String(200, "OK")
    })    
    mux.Run(":8080")
}

另外,查看最后一个版本(开发分支),我们对它进行了很多改进。现在,gin会自动将调用推迟到WriteHeader(),因此您不必担心。

答案 3 :(得分:1)

你没有使用正确的方法..

package main

import "fmt"
import "github.com/gin-gonic/gin"

const SERVER_INFO = "Some-Play-Server"

type ServerHeader struct {
    gin.ResponseWriter
    ServerInfo string
}

func (w *ServerHeader) WriteHeader(code int) {
    if w.Header().Get("Server") == "" {
        w.Header().Add("Server", w.ServerInfo)
    }

    w.ResponseWriter.WriteHeader(code)
}

func InitServerHeader() gin.HandlerFunc {
    return func(c *gin.Context) {
        writer := &ServerHeader{c.Writer, SERVER_INFO}
        c.Writer = writer
        c.Next()
    }
}

func main() {
    mux := gin.Default()
    mux.Use(InitServerHeader())
    mux.GET("/", func(c *gin.Context) {
        c.String(200, "OK")
    })

    fmt.Println("Server Listening on 0.0.0.0:8080")
    mux.Run(":8080")
}

这是输出

$ curl -v 'http://localhost:8080/'
* About to connect() to localhost port 8080 (#0)
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8080
> Accept: */*
> 
< HTTP/1.1 200 OK
< Content-Type: text/plain
< Server: Some-Play-Server
< Date: Thu, 14 Aug 2014 00:41:27 GMT
< Content-Length: 2
< 
OK