优雅地处理gin-gonic中的模板渲染错误

时间:2018-11-04 21:55:03

标签: go gin-gonic

我正在学习Go,并将gin-gonic用于Web应用程序。我正在尝试从模板错误中正常恢复,并且无法弄清楚如何缓冲输出或正确重定向以实现此目的。

使用以下代码:

package main

import (
    "net/http"

    "github.com/gin-gonic/gin"
)

func main() {
    g := gin.New()
    g.LoadHTMLGlob("templates/*")
    g.Use(func(c *gin.Context) {
        defer func() {
            if err := recover(); err != nil {
                c.HTML(http.StatusInternalServerError, "error.tmpl", nil)
            }
        }()

        c.Next()
    })
    g.GET("/", func(c *gin.Context) {
        c.HTML(http.StatusOK, "index.tmpl", gin.H{"var": 4})
    })
    g.Run(":80")
}

templates / index.tmpl在哪里

Before
<br>
Bad: {{.var.x}}
<br>
After

和模板/error.tmpl是

Oops! We encountered an error.

加载页面时,我看到

Before
Bad: Oops! We encountered an error.

并且响应代码最终为200。我更希望清除错误,以便向用户显示的唯一内容是

Oops! We encountered an error.

响应代码为500,错误记录在服务器上,以便以后进行调查。

杜松子酒中捕获模板错误而不向用户显示部分输出的最佳方法是什么?我已经看到了几个使用内置的net / http东西通过缓冲来实现此目的的示例,但是还没有找到任何方法来找到在gin中处理它的好方法。

使用解决方案进行编辑

基于@big Pigeon对已接受答案的评论,我最终自己在缓冲区中执行了模板,并在没有错误的情况下使用c.Data()进行显示。这似乎仍然不太理想,因为它绕开了multitemplate这样的功能,即能够在开发版本中在运行时动态重新加载已解析的模板的功能,但是它可以工作。更新后的概念验证代码如下:

package main

import (
    "bytes"
    "html/template"
    "net/http"

    "github.com/gin-gonic/gin"
)

func main() {
    g := gin.New()
    g.LoadHTMLGlob("templates/*")
    g.Use(func(c *gin.Context) {
        defer func() {
            if err := recover(); err != nil {
                c.HTML(http.StatusInternalServerError, "error.tmpl", nil)
            }
        }()

        c.Next()
    })
    g.GET("/", func(c *gin.Context) {
        if tmpl, err := template.ParseFiles("templates/index.tmpl"); err != nil {
            panic(err)
        } else {
            buf := &bytes.Buffer{}
            if err = tmpl.Execute(buf, gin.H{"var": 4}); err != nil {
                panic(err)
            } else {
                c.Data(http.StatusOK, "text/html; charset=utf-8", buf.Bytes())
            }
        }
    })
    g.Run(":80")
}

使用缓冲池,预解析模板以及其他类似功能,留给以后的读者练习。

如果有人知道一种更好的方法来处理此问题而不绕过gin的解析/渲染功能,那么我对此持开放态度。

1 个答案:

答案 0 :(得分:0)

您必须确保Template正确呈现,因为c.HTML将直接写入响应,这时某个字节已发送到客户端。

您可以使用“ html / template”,并使用buff来缓存响应数据,而不是直接写入响应编写器