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  }