我的第一个想法是将响应主体放入过滤器中,然后使用诸如tdewolff / minify之类的minify库之一并写入响应,但是我找不到找到响应主体的方法。
有没有更好的解决方案?
最佳答案
通过查看文档,过滤器似乎可以访问Controller
类型,其中包含Response
。此响应包含Out
,它是ResponseWriter(因此也是io.Writer)。我们只需要替换Write方法即可将写入重定向到Minifier,然后再将其写入响应编写器。为此,我们需要使用io.Pipe
和一个goroutine。
type MinifyResponseWriter struct {
http.ResponseWriter
io.Writer
}
func (f MinifyResponseWriter) Write(b []byte) (int, error) {
return f.Writer.Write(b)
}
func MinifyFilter(c *Controller, fc []Filter) {
pr, pw := io.Pipe()
go func(w io.Writer) {
m := minify.New()
m.AddFunc("text/css", css.Minify)
m.AddFunc("text/html", html.Minify)
m.AddFunc("text/javascript", js.Minify)
m.AddFunc("image/svg+xml", svg.Minify)
m.AddFuncRegexp(regexp.MustCompile("[/+]json$"), json.Minify)
m.AddFuncRegexp(regexp.MustCompile("[/+]xml$"), xml.Minify)
if err := m.Minify("mimetype", w, pr); err != nil {
panic(err)
}
}(c.Response.Out)
c.Response.Out = MinifyResponseWriter{c.Response.Out, pw}
}
遵循这些原则(未经测试)。在这里,我们接收传入的
io.Writer
(这是ResponseWriter
的一部分),并在其周围包装一个结构。它保留了响应编写器的原始方法,但是重写了Write方法,以将其替换为PipeWriter
。这意味着对新响应编写器的任何写操作都将传递给PipeWriter
,后者与PipeReader
耦合。缩小从该读取器读取的内容并写入原始响应编写器。因为我们更改了
c.Response.Out
的值,所以我们需要将其显式传递给goroutine。确保获得正确的模仿类型(通过扩展名?)或直接调用适当的minify函数。关于go - 如何使用Revel框架执行HTML Minify,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33067616/