Как да извършите минимизиране на html с Revel framework

Първата ми идея беше да получа тялото на отговора във филтъра, след това да използвам една от библиотеките за минимизиране като tdewolff/minify и да пиша в отговора, но не мога да намеря начин да получа тялото на отговора. Има ли по-добри решения?


person St. Venom    schedule 11.10.2015    source източник


Отговори (1)


Изглежда, като се гледат документите, филтърът може да има достъп до типа Controller, който съдържа Response. Този отговор съдържа Out, който е ResponseWriter (и следователно също io.Writer). Трябва да заменим само метода Write, за да пренасочи записа към минификатора, който след това пише към записващия отговор. Трябва да използваме 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. Уверете се, че сте получили правилния mimetype (чрез разширение?) или извикайте директно съответната функция за минимизиране.

person Taco de Wolff    schedule 11.10.2015
comment
работи във Firefox, но Chrome не показва страница с грешка net::ERR_CONTENT_LENGTH_MISMATCH. Опитах да вмъкна филтър преди или след revel.CompressFilter без успех. - person St. Venom; 12.10.2015
comment
Не съм сигурен как работи Revel, но погледнете github. com/revel/revel/blob/master/compress.go#L46, изглежда, че трябва да премахнете заглавката за дължина на съдържанието, за да се преизчисли? - person Taco de Wolff; 12.10.2015
comment
Благодаря ви много за страхотната ви помощ и хубавата библиотека за минимизиране) Единственият проблем, който виждам, са безкрайните грешки като goroutine 45 [semacquire]: sync.runtime_Syncsemacquire(0xc82013aa00) ; /home/venom/gocode/src/github.com/tdewolff/buffer/shifter.go:75 след като подновя страницата около 10 пъти - person St. Venom; 12.10.2015
comment
Благодаря! Това е странна грешка, по номера на реда изглежда, че идва от функцията Read на дадения io.Reader. Може би защото тръбата не е добре затворена? Не мога да кажа със сигурност без повече информация. - person Taco de Wolff; 12.10.2015
comment
111 ред е: if err := m.Minify(text/html, w, pr); err != nil { panic(err)} Грешка: Conn.Write е написал повече от декларираната Content-Length; goroutine 56 [работи]: my-site/app.glob.func3.1(0xc820281810, 0xc820276b28, 0x7f834fdb4100, 0xc820281760) /home/venom/gocode/src/my-site/app/init.go:111 +0x666, създаден от my-site/app.glob.func3 /home/venom/gocode/src/my-site/app/init.go:114 +0x2f4 - person St. Venom; 12.10.2015
comment
Не мога да кажа какво се случва без повече информация. Моля, установете дали това е грешка в Minify или не. - person Taco de Wolff; 13.10.2015
comment
Тази грешка (Conn.Write е написал повече от декларираната дължина на съдържанието) се появява на случаен принцип (от 2 подновявани страници до 30). Мисля, че това се случва по някаква странна причина, когато дължината на новото съдържание на минимизираното съдържание се отчита, но неминифицираната версия се записва в отговор, така че действителният размер на съдържанието е по-голям от очакваната дължина на съдържанието. Освен това тази грешка възниква случайно, така че мисля, че е по-лесно да минимизирате html чрез текстов редактор, вместо да решите този проблем:( - person St. Venom; 13.10.2015
comment
Звучи като надпревара с данни (проверете с go test -race) или нещо подобно. Но ако искате да го компресирате в текстовия редактор, този инструмент ще ви помогне: pi.tacodewolff.nl:8080/ минимизиране - person Taco de Wolff; 14.10.2015