Gin: how do i get response body in after router middleware?

Created on 21 May 2018  ·  7Comments  ·  Source: gin-gonic/gin

rt

r := gin.Default()
r.GET("/test",handler,middleware())

func middleware() gin.HandlerFunc{
// get response body in here;
...
}
question

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"

"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()
}

All 7 comments

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.
image

And WriteString calls sw.WriteString
image

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)
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

mdnight picture mdnight  ·  3Comments

ccaza picture ccaza  ·  3Comments

oryband picture oryband  ·  3Comments

ghost picture ghost  ·  3Comments

mastrolinux picture mastrolinux  ·  3Comments