Description
I have a Middleware which adds the xml.Header string to every response body. As you can see in the Code Example provided this works flawlessly when the StatusCode is set to be 200. If the status Code set to something else the middleware still returns 200 in the response status. The expected behaviour should be the Status code of the one set by c.XML.
I nailed down the Problem to the function:
func (w *responseWriter) WriteHeader(code int) {
if code > 0 && w.status != code {
if w.Written() {
debugPrint("[WARNING] Headers were already written. Wanted to override status code %d with %d", w.status, code)
return
}
w.status = code
}
}
I want to override the response header. I accedently set the ResponseHeader when writing to the response body befor calling c.Next(). Currently I don't see another solution to prepend the xml.Header-string to the body than my solution. But the behaviour of the response status code is an unexpected side behaviour I am trying to solve.
How to reproduce
package main
import (
"encoding/xml"
"github.com/gin-gonic/gin"
"log"
"net/http"
)
func Pong(c *gin.Context) {
c.XML(http.StatusOK, gin.H{"message": "ping"})
}
func PingBadRequest(c *gin.Context) {
c.XML(http.StatusBadRequest, gin.H{"message": "some error"})
}
func CustomMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// add xml.Header in front of response body
if c.NegotiateFormat(gin.MIMEXML) == gin.MIMEXML {
if _, err := c.Writer.Write([]byte(xml.Header)); err != nil {
log.Fatalln("Failed: " + err.Error())
}
}
c.Next()
}
}
func main() {
r := gin.Default()
r.Use(CustomMiddleware())
// Route which always returns 200
r.GET("/pong", Pong)
// Route which always returns 400
r.GET("/ping", PingBadRequest)
r.Run("localhost:8081")
}
Expectations
$ curl -i localhost:8081/ping
HTTP/1.1 400 OK
Date: Wed, 24 May 2023 09:08:30 GMT
Content-Length: 79
Content-Type: text/xml; charset=utf-8
<?xml version="1.0" encoding="UTF-8"?>
<map><message>some error</message></map>
Actual result
$ curl -i localhost:8081/ping
HTTP/1.1 200 OK
Date: Wed, 24 May 2023 09:08:30 GMT
Content-Length: 79
Content-Type: text/xml; charset=utf-8
<?xml version="1.0" encoding="UTF-8"?>
<map><message>some error</message></map>
Environment
- go version: 1.19.6
- gin version (or commit ref): 1.9.0
- operating system: Windows
Comment From: bestgopher
Beacuse the Write
will call w.WriteHeaderNow()
, and will write the default status code 200. Then w.Written
will return true, and not overwrite the http code.