ARI: write Retry-After header before body (#6787)

When sending an ARI response, write the Retry-After header before
writing the JSON response body. This is necessary because
http.ResponseWriter implicitly calls WriteHeader whenever Write is
called, flushing all headers to the network and preventing any
additional headers from being written. Unfortunately, the unittests use
httptest.ResponseRecorder, which doesn't seem to enforce this invariant
(it's happy to report headers which were written after the body). Add a
header check to the integration tests, to make up for this deficiency.
This commit is contained in:
Aaron Gable 2023-03-31 10:48:45 -07:00 committed by GitHub
parent 9262ca6e3f
commit 22fd579cf2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 5 additions and 11 deletions

View File

@ -73,7 +73,9 @@
"staleTimeout": "5m",
"authorizationLifetimeDays": 30,
"pendingAuthorizationLifetimeDays": 7,
"features": {}
"features": {
"ServeRenewalInfo": true
}
},
"syslog": {
"stdoutlevel": 4,

View File

@ -16,7 +16,6 @@ import (
"math/big"
"net/http"
"os"
"strings"
"testing"
"time"
@ -36,10 +35,6 @@ type certID struct {
func TestARI(t *testing.T) {
t.Parallel()
// This test is gated on the ServeRenewalInfo feature flag.
if !strings.Contains(os.Getenv("BOULDER_CONFIG_DIR"), "test/config-next") {
return
}
// Create an account.
os.Setenv("DIRECTORY", "http://boulder.service.consul:4001/directory")
@ -82,6 +77,7 @@ func TestARI(t *testing.T) {
resp, err := http.Get(url)
test.AssertNotError(t, err, "ARI request should have succeeded")
test.AssertEquals(t, resp.StatusCode, http.StatusOK)
test.AssertEquals(t, resp.Header.Get("Retry-After"), "21600")
// Revoke the cert, then request ARI again, and the window should now be in
// the past.

View File

@ -2293,17 +2293,13 @@ func (wfe *WebFrontEndImpl) RenewalInfo(ctx context.Context, logEvent *web.Reque
serial := core.SerialToString(id.SerialNumber)
logEvent.Extra["RequestedSerial"] = serial
setDefaultRetryAfterHeader := func(response http.ResponseWriter) {
response.Header().Set(headerRetryAfter, fmt.Sprintf("%d", int(6*time.Hour/time.Second)))
}
sendRI := func(ri core.RenewalInfo) {
response.Header().Set(headerRetryAfter, fmt.Sprintf("%d", int(6*time.Hour/time.Second)))
err = wfe.writeJsonResponse(response, logEvent, http.StatusOK, ri)
if err != nil {
wfe.sendError(response, logEvent, probs.ServerInternal("Error marshalling renewalInfo"), err)
return
}
setDefaultRetryAfterHeader(response)
}
// Check if the serial is part of an ongoing/active incident, in which case