Repository: istio/fortio (go)

Issue:
data caching
I noticed when flipping through results

```
15:14:01 I http_server.go:391> Data: GET /data/ing-to-f1.json HTTP/1.1 [::1]:54081 ()
15:14:01 I http_server.go:391> Data: GET /data/ing-to-f2.json HTTP/1.1 [::1]:54081 ()
15:14:02 I http_server.go:391> Data: GET /data/ing-to-f1.json HTTP/1.1 [::1]:54081 ()
15:14:02 I http_server.go:391> Data: GET /data/f2-to-f1.json HTTP/1.1 [::1]:54081 ()
15:14:02 I http_server.go:391> Data: GET /data/f1-to-f2.json HTTP/1.1 [::1]:54081 ()
```

and 
```
HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Content-Length: 6419
Content-Type: application/json
Last-Modified: Fri, 23 Mar 2018 21:40:09 GMT
Date: Fri, 23 Mar 2018 22:14:02 GMT
```

we should use the same cache control as the static resources


Pull request description:
Use cache for data serve (except index)
Fixes #216

Patch:
diff --git a/fhttp/http_server.go b/fhttp/http_server.go
index 701e9cb..a9e71cf 100644
--- a/fhttp/http_server.go
+++ b/fhttp/http_server.go
@@ -304,6 +304,11 @@ func DebugHandler(w http.ResponseWriter, r *http.Request) {
 	}
 }
 
+// CacheOn sets the header for indefinite caching.
+func CacheOn(w http.ResponseWriter) {
+	w.Header().Set("Cache-Control", "max-age=365000000, immutable")
+}
+
 // Serve starts a debug / echo http server on the given port.
 // Returns the mux and addr where the listening socket is bound.
 // The .Port can be retrieved from it when requesting the 0 port as
diff --git a/ui/uihandler.go b/ui/uihandler.go
index eeb5a1e..ea71888 100644
--- a/ui/uihandler.go
+++ b/ui/uihandler.go
@@ -437,7 +437,7 @@ func LogAndAddCacheControl(h http.Handler) http.Handler {
 			r.URL.Path = "/static/img" + faviconPath // fortio/version expected to be stripped already
 			log.LogVf("Changed favicon internal path to %s", r.URL.Path)
 		}
-		w.Header().Set("Cache-Control", "max-age=365000000, immutable")
+		fhttp.CacheOn(w)
 		h.ServeHTTP(w, r)
 	})
 }
@@ -550,6 +550,7 @@ func LogAndFilterDataRequest(h http.Handler) http.Handler {
 			w.WriteHeader(http.StatusNotFound)
 			return
 		}
+		fhttp.CacheOn(w)
 		h.ServeHTTP(w, r)
 	})
 }


Test patch:
diff --git a/fhttp/http_test.go b/fhttp/http_test.go
index 1287a65..dde57d5 100644
--- a/fhttp/http_test.go
+++ b/fhttp/http_test.go
@@ -767,6 +767,35 @@ func TestServeError(t *testing.T) {
 	}
 }
 
+func testCacheHeaderHandler(w http.ResponseWriter, r *http.Request) {
+	LogRequest(r, "testCacheHeader")
+	CacheOn(w)
+	w.Write([]byte("cache me"))
+}
+
+func TestCache(t *testing.T) {
+	mux, addr := Serve("0", "")
+	mux.HandleFunc("/cached", testCacheHeaderHandler)
+	baseURL := fmt.Sprintf("http://localhost:%d/", addr.Port)
+	o := NewHTTPOptions(baseURL)
+	code, data := Fetch(o)
+	if code != 200 {
+		t.Errorf("error fetching %s: %v %s", o.URL, code, DebugSummary(data, 256))
+	}
+	expectedWithCache := []byte("Cache-Control:")
+	if bytes.Contains(data, expectedWithCache) {
+		t.Errorf("Got %s when shouldn't have for %s: %v", expectedWithCache, o.URL, DebugSummary(data, 256))
+	}
+	o.URL += "cached"
+	code, data = Fetch(o)
+	if code != 200 {
+		t.Errorf("error fetching %s: %v %s", o.URL, code, DebugSummary(data, 256))
+	}
+	if !bytes.Contains(data, expectedWithCache) {
+		t.Errorf("Didn't get %s when should have for %s: %v", expectedWithCache, o.URL, DebugSummary(data, 256))
+	}
+}
+
 func TestRedirector(t *testing.T) {
 	addr := RedirectToHTTPS(":0")
 	relativeURL := "/foo/bar?some=param&anotherone"