Description

As part of a microservice, I'm attempting to use a gin context's HTML template function to dynamically generate documents. While the templating itself works, I need a way to assign the resulting HTML to a string.

Since g.HTML in the example below offers no return value, how do I assign the templated HTML to a string variable?

How to reproduce

router.R.Engine().LoadHTMLGlob("templ/pdf/*.html")

    router.R.POST("/pdf", func(c *Hello, g *gin.Context) int {

        g.HTML(http.StatusOK, "hello.html", gin.H{
            "salutation": c.Salutation,
            "name":       c.Name,
        })

Environment

  • go version: 1.19.1
  • gin version (or commit ref): 1.7.7 (I'm using gNext, but it bundles gin internally and I use the exposed raw functionality most of the time)
  • operating system: Windows 11 (WSL2)

Comment From: markusbkk

Not sure if this is canonical (found in an older Stack Overflow thread) but this is how I implemented it now.

type htmlWriter struct {
    gin.ResponseWriter
    body *bytes.Buffer
}

func (w htmlWriter) Write(b []byte) (int, error) {
    w.body.Write(b)
    return w.ResponseWriter.Write(b)
}

func returnHTML(c *gin.Context) htmlWriter {
    html := &htmlWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
    c.Writer = html
    c.Next()
    statusCode := c.Writer.Status()
    if statusCode >= 400 {
        //ok this is an request with error, let's make a record for it
        // now print body (or log in your preferred way)
        fmt.Println("Response body: " + html.body.String())
    }
    return *html
}

It can then be used by providing the context from within the POST function.

i e:

html := returnHTML(g)

(where g is *gin.Context

The result can then be accessed in string form by calling html.body.String()