github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/pkg/assets/middleware.go (about)

     1  package assets
     2  
     3  import (
     4  	"net/http"
     5  	"strings"
     6  )
     7  
     8  // Middleware that attaches a server at a subpath.
     9  // Modeled after http.StripPrefix, but attaches the work it did to the Request Context.
    10  func StripPrefix(prefix string, h http.Handler) http.Handler {
    11  	if prefix == "" {
    12  		return h
    13  	}
    14  
    15  	delegate := http.StripPrefix(prefix, h)
    16  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    17  		if p := strings.TrimPrefix(r.URL.Path, prefix); len(p) < len(r.URL.Path) {
    18  			// If the prefix was stripped successfully, add it to the context.
    19  			r = appendPublicPathPrefix(prefix, r)
    20  		}
    21  		delegate.ServeHTTP(w, r)
    22  	})
    23  }
    24  
    25  func isAssetPath(path string) bool {
    26  	return strings.HasPrefix(path, "/static/") || path == "/favicon.ico" || path == "/manifest.json"
    27  }
    28  
    29  type cacheWriter struct {
    30  	writer               http.ResponseWriter
    31  	assetPath, reqMethod string
    32  }
    33  
    34  func (w cacheWriter) Header() http.Header {
    35  	return w.writer.Header()
    36  }
    37  
    38  func (w cacheWriter) Write(b []byte) (int, error) {
    39  	return w.writer.Write(b)
    40  }
    41  
    42  func (w cacheWriter) WriteHeader(statusCode int) {
    43  	if statusCode == 200 && w.reqMethod == http.MethodGet {
    44  		// Set caching headers according to this doc:
    45  		// https://create-react-app.dev/docs/production-build/#static-file-caching
    46  		//
    47  		// Static artifacts are checksummed and can be cached indefinitely
    48  		// The main index html page should never be cached.
    49  		cacheControl := "no-store, max-age=0"
    50  		if isAssetPath(w.assetPath) {
    51  			cacheControl = "public, max-age=31536000"
    52  		}
    53  		w.writer.Header().Set("Cache-Control", cacheControl)
    54  	}
    55  	w.writer.WriteHeader(statusCode)
    56  }
    57  
    58  func cacheAssets(w http.ResponseWriter, assetPath, reqMethod string) http.ResponseWriter {
    59  	return cacheWriter{
    60  		writer:    w,
    61  		assetPath: assetPath,
    62  		reqMethod: reqMethod,
    63  	}
    64  }