Minify Filter - Revel Framework - Go Lang. Article: http://myjeeva.com/minify-filter-revel-framework-go-lang.html
// | |
// The MIT License (MIT) | |
// | |
// Copyright (c) 2016 Jeevanandam M. (jeeva@myjeeva.com) | |
// | |
// Permission is hereby granted, free of charge, to any person obtaining a copy | |
// of this software and associated documentation files (the "Software"), to deal | |
// in the Software without restriction, including without limitation the rights | |
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
// copies of the Software, and to permit persons to whom the Software is | |
// furnished to do so, subject to the following conditions: | |
// | |
// The above copyright notice and this permission notice shall be included in | |
// all copies or substantial portions of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
// THE SOFTWARE. | |
// | |
// Article: http://myjeeva.com/minify-filter-revel-framework-go-lang.html | |
package filter | |
import ( | |
"io" | |
"net/http" | |
"regexp" | |
"github.com/revel/revel" | |
"github.com/tdewolff/minify" | |
"github.com/tdewolff/minify/css" | |
"github.com/tdewolff/minify/html" | |
"github.com/tdewolff/minify/js" | |
) | |
var ( | |
m *minify.M | |
htmlMimeType *regexp.Regexp | |
) | |
type MinifyWriter struct { | |
http.ResponseWriter | |
minifyWriter io.WriteCloser | |
shouldMinify bool | |
headersWritten bool | |
closeNotify chan bool | |
parentNotify <-chan bool | |
closed bool | |
} | |
func Minify(c *revel.Controller, fc []revel.Filter) { | |
fc[0](c, fc[1:]) | |
if revel.Config.BoolDefault("results.minify", false) { | |
if c.Response.Status != http.StatusNoContent && c.Response.Status != http.StatusNotModified { | |
mw := m.Writer("text/html", c.Response.Out) | |
writer := MinifyWriter{c.Response.Out, mw, false, false, make(chan bool, 1), nil, false} | |
w, ok := c.Response.Out.(http.CloseNotifier) | |
if ok { | |
writer.parentNotify = w.CloseNotify() | |
} | |
c.Response.Out = &writer | |
} else { | |
revel.TRACE.Printf("Minify disabled for response status (%d)", c.Response.Status) | |
} | |
} | |
} | |
func (c MinifyWriter) CloseNotify() <-chan bool { | |
if c.parentNotify != nil { | |
return c.parentNotify | |
} | |
return c.closeNotify | |
} | |
func (c *MinifyWriter) WriteHeader(status int) { | |
c.headersWritten = true | |
c.prepareHeader() | |
c.ResponseWriter.WriteHeader(status) | |
} | |
func (c *MinifyWriter) prepareHeader() { | |
// minify is only applied to HTML content | |
if htmlMimeType.MatchString(c.Header().Get("Content-Type")) { | |
c.shouldMinify = true | |
c.Header().Del("Content-Length") | |
} | |
} | |
func (c *MinifyWriter) Close() error { | |
if c.shouldMinify { | |
c.minifyWriter.Close() | |
} | |
if w, ok := c.ResponseWriter.(io.Closer); ok { | |
w.Close() | |
} | |
// Non-blocking write to the closenotifier, if we for some reason should | |
// get called multiple times | |
select { | |
case c.closeNotify <- true: | |
default: | |
} | |
c.closed = true | |
return nil | |
} | |
func (c *MinifyWriter) Write(b []byte) (int, error) { | |
// Abort if parent has been closed | |
if c.parentNotify != nil { | |
select { | |
case <-c.parentNotify: | |
return 0, io.ErrClosedPipe | |
default: | |
} | |
} | |
// Abort if we ourselves have been closed | |
if c.closed { | |
return 0, io.ErrClosedPipe | |
} | |
if !c.headersWritten { | |
c.prepareHeader() | |
c.headersWritten = true | |
} | |
if c.shouldMinify { | |
return c.minifyWriter.Write(b) | |
} else { | |
return c.ResponseWriter.Write(b) | |
} | |
} | |
func init() { | |
m = minify.New() | |
m.AddFunc("text/css", css.Minify) | |
m.AddFunc("text/html", html.Minify) | |
m.AddFunc("text/javascript", js.Minify) | |
htmlMimeType = regexp.MustCompile("[text|appliation]/html") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment