add Cache-Control headers to ocsp-responder
Also, adds a JSONDuration to clean up some of the config code. It will get used more in later PRs. Fixes #797
This commit is contained in:
parent
7a10b3c546
commit
601cf9f0fb
|
@ -27,6 +27,16 @@ import (
|
|||
"github.com/letsencrypt/boulder/sa"
|
||||
)
|
||||
|
||||
type cacheCtrlHandler struct {
|
||||
http.Handler
|
||||
MaxAge time.Duration
|
||||
}
|
||||
|
||||
func (c *cacheCtrlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%d", c.MaxAge/time.Second))
|
||||
c.Handler.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
/*
|
||||
DBSource maps a given Database schema to a CA Key Hash, so we can pick
|
||||
from among them when presented with OCSP requests for different certs.
|
||||
|
@ -158,9 +168,9 @@ func main() {
|
|||
killTimeout, err := time.ParseDuration(c.OCSPResponder.ShutdownKillTimeout)
|
||||
cmd.FailOnError(err, "Couldn't parse shutdown kill timeout")
|
||||
|
||||
// Configure HTTP
|
||||
m := http.NewServeMux()
|
||||
m.Handle(c.OCSPResponder.Path, cfocsp.Responder{Source: source})
|
||||
m.Handle(c.OCSPResponder.Path,
|
||||
handler(source, c.OCSPResponder.MaxAge.Duration))
|
||||
|
||||
httpMonitor := metrics.NewHTTPMonitor(stats, m, "OCSP")
|
||||
srv := &http.Server{
|
||||
|
@ -179,3 +189,10 @@ func main() {
|
|||
|
||||
app.Run()
|
||||
}
|
||||
|
||||
func handler(src cfocsp.Source, maxAge time.Duration) http.Handler {
|
||||
return &cacheCtrlHandler{
|
||||
Handler: cfocsp.Responder{Source: src},
|
||||
MaxAge: maxAge,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1,26 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp"
|
||||
)
|
||||
|
||||
func TestCacheControl(t *testing.T) {
|
||||
src := make(ocsp.InMemorySource)
|
||||
h := handler(src, 10*time.Second)
|
||||
w := httptest.NewRecorder()
|
||||
r, err := http.NewRequest("GET", "/", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h.ServeHTTP(w, r)
|
||||
expected := "max-age=10"
|
||||
actual := w.Header().Get("Cache-Control")
|
||||
if actual != expected {
|
||||
t.Errorf("Cache-Control value: want %#v, got %#v", expected, actual)
|
||||
}
|
||||
}
|
||||
|
|
27
cmd/shell.go
27
cmd/shell.go
|
@ -159,6 +159,9 @@ type Config struct {
|
|||
|
||||
Path string
|
||||
ListenAddress string
|
||||
// MaxAge is the max-age to set in the Cache-Controler response
|
||||
// header. It is a time.Duration formatted string.
|
||||
MaxAge JSONDuration
|
||||
|
||||
ShutdownStopTimeout string
|
||||
ShutdownKillTimeout string
|
||||
|
@ -392,3 +395,27 @@ func DebugServer(addr string) {
|
|||
log.Printf("booting debug server at %#v", addr)
|
||||
log.Println(http.Serve(ln, nil))
|
||||
}
|
||||
|
||||
type JSONDuration struct {
|
||||
time.Duration
|
||||
}
|
||||
|
||||
var ErrDurationMustBeString = errors.New("cannot JSON unmarshal something other than a string into a JSONDuration")
|
||||
|
||||
func (d *JSONDuration) UnmarshalJSON(b []byte) error {
|
||||
s := ""
|
||||
err := json.Unmarshal(b, &s)
|
||||
if err != nil {
|
||||
if _, ok := err.(*json.UnmarshalTypeError); ok {
|
||||
return ErrDurationMustBeString
|
||||
}
|
||||
return err
|
||||
}
|
||||
dd, err := time.ParseDuration(s)
|
||||
d.Duration = dd
|
||||
return err
|
||||
}
|
||||
|
||||
func (d JSONDuration) MarshalJSON() ([]byte, error) {
|
||||
return []byte(d.Duration.String()), nil
|
||||
}
|
||||
|
|
|
@ -148,6 +148,7 @@
|
|||
"source": "mysql+tcp://boulder@localhost:3306/boulder_sa_integration",
|
||||
"path": "/",
|
||||
"listenAddress": "localhost:4002",
|
||||
"maxAge": "10s",
|
||||
"shutdownStopTimeout": "10s",
|
||||
"shutdownKillTimeout": "1m",
|
||||
"debugAddr": "localhost:8005"
|
||||
|
|
Loading…
Reference in New Issue