github.com/vmware/transport-go@v1.3.4/plank/pkg/server/spa_config.go (about) 1 // Copyright 2019-2021 VMware, Inc. 2 // SPDX-License-Identifier: BSD-2-Clause 3 4 package server 5 6 import ( 7 "github.com/gorilla/mux" 8 "github.com/vmware/transport-go/plank/pkg/middleware" 9 "github.com/vmware/transport-go/plank/utils" 10 "net/http" 11 "regexp" 12 ) 13 14 // SpaConfig shorthand for SinglePageApplication Config is used to configure routes for your SPAs like 15 // Angular or React. for example if your app index.html is served at /app and static contents like JS/CSS 16 // are served from /app/static, BaseUri can be set to /app and StaticAssets to "/app/assets". see config.json 17 // for details. 18 type SpaConfig struct { 19 RootFolder string `json:"root_folder"` // location where Plank will serve SPA 20 BaseUri string `json:"base_uri"` // base URI for the SPA 21 StaticAssets []string `json:"static_assets"` // locations for static assets used by the SPA 22 CacheControlRules map[string]string `json:"cache_control_rules"` // map holding glob pattern - cache-control header value 23 24 cacheControlRulePairs []middleware.CacheControlRulePair 25 } 26 27 type regexCacheControlRulePair struct { 28 regex *regexp.Regexp 29 cacheControlRule string 30 } 31 32 // NewSpaConfig takes location to where the SPA content is as an input and returns a sanitized 33 // instance of *SpaConfig. 34 func NewSpaConfig(input string) (spaConfig *SpaConfig, err error) { 35 p, uri := utils.DeriveStaticURIFromPath(input) 36 spaConfig = &SpaConfig{ 37 RootFolder: p, 38 BaseUri: uri, 39 CacheControlRules: make(map[string]string), 40 cacheControlRulePairs: make([]middleware.CacheControlRulePair, 0), 41 } 42 43 spaConfig.CollateCacheControlRules() 44 return spaConfig, err 45 } 46 47 // CollateCacheControlRules compiles glob patterns and stores them as an array. 48 func (s *SpaConfig) CollateCacheControlRules() { 49 for globP, rule := range s.CacheControlRules { 50 pair, err := middleware.NewCacheControlRulePair(globP, rule) 51 if err != nil { 52 utils.Log.Errorln("Ignoring invalid glob pattern provided as cache control matcher rule", err) 53 continue 54 } 55 56 s.cacheControlRulePairs = append(s.cacheControlRulePairs, pair) 57 } 58 } 59 60 // CacheControlMiddleware returns the middleware func to be used in route configuration 61 func (s *SpaConfig) CacheControlMiddleware() mux.MiddlewareFunc { 62 return func(handler http.Handler) http.Handler { 63 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 64 // apply cache control rule that matches first 65 for _, pair := range s.cacheControlRulePairs { 66 if pair.CompiledGlobPattern.Match(r.RequestURI) { 67 w.Header().Set("Cache-Control", pair.CacheControlRule) 68 break 69 } 70 } 71 handler.ServeHTTP(w, r) 72 }) 73 } 74 }