rt
r := gin.Default()
r.GET("/test",handler,middleware())
func middleware() gin.HandlerFunc{
// get response body in here;
...
}
what is your scenario?
I want to cache response body.
an request flow like this :
frist:before router middleware(query in cache,no found) -> controller -> after router middleware(save in cache) -> return
second: before router middleware(query in cache,founded) ->return
I think you need to replace ctx.Writer by a wrapped version, that will implement buffered write-operation
r := gin.Default()
r.GET("/test",handler,middleware())
func middleware(ctx *gin.Context) gin.HandlerFunc {
// here you need to replace ctx.Writer by your wrapper
ctx.Next()
// here you can access the data, that your wrapper saved into a buffer
}
I think you need to replace ctx.Writer by a wrapped version, that will implement buffered write-operation
r := gin.Default() r.GET("/test",handler,middleware()) func middleware(ctx *gin.Context) gin.HandlerFunc { // here you need to replace ctx.Writer by your wrapper ctx.Next() // here you can access the data, that your wrapper saved into a buffer }
The problem is how to get data from ctx, after ctx.Next() infact ;
Do you agree? @privationel
Here's a full example of using a custom response writer to capture the response body:
```go
package main
import (
"bytes"
"fmt"
"github.com/gin-gonic/gin"
)
type responseBodyWriter struct {
gin.ResponseWriter
body *bytes.Buffer
}
func (r responseBodyWriter) Write(b []byte) (int, error) {
r.body.Write(b)
return r.ResponseWriter.Write(b)
}
func logResponseBody(c *gin.Context) {
w := &responseBodyWriter{body: &bytes.Buffer{}, ResponseWriter: c.Writer}
c.Writer = w
c.Next()
fmt.Println("Response body: " + w.body.String())
}
func sayHello(c *gin.Context) {
c.JSON(200, gin.H{
"hello": "privationel",
})
}
func main() {
r := gin.Default()
r.Use(logResponseBody)
r.GET("/", sayHello)
r.Run()
}
👍
Here's a full example of using a custom response writer to capture the response body:
package main import ( "bytes" "fmt" "github.com/gin-gonic/gin" ) type responseBodyWriter struct { gin.ResponseWriter body *bytes.Buffer } func (r responseBodyWriter) Write(b []byte) (int, error) { r.body.Write(b) return r.ResponseWriter.Write(b) } func logResponseBody(c *gin.Context) { w := &responseBodyWriter{body: &bytes.Buffer{}, ResponseWriter: c.Writer} c.Writer = w c.Next() fmt.Println("Response body: " + w.body.String()) } func sayHello(c *gin.Context) { c.JSON(200, gin.H{ "hello": "privationel", }) } func main() { r := gin.Default() r.Use(logResponseBody) r.GET("/", sayHello) r.Run() }
If gin response like c.String(200, "hello world"), the code does not work.
Because text implements the Render interface by io.WriteString, see the picture in the blow.

And WriteString calls sw.WriteString

So, i think it should supplement these code:
func (r responseBodyWriter) WriteString(s string) (n int, err error) {
r.body.WriteString(s)
return r.ResponseWriter.WriteString(s)
}
Most helpful comment
Here's a full example of using a custom response writer to capture the response body:
```go
package main
import (
"bytes"
"fmt"
)
type responseBodyWriter struct {
gin.ResponseWriter
body *bytes.Buffer
}
func (r responseBodyWriter) Write(b []byte) (int, error) {
r.body.Write(b)
return r.ResponseWriter.Write(b)
}
func logResponseBody(c *gin.Context) {
w := &responseBodyWriter{body: &bytes.Buffer{}, ResponseWriter: c.Writer}
c.Writer = w
c.Next()
fmt.Println("Response body: " + w.body.String())
}
func sayHello(c *gin.Context) {
c.JSON(200, gin.H{
"hello": "privationel",
})
}
func main() {
r := gin.Default()
r.Use(logResponseBody)
r.GET("/", sayHello)
r.Run()
}