Pārlūkot izejas kodu

Compress HTML responses to Gzip/Deflate if supported by browser

Frédéric Guillot 8 gadi atpakaļ
vecāks
revīzija
34a3fe426b

+ 3 - 2
http/response/html/html.go

@@ -7,13 +7,14 @@ package html
 import (
 	"net/http"
 
+	"github.com/miniflux/miniflux/http/response"
 	"github.com/miniflux/miniflux/logger"
 )
 
 // OK writes a standard HTML response.
-func OK(w http.ResponseWriter, b []byte) {
+func OK(w http.ResponseWriter, r *http.Request, b []byte) {
 	w.Header().Set("Content-Type", "text/html; charset=utf-8")
-	w.Write(b)
+	response.Compress(w, r, b)
 }
 
 // ServerError sends a 500 error to the browser.

+ 23 - 0
http/response/response.go

@@ -5,7 +5,10 @@
 package response
 
 import (
+	"compress/flate"
+	"compress/gzip"
 	"net/http"
+	"strings"
 	"time"
 )
 
@@ -32,3 +35,23 @@ func Cache(w http.ResponseWriter, r *http.Request, mimeType, etag string, conten
 		w.Write(content)
 	}
 }
+
+// Compress the response sent to the browser.
+func Compress(w http.ResponseWriter, r *http.Request, data []byte) {
+	acceptEncoding := r.Header.Get("Accept-Encoding")
+
+	switch {
+	case strings.Contains(acceptEncoding, "gzip"):
+		w.Header().Set("Content-Encoding", "gzip")
+		gzipWriter := gzip.NewWriter(w)
+		defer gzipWriter.Close()
+		gzipWriter.Write(data)
+	case strings.Contains(acceptEncoding, "deflate"):
+		w.Header().Set("Content-Encoding", "deflate")
+		flateWriter, _ := flate.NewWriter(w, -1)
+		defer flateWriter.Close()
+		flateWriter.Write(data)
+	default:
+		w.Write(data)
+	}
+}

+ 1 - 1
ui/about.go

@@ -32,5 +32,5 @@ func (c *Controller) About(w http.ResponseWriter, r *http.Request) {
 	view.Set("user", user)
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 
-	html.OK(w, view.Render("about"))
+	html.OK(w, r, view.Render("about"))
 }

+ 1 - 1
ui/bookmark_entries.go

@@ -58,5 +58,5 @@ func (c *Controller) ShowStarredPage(w http.ResponseWriter, r *http.Request) {
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 	view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
 
-	html.OK(w, view.Render("bookmark_entries"))
+	html.OK(w, r, view.Render("bookmark_entries"))
 }

+ 1 - 1
ui/category_create.go

@@ -29,5 +29,5 @@ func (c *Controller) CreateCategory(w http.ResponseWriter, r *http.Request) {
 	view.Set("user", user)
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 
-	html.OK(w, view.Render("create_category"))
+	html.OK(w, r, view.Render("create_category"))
 }

+ 1 - 1
ui/category_edit.go

@@ -54,5 +54,5 @@ func (c *Controller) EditCategory(w http.ResponseWriter, r *http.Request) {
 	view.Set("user", user)
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 
-	html.OK(w, view.Render("edit_category"))
+	html.OK(w, r, view.Render("edit_category"))
 }

+ 1 - 1
ui/category_entries.go

@@ -75,5 +75,5 @@ func (c *Controller) CategoryEntries(w http.ResponseWriter, r *http.Request) {
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 	view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
 
-	html.OK(w, view.Render("category_entries"))
+	html.OK(w, r, view.Render("category_entries"))
 }

+ 1 - 1
ui/category_list.go

@@ -37,5 +37,5 @@ func (c *Controller) CategoryList(w http.ResponseWriter, r *http.Request) {
 	view.Set("user", user)
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 
-	html.OK(w, view.Render("categories"))
+	html.OK(w, r, view.Render("categories"))
 }

+ 3 - 3
ui/category_save.go

@@ -39,7 +39,7 @@ func (c *Controller) SaveCategory(w http.ResponseWriter, r *http.Request) {
 
 	if err := categoryForm.Validate(); err != nil {
 		view.Set("errorMessage", err.Error())
-		html.OK(w, view.Render("create_category"))
+		html.OK(w, r, view.Render("create_category"))
 		return
 	}
 
@@ -51,7 +51,7 @@ func (c *Controller) SaveCategory(w http.ResponseWriter, r *http.Request) {
 
 	if duplicateCategory != nil {
 		view.Set("errorMessage", "This category already exists.")
-		html.OK(w, view.Render("create_category"))
+		html.OK(w, r, view.Render("create_category"))
 		return
 	}
 
@@ -63,7 +63,7 @@ func (c *Controller) SaveCategory(w http.ResponseWriter, r *http.Request) {
 	if err = c.store.CreateCategory(&category); err != nil {
 		logger.Error("[Controller:CreateCategory] %v", err)
 		view.Set("errorMessage", "Unable to create this category.")
-		html.OK(w, view.Render("create_category"))
+		html.OK(w, r, view.Render("create_category"))
 		return
 	}
 

+ 3 - 3
ui/category_update.go

@@ -57,13 +57,13 @@ func (c *Controller) UpdateCategory(w http.ResponseWriter, r *http.Request) {
 
 	if err := categoryForm.Validate(); err != nil {
 		view.Set("errorMessage", err.Error())
-		html.OK(w, view.Render("edit_category"))
+		html.OK(w, r, view.Render("edit_category"))
 		return
 	}
 
 	if c.store.AnotherCategoryExists(user.ID, category.ID, categoryForm.Title) {
 		view.Set("errorMessage", "This category already exists.")
-		html.OK(w, view.Render("edit_category"))
+		html.OK(w, r, view.Render("edit_category"))
 		return
 	}
 
@@ -71,7 +71,7 @@ func (c *Controller) UpdateCategory(w http.ResponseWriter, r *http.Request) {
 	if err != nil {
 		logger.Error("[Controller:UpdateCategory] %v", err)
 		view.Set("errorMessage", "Unable to update this category.")
-		html.OK(w, view.Render("edit_category"))
+		html.OK(w, r, view.Render("edit_category"))
 		return
 	}
 

+ 1 - 1
ui/entry_bookmark.go

@@ -88,5 +88,5 @@ func (c *Controller) ShowStarredEntry(w http.ResponseWriter, r *http.Request) {
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 	view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
 
-	html.OK(w, view.Render("entry"))
+	html.OK(w, r, view.Render("entry"))
 }

+ 1 - 1
ui/entry_category.go

@@ -95,5 +95,5 @@ func (c *Controller) ShowCategoryEntry(w http.ResponseWriter, r *http.Request) {
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 	view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
 
-	html.OK(w, view.Render("entry"))
+	html.OK(w, r, view.Render("entry"))
 }

+ 1 - 1
ui/entry_feed.go

@@ -95,5 +95,5 @@ func (c *Controller) ShowFeedEntry(w http.ResponseWriter, r *http.Request) {
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 	view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
 
-	html.OK(w, view.Render("entry"))
+	html.OK(w, r, view.Render("entry"))
 }

+ 1 - 1
ui/entry_read.go

@@ -78,5 +78,5 @@ func (c *Controller) ShowReadEntry(w http.ResponseWriter, r *http.Request) {
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 	view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
 
-	html.OK(w, view.Render("entry"))
+	html.OK(w, r, view.Render("entry"))
 }

+ 1 - 1
ui/entry_search.go

@@ -91,5 +91,5 @@ func (c *Controller) ShowSearchEntry(w http.ResponseWriter, r *http.Request) {
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 	view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
 
-	html.OK(w, view.Render("entry"))
+	html.OK(w, r, view.Render("entry"))
 }

+ 1 - 1
ui/entry_unread.go

@@ -99,5 +99,5 @@ func (c *Controller) ShowUnreadEntry(w http.ResponseWriter, r *http.Request) {
 	// Fetching the counter here avoid to be off by one.
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 
-	html.OK(w, view.Render("entry"))
+	html.OK(w, r, view.Render("entry"))
 }

+ 1 - 1
ui/feed_edit.go

@@ -69,5 +69,5 @@ func (c *Controller) EditFeed(w http.ResponseWriter, r *http.Request) {
 	view.Set("user", user)
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 
-	html.OK(w, view.Render("edit_feed"))
+	html.OK(w, r, view.Render("edit_feed"))
 }

+ 1 - 1
ui/feed_entries.go

@@ -75,5 +75,5 @@ func (c *Controller) ShowFeedEntries(w http.ResponseWriter, r *http.Request) {
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 	view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
 
-	html.OK(w, view.Render("feed_entries"))
+	html.OK(w, r, view.Render("feed_entries"))
 }

+ 1 - 1
ui/feed_list.go

@@ -37,5 +37,5 @@ func (c *Controller) ShowFeedsPage(w http.ResponseWriter, r *http.Request) {
 	view.Set("user", user)
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 
-	html.OK(w, view.Render("feeds"))
+	html.OK(w, r, view.Render("feeds"))
 }

+ 2 - 2
ui/feed_update.go

@@ -64,7 +64,7 @@ func (c *Controller) UpdateFeed(w http.ResponseWriter, r *http.Request) {
 
 	if err := feedForm.ValidateModification(); err != nil {
 		view.Set("errorMessage", err.Error())
-		html.OK(w, view.Render("edit_feed"))
+		html.OK(w, r, view.Render("edit_feed"))
 		return
 	}
 
@@ -72,7 +72,7 @@ func (c *Controller) UpdateFeed(w http.ResponseWriter, r *http.Request) {
 	if err != nil {
 		logger.Error("[Controller:EditFeed] %v", err)
 		view.Set("errorMessage", "Unable to update this feed.")
-		html.OK(w, view.Render("edit_feed"))
+		html.OK(w, r, view.Render("edit_feed"))
 		return
 	}
 

+ 1 - 1
ui/history_entries.go

@@ -56,5 +56,5 @@ func (c *Controller) ShowHistoryPage(w http.ResponseWriter, r *http.Request) {
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 	view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
 
-	html.OK(w, view.Render("history_entries"))
+	html.OK(w, r, view.Render("history_entries"))
 }

+ 1 - 1
ui/integration_show.go

@@ -63,5 +63,5 @@ func (c *Controller) ShowIntegrations(w http.ResponseWriter, r *http.Request) {
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 	view.Set("hasPocketConsumerKeyConfigured", c.cfg.PocketConsumerKey("") != "")
 
-	html.OK(w, view.Render("integrations"))
+	html.OK(w, r, view.Render("integrations"))
 }

+ 2 - 2
ui/login_check.go

@@ -28,13 +28,13 @@ func (c *Controller) CheckLogin(w http.ResponseWriter, r *http.Request) {
 
 	if err := authForm.Validate(); err != nil {
 		logger.Error("[Controller:CheckLogin] %v", err)
-		html.OK(w, view.Render("login"))
+		html.OK(w, r, view.Render("login"))
 		return
 	}
 
 	if err := c.store.CheckPassword(authForm.Username, authForm.Password); err != nil {
 		logger.Error("[Controller:CheckLogin] %v", err)
-		html.OK(w, view.Render("login"))
+		html.OK(w, r, view.Render("login"))
 		return
 	}
 

+ 1 - 1
ui/login_show.go

@@ -25,5 +25,5 @@ func (c *Controller) ShowLoginPage(w http.ResponseWriter, r *http.Request) {
 
 	sess := session.New(c.store, ctx)
 	view := view.New(c.tpl, ctx, sess)
-	html.OK(w, view.Render("login"))
+	html.OK(w, r, view.Render("login"))
 }

+ 1 - 1
ui/opml_import.go

@@ -29,5 +29,5 @@ func (c *Controller) Import(w http.ResponseWriter, r *http.Request) {
 	view.Set("user", user)
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 
-	html.OK(w, view.Render("import"))
+	html.OK(w, r, view.Render("import"))
 }

+ 2 - 2
ui/opml_upload.go

@@ -50,13 +50,13 @@ func (c *Controller) UploadOPML(w http.ResponseWriter, r *http.Request) {
 
 	if fileHeader.Size == 0 {
 		view.Set("errorMessage", "This file is empty")
-		html.OK(w, view.Render("import"))
+		html.OK(w, r, view.Render("import"))
 		return
 	}
 
 	if impErr := opml.NewHandler(c.store).Import(user.ID, file); impErr != nil {
 		view.Set("errorMessage", impErr)
-		html.OK(w, view.Render("import"))
+		html.OK(w, r, view.Render("import"))
 		return
 	}
 

+ 1 - 1
ui/search_entries.go

@@ -62,5 +62,5 @@ func (c *Controller) ShowSearchEntries(w http.ResponseWriter, r *http.Request) {
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 	view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
 
-	html.OK(w, view.Render("search_entries"))
+	html.OK(w, r, view.Render("search_entries"))
 }

+ 1 - 1
ui/session_list.go

@@ -40,5 +40,5 @@ func (c *Controller) ShowSessions(w http.ResponseWriter, r *http.Request) {
 	view.Set("user", user)
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 
-	html.OK(w, view.Render("sessions"))
+	html.OK(w, r, view.Render("sessions"))
 }

+ 1 - 1
ui/settings_show.go

@@ -50,5 +50,5 @@ func (c *Controller) ShowSettings(w http.ResponseWriter, r *http.Request) {
 	view.Set("user", user)
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 
-	html.OK(w, view.Render("settings"))
+	html.OK(w, r, view.Render("settings"))
 }

+ 3 - 3
ui/settings_update.go

@@ -49,13 +49,13 @@ func (c *Controller) UpdateSettings(w http.ResponseWriter, r *http.Request) {
 
 	if err := settingsForm.Validate(); err != nil {
 		view.Set("errorMessage", err.Error())
-		html.OK(w, view.Render("settings"))
+		html.OK(w, r, view.Render("settings"))
 		return
 	}
 
 	if c.store.AnotherUserExists(user.ID, settingsForm.Username) {
 		view.Set("errorMessage", "This user already exists.")
-		html.OK(w, view.Render("settings"))
+		html.OK(w, r, view.Render("settings"))
 		return
 	}
 
@@ -63,7 +63,7 @@ func (c *Controller) UpdateSettings(w http.ResponseWriter, r *http.Request) {
 	if err != nil {
 		logger.Error("[Controller:UpdateSettings] %v", err)
 		view.Set("errorMessage", "Unable to update this user.")
-		html.OK(w, view.Render("settings"))
+		html.OK(w, r, view.Render("settings"))
 		return
 	}
 

+ 1 - 1
ui/subscription_add.go

@@ -36,5 +36,5 @@ func (c *Controller) AddSubscription(w http.ResponseWriter, r *http.Request) {
 	view.Set("user", user)
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 
-	html.OK(w, view.Render("add_subscription"))
+	html.OK(w, r, view.Render("add_subscription"))
 }

+ 1 - 1
ui/subscription_bookmarklet.go

@@ -41,5 +41,5 @@ func (c *Controller) Bookmarklet(w http.ResponseWriter, r *http.Request) {
 	view.Set("user", user)
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 
-	html.OK(w, view.Render("add_subscription"))
+	html.OK(w, r, view.Render("add_subscription"))
 }

+ 2 - 2
ui/subscription_choose.go

@@ -43,7 +43,7 @@ func (c *Controller) ChooseSubscription(w http.ResponseWriter, r *http.Request)
 	if err := subscriptionForm.Validate(); err != nil {
 		view.Set("form", subscriptionForm)
 		view.Set("errorMessage", err.Error())
-		html.OK(w, view.Render("add_subscription"))
+		html.OK(w, r, view.Render("add_subscription"))
 		return
 	}
 
@@ -58,7 +58,7 @@ func (c *Controller) ChooseSubscription(w http.ResponseWriter, r *http.Request)
 	if err != nil {
 		view.Set("form", subscriptionForm)
 		view.Set("errorMessage", err)
-		html.OK(w, view.Render("add_subscription"))
+		html.OK(w, r, view.Render("add_subscription"))
 		return
 	}
 

+ 5 - 5
ui/subscription_submit.go

@@ -45,7 +45,7 @@ func (c *Controller) SubmitSubscription(w http.ResponseWriter, r *http.Request)
 	if err := subscriptionForm.Validate(); err != nil {
 		v.Set("form", subscriptionForm)
 		v.Set("errorMessage", err.Error())
-		html.OK(w, v.Render("add_subscription"))
+		html.OK(w, r, v.Render("add_subscription"))
 		return
 	}
 
@@ -58,7 +58,7 @@ func (c *Controller) SubmitSubscription(w http.ResponseWriter, r *http.Request)
 		logger.Error("[Controller:SubmitSubscription] %v", err)
 		v.Set("form", subscriptionForm)
 		v.Set("errorMessage", err)
-		html.OK(w, v.Render("add_subscription"))
+		html.OK(w, r, v.Render("add_subscription"))
 		return
 	}
 
@@ -69,7 +69,7 @@ func (c *Controller) SubmitSubscription(w http.ResponseWriter, r *http.Request)
 	case n == 0:
 		v.Set("form", subscriptionForm)
 		v.Set("errorMessage", "Unable to find any subscription.")
-		html.OK(w, v.Render("add_subscription"))
+		html.OK(w, r, v.Render("add_subscription"))
 	case n == 1:
 		feed, err := c.feedHandler.CreateFeed(
 			user.ID,
@@ -82,7 +82,7 @@ func (c *Controller) SubmitSubscription(w http.ResponseWriter, r *http.Request)
 		if err != nil {
 			v.Set("form", subscriptionForm)
 			v.Set("errorMessage", err)
-			html.OK(w, v.Render("add_subscription"))
+			html.OK(w, r, v.Render("add_subscription"))
 			return
 		}
 
@@ -95,6 +95,6 @@ func (c *Controller) SubmitSubscription(w http.ResponseWriter, r *http.Request)
 		v.Set("user", user)
 		v.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 
-		html.OK(w, v.Render("choose_subscription"))
+		html.OK(w, r, v.Render("choose_subscription"))
 	}
 }

+ 1 - 1
ui/unread_entries.go

@@ -60,5 +60,5 @@ func (c *Controller) ShowUnreadPage(w http.ResponseWriter, r *http.Request) {
 	view.Set("countUnread", countUnread)
 	view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
 
-	html.OK(w, view.Render("unread_entries"))
+	html.OK(w, r, view.Render("unread_entries"))
 }

+ 1 - 1
ui/user_create.go

@@ -36,5 +36,5 @@ func (c *Controller) CreateUser(w http.ResponseWriter, r *http.Request) {
 	view.Set("user", user)
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 
-	html.OK(w, view.Render("create_user"))
+	html.OK(w, r, view.Render("create_user"))
 }

+ 1 - 1
ui/user_edit.go

@@ -60,5 +60,5 @@ func (c *Controller) EditUser(w http.ResponseWriter, r *http.Request) {
 	view.Set("user", user)
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 
-	html.OK(w, view.Render("edit_user"))
+	html.OK(w, r, view.Render("edit_user"))
 }

+ 1 - 1
ui/user_list.go

@@ -43,5 +43,5 @@ func (c *Controller) ShowUsers(w http.ResponseWriter, r *http.Request) {
 	view.Set("user", user)
 	view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
 
-	html.OK(w, view.Render("users"))
+	html.OK(w, r, view.Render("users"))
 }

+ 3 - 3
ui/user_save.go

@@ -43,13 +43,13 @@ func (c *Controller) SaveUser(w http.ResponseWriter, r *http.Request) {
 
 	if err := userForm.ValidateCreation(); err != nil {
 		view.Set("errorMessage", err.Error())
-		html.OK(w, view.Render("create_user"))
+		html.OK(w, r, view.Render("create_user"))
 		return
 	}
 
 	if c.store.UserExists(userForm.Username) {
 		view.Set("errorMessage", "This user already exists.")
-		html.OK(w, view.Render("create_user"))
+		html.OK(w, r, view.Render("create_user"))
 		return
 	}
 
@@ -57,7 +57,7 @@ func (c *Controller) SaveUser(w http.ResponseWriter, r *http.Request) {
 	if err := c.store.CreateUser(newUser); err != nil {
 		logger.Error("[Controller:SaveUser] %v", err)
 		view.Set("errorMessage", "Unable to create this user.")
-		html.OK(w, view.Render("create_user"))
+		html.OK(w, r, view.Render("create_user"))
 		return
 	}
 

+ 3 - 3
ui/user_update.go

@@ -62,13 +62,13 @@ func (c *Controller) UpdateUser(w http.ResponseWriter, r *http.Request) {
 
 	if err := userForm.ValidateModification(); err != nil {
 		view.Set("errorMessage", err.Error())
-		html.OK(w, view.Render("edit_user"))
+		html.OK(w, r, view.Render("edit_user"))
 		return
 	}
 
 	if c.store.AnotherUserExists(selectedUser.ID, userForm.Username) {
 		view.Set("errorMessage", "This user already exists.")
-		html.OK(w, view.Render("edit_user"))
+		html.OK(w, r, view.Render("edit_user"))
 		return
 	}
 
@@ -76,7 +76,7 @@ func (c *Controller) UpdateUser(w http.ResponseWriter, r *http.Request) {
 	if err := c.store.UpdateUser(selectedUser); err != nil {
 		logger.Error("[Controller:UpdateUser] %v", err)
 		view.Set("errorMessage", "Unable to update this user.")
-		html.OK(w, view.Render("edit_user"))
+		html.OK(w, r, view.Render("edit_user"))
 		return
 	}