英文:
Server Header Middleware in Golang
问题
我正在尝试在每个响应中设置服务器头。我尝试使用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
英文:
I'm trying to set Server Header on every Response. I'm trying to achieve this, using a Middleware for Gin. However, this does not set the Header, for some reason. I've tried to debug this so far, and I could not understand why this should not work. Probably I'm missing something here.
Here is the code
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")
}
And, here is the Test Output
❯ 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
答案1
得分: 5
这里是Gin的创建者:请不要覆盖c.Writer,这会增加很多额外的开销和不必要的复杂性。如果你想要支持透明的gzip压缩或缓存(参见gzip中间件),才需要覆盖writer。如果你只是想要添加一个头部,可以这样做:
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) {
// 快捷方式,等同于 c.Writer.Header().Set("Server", "Some-Play-Server")
c.Header("Server", "Some-Play-Server")
}
完成!由于它作为全局中间件附加,所有的响应都会包含Server头部,即使是提供静态文件的时候也是如此!
英文:
here Gin's creator: DO NOT override the c.Writer, that's too much overhead and uneeded complexity. The writer should be overrided if you want to support transparent gzip compression or caching (see gzip middleware). If you want to add a header just do this:
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")
}
Done! since it is attached as a global middleware, all the responses will include the Server header, even when serving static files!
答案2
得分: 3
你没有使用正确的方法来实现这个。
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
英文:
You did not use the right method for that ..
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")
}
Here is the Output
$ 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
答案3
得分: 3
你不需要这样做。
你只需要这样做:
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")
}
另外,请查看最新版本(develop分支),我们对其进行了很多改进。现在gin自动推迟调用WriteHeader(),所以你不需要担心。
英文:
you do not have to do that.
You just have to do this:
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")
}
Also, check out the last version (develop branch), we improved it a lot. Now gin automatically defers the call to WriteHeader() so you do not have to worry.
答案4
得分: 2
我不熟悉gin,但是使用内置的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.ServeHTTP(rw, req)
})
}
[kbd]playground/kbd
英文:
I'm not familiar with gin, however using the built in http server it's rather trivial to do that:
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))
}
A different approach was mentioned by @elithrar in the comments is to return http.Handler
instead:
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)
})
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论