Send an Allow header whenever we send 405

This commit is contained in:
Richard Barnes 2015-06-11 22:12:01 -04:00
parent 32531c7f24
commit d398bd962a
2 changed files with 60 additions and 1 deletions

View File

@ -113,6 +113,8 @@ func (wfe *WebFrontEndImpl) HandlePaths() {
// Method implementations
func (wfe *WebFrontEndImpl) Index(response http.ResponseWriter, request *http.Request) {
wfe.sendNonce(response)
// http://golang.org/pkg/net/http/#example_ServeMux_Handle
// The "/" pattern matches everything, so we need to check
// that we're at the root here.
@ -121,6 +123,11 @@ func (wfe *WebFrontEndImpl) Index(response http.ResponseWriter, request *http.Re
return
}
if request.Method != "GET" {
sendAllow(response, "GET")
wfe.sendError(response, "Method not allowed", request.Method, http.StatusMethodNotAllowed)
}
tmpl := template.Must(template.New("body").Parse(`<html>
<body>
This is an <a href="https://github.com/letsencrypt/acme-spec/">ACME</a>
@ -155,6 +162,10 @@ const (
ServerInternalProblem = ProblemType("urn:acme:error:serverInternal")
)
func sendAllow(response http.ResponseWriter, methods ...string) {
response.Header().Set("Allow", strings.Join(methods, ", "))
}
func (wfe *WebFrontEndImpl) sendNonce(response http.ResponseWriter) {
response.Header().Set("Replay-Nonce", wfe.nonceService.Nonce())
}
@ -269,6 +280,7 @@ func (wfe *WebFrontEndImpl) NewRegistration(response http.ResponseWriter, reques
wfe.sendNonce(response)
if request.Method != "POST" {
sendAllow(response, "POST")
wfe.sendError(response, "Method not allowed", "", http.StatusMethodNotAllowed)
return
}
@ -330,6 +342,7 @@ func (wfe *WebFrontEndImpl) NewAuthorization(response http.ResponseWriter, reque
wfe.sendNonce(response)
if request.Method != "POST" {
sendAllow(response, "POST")
wfe.sendError(response, "Method not allowed", request.Method, http.StatusMethodNotAllowed)
return
}
@ -389,6 +402,7 @@ func (wfe *WebFrontEndImpl) RevokeCertificate(response http.ResponseWriter, requ
wfe.sendNonce(response)
if request.Method != "POST" {
sendAllow(response, "POST")
wfe.sendError(response, "Method not allowed", request.Method, http.StatusMethodNotAllowed)
return
}
@ -466,6 +480,7 @@ func (wfe *WebFrontEndImpl) NewCertificate(response http.ResponseWriter, request
wfe.sendNonce(response)
if request.Method != "POST" {
sendAllow(response, "POST")
wfe.sendError(response, "Method not allowed", request.Method, http.StatusMethodNotAllowed)
return
}
@ -539,6 +554,7 @@ func (wfe *WebFrontEndImpl) Challenge(authz core.Authorization, response http.Re
wfe.sendNonce(response)
if request.Method != "GET" && request.Method != "POST" {
sendAllow(response, "GET", "POST")
wfe.sendError(response, "Method not allowed", request.Method, http.StatusMethodNotAllowed)
return
}
@ -562,6 +578,7 @@ func (wfe *WebFrontEndImpl) Challenge(authz core.Authorization, response http.Re
switch request.Method {
default:
sendAllow(response, "GET", "POST")
wfe.sendError(response, "Method not allowed", "", http.StatusMethodNotAllowed)
return
@ -648,6 +665,7 @@ func (wfe *WebFrontEndImpl) Registration(response http.ResponseWriter, request *
wfe.sendNonce(response)
if request.Method != "POST" {
sendAllow(response, "POST")
wfe.sendError(response, "Method not allowed", request.Method, http.StatusMethodNotAllowed)
return
}
@ -721,6 +739,7 @@ func (wfe *WebFrontEndImpl) Authorization(response http.ResponseWriter, request
wfe.sendNonce(response)
if request.Method != "GET" && request.Method != "POST" {
sendAllow(response, "GET", "POST")
wfe.sendError(response, "Method not allowed", request.Method, http.StatusMethodNotAllowed)
return
}
@ -743,6 +762,7 @@ func (wfe *WebFrontEndImpl) Authorization(response http.ResponseWriter, request
switch request.Method {
default:
sendAllow(response, "GET", "POST")
wfe.sendError(response, "Method not allowed", request.Method, http.StatusMethodNotAllowed)
return
@ -771,6 +791,7 @@ func (wfe *WebFrontEndImpl) Certificate(response http.ResponseWriter, request *h
wfe.sendNonce(response)
if request.Method != "GET" && request.Method != "POST" {
sendAllow(response, "GET", "POST")
wfe.sendError(response, "Method not allowed", request.Method, http.StatusMethodNotAllowed)
return
}
@ -778,6 +799,7 @@ func (wfe *WebFrontEndImpl) Certificate(response http.ResponseWriter, request *h
path := request.URL.Path
switch request.Method {
default:
sendAllow(response, "GET", "POST")
wfe.sendError(response, "Method not allowed", request.Method, http.StatusMethodNotAllowed)
return
@ -819,6 +841,7 @@ func (wfe *WebFrontEndImpl) Terms(response http.ResponseWriter, request *http.Re
wfe.sendNonce(response)
if request.Method != "GET" {
sendAllow(response, "GET")
wfe.sendError(response, "Method not allowed", request.Method, http.StatusMethodNotAllowed)
return
}
@ -830,6 +853,7 @@ func (wfe *WebFrontEndImpl) Issuer(response http.ResponseWriter, request *http.R
wfe.sendNonce(response)
if request.Method != "GET" {
sendAllow(response, "GET")
wfe.sendError(response, "Method not allowed", request.Method, http.StatusMethodNotAllowed)
return
}
@ -847,6 +871,7 @@ func (wfe *WebFrontEndImpl) BuildID(response http.ResponseWriter, request *http.
wfe.sendNonce(response)
if request.Method != "GET" {
sendAllow(response, "GET")
wfe.sendError(response, "Method not allowed", request.Method, http.StatusMethodNotAllowed)
return
}

View File

@ -298,6 +298,39 @@ func setupWFE() WebFrontEndImpl {
return wfe
}
func TestMethodNotAllowed(t *testing.T) {
wfe := setupWFE()
cases := []struct {
path string
handler func(http.ResponseWriter, *http.Request)
allowed []string
}{
{"/", wfe.Index, []string{"GET"}},
{wfe.NewReg, wfe.NewRegistration, []string{"POST"}},
{wfe.RegBase, wfe.Registration, []string{"POST"}},
{wfe.NewAuthz, wfe.NewAuthorization, []string{"POST"}},
{wfe.AuthzBase, wfe.Authorization, []string{"GET", "POST"}},
{wfe.NewCert, wfe.NewCertificate, []string{"POST"}},
{wfe.CertBase, wfe.Certificate, []string{"GET", "POST"}},
{wfe.SubscriberAgreementURL, wfe.Terms, []string{"GET"}},
}
for _, c := range cases {
responseWriter := httptest.NewRecorder()
url, _ := url.Parse(c.path)
c.handler(responseWriter, &http.Request{
Method: "BOGUS",
URL: url,
})
nonce := responseWriter.Header().Get("Replay-Nonce")
allow := responseWriter.Header().Get("Allow")
test.Assert(t, responseWriter.Code == http.StatusMethodNotAllowed, "Bogus method allowed")
test.Assert(t, len(nonce) > 0, "Bad Replay-Nonce header")
test.Assert(t, len(allow) > 0 && allow == strings.Join(c.allowed, ", "), "Bad Allow header")
}
}
func TestIndex(t *testing.T) {
wfe := setupWFE()
@ -305,7 +338,8 @@ func TestIndex(t *testing.T) {
url, _ := url.Parse("/")
wfe.Index(responseWriter, &http.Request{
URL: url,
Method: "GET",
URL: url,
})
test.AssertEquals(t, responseWriter.Code, http.StatusOK)
test.AssertNotEquals(t, responseWriter.Body.String(), "404 page not found\n")