web-server/cache.go

74 lines
1.4 KiB
Go

package main
import (
"net/http"
)
type Response struct {
Code int
Headers map[string][]string
Body []byte
}
func (r Response) WriteResponse(rw http.ResponseWriter) {
for k, vs := range r.Headers {
for _, v := range vs {
rw.Header().Add(k, v)
}
}
rw.WriteHeader(r.Code)
rw.Write(r.Body)
}
// implements ResponseWriter to collect HTTP responses
type ResponseCollector struct {
Response
}
func (rc *ResponseCollector) Header() http.Header {
return rc.Headers
}
func (rc *ResponseCollector) Write(bs []byte) (int, error) {
rc.Body = append(rc.Body, bs...)
return len(bs), nil
}
func (rc *ResponseCollector) WriteHeader(code int) {
rc.Code = code
}
func (rc *ResponseCollector) CollectResponse() Response {
return rc.Response
}
type cacheEntry struct {
r Response
}
func Cache(h http.Handler) http.Handler {
c := make(map[string]cacheEntry)
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
rw.WriteHeader(403)
rw.Write([]byte("invalid request type"))
return
}
entry, exists := c[r.URL.String()]
if exists {
entry.r.WriteResponse(rw)
} else {
rc := ResponseCollector{}
// copy request in case they modify it
req := *r
h.ServeHTTP(&rc, &req)
resp := rc.CollectResponse()
c[r.URL.String()] = cacheEntry{resp}
resp.WriteResponse(rw)
}
// TODO bookkeeping for the cache here
})
}