Home > Blockchain >  How to customize a response data from two handlers in single entrypoint go?
How to customize a response data from two handlers in single entrypoint go?

Time:09-05

I use echo framework in my app and i faced with issue to constuct response from two handler on single entrypoint.

There is example code

type RespObject struct {
    Message string `json:"message"`
}

func main() {
    e := echo.New()
    e.GET("/hello", handler, middle)

    e.Logger.Fatal(e.Start(":3000"))
}

func handler(c echo.Context) error {
    return c.JSON(http.StatusOK, RespObject{
        Message: "Hello",
    })
}

func middle(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
        c.JSON(http.StatusOK, RespObject{
            Message: "World",
        })
        return next(c)
    }
}

after request i got

curl localhost:3000/hello
{"message":"World"}
{"message":"Hello"}

My goal is make response

{"message":"Hello World"}

echo.Context has struct Response with implement ResponseWriter

But seems ResponseWriter is WriteOnly contract. Is there is a way to some how erase and rebuild data in ResponseWriter?

As far i see there is a two issues

  1. Read data from ResponseWriter after passing "middle" handler.
  2. Erase data in ResponseWriter and write new data in "handler" handler

In real issue there is not necessary of name collision of struct. It`s request in two different SCIM API and make combine response.

CodePudding user response:

This can be achieved by creating a custom function that adds the response object and code to context and call it in handler; in middleware you get this object from context, modify the response and call actual c.JSON which writes the modified response to the wire.

const (
    echoCtxRespKey = "echo_ctx_resp_key"
)

type RespObject struct {
    Message string `json:"message"`
}

type Response struct {
    Data interface{}
    Code int
}

func main() {
    e := echo.New()
    e.GET("/hello", handler, middle)

    e.Logger.Fatal(e.Start(":3000"))
}

func handler(c echo.Context) error {
    resp := RespObject{
        Message: "Hello",
    }
    addResponseToContext(c, Response{
        Data: resp,
        Code: http.StatusOK,
    })
    
    return nil 
}

func middle(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
        next(c)
        
        resp := getResponseFromContext(c)
        
        // modify resp
        
        return c.JSON(resp.Code, resp.Data)
    }
}

func addResponseToContext(c echo.Context, response Response) {
    c.Set(echoCtxRespKey, response)
}

func getResponseFromContext(c echo.Context) Response {
    return c.Get(echoCtxRespKey).(Response)
}
  • Related