Skip to content

Commit

Permalink
Add gzip and cache controll for http response
Browse files Browse the repository at this point in the history
  • Loading branch information
orangedeng authored and Alena Prokharchyk committed Oct 12, 2018
1 parent 2b2ee67 commit fe353c4
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 4 deletions.
35 changes: 35 additions & 0 deletions server/responsewriter/cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package responsewriter

import (
"net/http"
"strings"

"github.com/gorilla/mux"
)

func CacheMiddleware(suffixes ...string) mux.MiddlewareFunc {
return mux.MiddlewareFunc(func(handler http.Handler) http.Handler {
return Cache(handler, suffixes...)
})
}

func Cache(handler http.Handler, suffixes ...string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
i := strings.LastIndex(r.URL.Path, ".")
if i >= 0 {
for _, suffix := range suffixes {
if suffix == r.URL.Path[i+1:] {
w.Header().Set("Cache-Control", "max-age=31536000, public")
}
}
}
handler.ServeHTTP(w, r)
})
}

func NoCache(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
handler.ServeHTTP(w, r)
})
}
31 changes: 31 additions & 0 deletions server/responsewriter/content.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package responsewriter

import (
"net/http"
"strings"
)

type ContentTypeWriter struct {
http.ResponseWriter
}

func (c ContentTypeWriter) Write(b []byte) (int, error) {
found := false
for k := range c.Header() {
if strings.EqualFold(k, "Content-Type") {
found = true
break
}
}
if !found {
c.Header().Set("Content-Type", http.DetectContentType(b))
}
return c.ResponseWriter.Write(b)
}

func ContentType(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
writer := ContentTypeWriter{ResponseWriter: w}
handler.ServeHTTP(writer, r)
})
}
31 changes: 31 additions & 0 deletions server/responsewriter/gzip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package responsewriter

import (
"compress/gzip"
"io"
"net/http"
"strings"
)

type gzipResponseWriter struct {
io.Writer
http.ResponseWriter
}

func (w gzipResponseWriter) Write(b []byte) (int, error) {
return w.Writer.Write(b)
}

func Gzip(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
handler.ServeHTTP(w, r)
return
}
gz := gzip.NewWriter(w)
defer gz.Close()
gzw := gzipResponseWriter{Writer: gz, ResponseWriter: w}
gzw.Header().Set("Content-Encoding", "gzip")
handler.ServeHTTP(gzw, r)
})
}
24 changes: 24 additions & 0 deletions server/responsewriter/middleware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package responsewriter

import (
"net/http"

"github.com/gorilla/mux"
)

type MiddlewareChain struct {
middleWares []mux.MiddlewareFunc
}

func NewMiddlewareChain(middleWares ...mux.MiddlewareFunc) *MiddlewareChain {
return &MiddlewareChain{middleWares: middleWares}
}

func (m *MiddlewareChain) Handler(handler http.Handler) http.Handler {
rtn := handler
for i := len(m.middleWares) - 1; i >= 0; i-- {
w := m.middleWares[i]
rtn = w.Middleware(rtn)
}
return rtn
}
9 changes: 5 additions & 4 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/rancher/rancher/pkg/rkenodeconfigserver"
"github.com/rancher/rancher/pkg/telemetry"
"github.com/rancher/rancher/server/capabilities"
"github.com/rancher/rancher/server/responsewriter"
"github.com/rancher/rancher/server/ui"
"github.com/rancher/rancher/server/whitelist"
managementSchema "github.com/rancher/types/apis/management.cattle.io/v3/schema"
Expand Down Expand Up @@ -64,8 +65,8 @@ func Start(ctx context.Context, httpPort, httpsPort int, scaledContext *config.S
connectHandler, connectConfigHandler := connectHandlers(scaledContext)

samlRoot := saml.AuthHandler()

root.Handle("/", ui.UI(managementAPI))
chain := responsewriter.NewMiddlewareChain(responsewriter.Gzip, responsewriter.NoCache, responsewriter.ContentType, ui.UI)
root.Handle("/", chain.Handler(managementAPI))
root.PathPrefix("/v3-public").Handler(publicAPI)
root.Handle("/v3/import/{token}.yaml", http.HandlerFunc(clusterregistrationtokens.ClusterImportHandler))
root.Handle("/v3/connect", connectHandler)
Expand All @@ -79,11 +80,11 @@ func Start(ctx context.Context, httpPort, httpsPort int, scaledContext *config.S
root.PathPrefix("/k8s/clusters/").Handler(authedHandler)
root.PathPrefix("/meta").Handler(authedHandler)
root.PathPrefix("/v1-telemetry").Handler(authedHandler)
root.NotFoundHandler = ui.UI(http.NotFoundHandler())
root.NotFoundHandler = chain.Handler(http.NotFoundHandler())
root.PathPrefix("/v1-saml").Handler(samlRoot)

// UI
uiContent := ui.Content()
uiContent := responsewriter.NewMiddlewareChain(responsewriter.Gzip, responsewriter.CacheMiddleware("json", "js", "css")).Handler(ui.Content())
root.PathPrefix("/assets").Handler(uiContent)
root.PathPrefix("/translations").Handler(uiContent)
root.Handle("/humans.txt", uiContent)
Expand Down

0 comments on commit fe353c4

Please sign in to comment.