Add nocache headers to static scouting serving.
This should fix things going forward, but anyone who loaded the page
previously will probably have to clear their cache to be sure.
Change-Id: I40299ade3e2235a5f86ed0e8376155de2a54ac84
Signed-off-by: Alex Perry <alex.perry96@gmail.com>
diff --git a/scouting/webserver/static/static.go b/scouting/webserver/static/static.go
index e921b0b..57824d9 100644
--- a/scouting/webserver/static/static.go
+++ b/scouting/webserver/static/static.go
@@ -3,12 +3,37 @@
// A year agnostic way to serve static http files.
import (
"net/http"
+ "time"
"github.com/frc971/971-Robot-Code/scouting/webserver/server"
)
+// We want the static files (which include JS that is modified over time), to not be cached.
+// This ensures users get updated versions when uploaded to the server.
+// Based on https://stackoverflow.com/a/33881296, this disables cache for most browsers.
+var epoch = time.Unix(0, 0).Format(time.RFC1123)
+
+var noCacheHeaders = map[string]string{
+ "Expires": epoch,
+ "Cache-Control": "no-cache, private, max-age=0",
+ "Pragma": "no-cache",
+ "X-Accel-Expires": "0",
+}
+
+func NoCache(h http.Handler) http.Handler {
+ fn := func(w http.ResponseWriter, r *http.Request) {
+ for k, v := range noCacheHeaders {
+ w.Header().Set(k, v)
+ }
+
+ h.ServeHTTP(w, r)
+ }
+
+ return http.HandlerFunc(fn)
+}
+
// Serve pages given a port, directory to serve from, and an channel to pass the errors back to the caller.
func ServePages(scoutingServer server.ScoutingServer, directory string) {
// Serve the / endpoint given a folder of pages.
- scoutingServer.Handle("/", http.FileServer(http.Dir(directory)))
+ scoutingServer.Handle("/", NoCache(http.FileServer(http.Dir(directory))))
}
diff --git a/scouting/webserver/static/static_test.go b/scouting/webserver/static/static_test.go
index 15bd872..3524c05 100644
--- a/scouting/webserver/static/static_test.go
+++ b/scouting/webserver/static/static_test.go
@@ -36,6 +36,27 @@
scoutingServer.Stop()
}
+func TestCache(t *testing.T) {
+ scoutingServer := server.NewScoutingServer()
+ ServePages(scoutingServer, "test_pages")
+ scoutingServer.Start(8080)
+
+ resp, err := http.Get("http://localhost:8080/root.txt")
+ if err != nil {
+ t.Fatalf("Failed to get data ", err)
+ }
+ compareString(resp.Header.Get("Expires"), "Thu, 01 Jan 1970 00:00:00 UTC", t)
+ compareString(resp.Header.Get("Cache-Control"), "no-cache, private, max-age=0", t)
+ compareString(resp.Header.Get("Pragma"), "no-cache", t)
+ compareString(resp.Header.Get("X-Accel-Expires"), "0", t)
+}
+
+func compareString(actual string, expected string, t *testing.T) {
+ if actual != expected {
+ t.Errorf("Expected ", actual, " to equal ", expected)
+ }
+}
+
// Retrieves the data at the specified path. If an error occurs, the test case
// is terminated and failed.
func getData(path string, t *testing.T) string {