diff --git a/internal/docker/idlewatcher/waker_http.go b/internal/docker/idlewatcher/waker_http.go index cb95f10..b3b7c9b 100644 --- a/internal/docker/idlewatcher/waker_http.go +++ b/internal/docker/idlewatcher/waker_http.go @@ -12,6 +12,21 @@ import ( "github.com/yusing/go-proxy/internal/watcher/health" ) +type ForceCacheControl struct { + expires string + http.ResponseWriter +} + +func (f *ForceCacheControl) WriteHeader(code int) { + f.ResponseWriter.Header().Set("Cache-Control", "must-revalidate") + f.ResponseWriter.Header().Set("Expires", f.expires) + f.ResponseWriter.WriteHeader(code) +} + +func (f *ForceCacheControl) Unwrap() http.ResponseWriter { + return f.ResponseWriter +} + // ServeHTTP implements http.Handler. func (w *Watcher) ServeHTTP(rw http.ResponseWriter, r *http.Request) { shouldNext := w.wakeFromHTTP(rw, r) @@ -22,7 +37,8 @@ func (w *Watcher) ServeHTTP(rw http.ResponseWriter, r *http.Request) { case <-r.Context().Done(): return default: - w.rp.ServeHTTP(rw, r) + f := &ForceCacheControl{expires: w.expires().Format(http.TimeFormat), ResponseWriter: rw} + w.rp.ServeHTTP(f, r) } } @@ -53,7 +69,7 @@ func (w *Watcher) wakeFromHTTP(rw http.ResponseWriter, r *http.Request) (shouldN body := w.makeLoadingPageBody() rw.Header().Set("Content-Type", "text/html; charset=utf-8") rw.Header().Set("Content-Length", strconv.Itoa(len(body))) - rw.Header().Add("Cache-Control", "no-cache") + rw.Header().Set("Cache-Control", "no-cache") rw.Header().Add("Cache-Control", "no-store") rw.Header().Add("Cache-Control", "must-revalidate") rw.Header().Add("Connection", "close") diff --git a/internal/docker/idlewatcher/watcher.go b/internal/docker/idlewatcher/watcher.go index 45c0817..8451880 100644 --- a/internal/docker/idlewatcher/watcher.go +++ b/internal/docker/idlewatcher/watcher.go @@ -32,6 +32,7 @@ type ( client *D.SharedClient stopByMethod StopCallback // send a docker command w.r.t. `stop_method` ticker *time.Ticker + lastReset time.Time task *task.Task } @@ -207,6 +208,11 @@ func (w *Watcher) getStopCallback() StopCallback { func (w *Watcher) resetIdleTimer() { w.Trace().Msg("reset idle timer") w.ticker.Reset(w.IdleTimeout) + w.lastReset = time.Now() +} + +func (w *Watcher) expires() time.Time { + return w.lastReset.Add(w.IdleTimeout) } func (w *Watcher) getEventCh(dockerWatcher watcher.DockerWatcher) (eventCh <-chan events.Event, errCh <-chan E.Error) {