2015-10-11 2 views
0

Моя первая идея состояла в том, чтобы получить тело ответа внутри фильтра, а затем использовать одну из minify библиотек, таких как tdewolff/minify и write to response, но я не могу найти способ получить тело ответа. Есть ли лучшие решения?Как выполнить html minify с Revel framework

ответ

0

Кажется, взглянув на документы, фильтр может получить доступ к типу 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. Minify Читает от этого читателя и пишет первому автору ответа.

Поскольку мы меняем значение c.Response.Out, мы должны передать его явно в goroutine. Убедитесь, что вы получили правильный тип mimetype (через расширение?) Или напрямую вызываете соответствующую функцию minify.

+0

работает в Firefox, но Chrome не показывает страницу с ошибкой net :: ERR_CONTENT_LENGTH_MISMATCH. Пытался вставить фильтр до или после revel.CompressFilter без успеха. –

+0

Я не уверен, как работает Ревель, но посмотрите на https://github.com/revel/revel/blob/master/compress.go#L46, кажется, что вам нужно удалить заголовок длины содержимого, чтобы он пересчитывается? –

+0

Большое вам спасибо за вашу большую помощь и приятную библиотеку minify) Единственная проблема, которую я вижу, это бесконечные ошибки, такие как goroutine 45 [semacquire]: sync.runtime_Syncsemacquire (0xc82013aa00); /home/venom/gocode/src/github.com/tdewolff/buffer/shifter.go:75 после обновления страницы, как 10 раз –

Смежные вопросы