Gin: c.String but as HTML

Created on 26 May 2016  Â·  2Comments  Â·  Source: gin-gonic/gin

I have my HTML coming from a cache. That's because the combining of a DB read and rendering is expensive. So I cache the HTML (a string starting with <!doctype html><html>...).
And in my view function I fetch it from the cache and push it out.

If I use c.String(http.StatusOK, html) it works but the content-type gets set to text/plain.

I could use...:

c.HTML(http.StatusOK, "index.tmpl", gin.H{
            "html": template.HTML(html),
        })

with a template that does nothing other than {{ .html }}.

Most helpful comment

@peterbe Here's one way to do it:

You could write the bytes directly to the underlying http response writer, skipping the template completely, then make sure you return your function to avoid further interaction with the response writer.

Gin packs http.ResponseWriter inside gin.Context (might be different if you aren't running v1)
The http response writer will automatically detect what Content-Type you're writing if you pass your valid byte slice to the Write() function:

Write adds a Content-Type set to the result of passing the initial 512 bytes of written data to DetectContentType
https://golang.org/pkg/net/http/#ResponseWriter

func CachedPageHandler(c *gin.Context){
    //Do what you need to get the cached html
    yourHtmlString := "<html><body>I am cached HTML!</body></html>"

    //Write your 200 header status (or other status codes, but only WriteHeader once)
    c.Writer.WriteHeader(http.StatusOK)
    //Convert your cached html string to byte array
    c.Writer.Write([]byte(yourHtmlString))
    return
}

If you can pull the cached html as a raw []byte then that's even better, you could avoid dealing with strings completely.

This should also be better performance wise, since you can skip the template completely.

Cheers ☕

All 2 comments

@peterbe Here's one way to do it:

You could write the bytes directly to the underlying http response writer, skipping the template completely, then make sure you return your function to avoid further interaction with the response writer.

Gin packs http.ResponseWriter inside gin.Context (might be different if you aren't running v1)
The http response writer will automatically detect what Content-Type you're writing if you pass your valid byte slice to the Write() function:

Write adds a Content-Type set to the result of passing the initial 512 bytes of written data to DetectContentType
https://golang.org/pkg/net/http/#ResponseWriter

func CachedPageHandler(c *gin.Context){
    //Do what you need to get the cached html
    yourHtmlString := "<html><body>I am cached HTML!</body></html>"

    //Write your 200 header status (or other status codes, but only WriteHeader once)
    c.Writer.WriteHeader(http.StatusOK)
    //Convert your cached html string to byte array
    c.Writer.Write([]byte(yourHtmlString))
    return
}

If you can pull the cached html as a raw []byte then that's even better, you could avoid dealing with strings completely.

This should also be better performance wise, since you can skip the template completely.

Cheers ☕

I like that. That'll work. Shame it wasn't in the README.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghost picture ghost  Â·  3Comments

mastrolinux picture mastrolinux  Â·  3Comments

iiinsomnia picture iiinsomnia  Â·  3Comments

rawoke083 picture rawoke083  Â·  3Comments

frederikhors picture frederikhors  Â·  3Comments