diff --git a/wfe/web-front-end.go b/wfe/web-front-end.go index 7183b949e..0b2c9fbf5 100644 --- a/wfe/web-front-end.go +++ b/wfe/web-front-end.go @@ -188,6 +188,10 @@ func (wfe *WebFrontEndImpl) HandleFunc(mux *http.ServeMux, pattern string, h wfe }) } +func marshalIndent(v interface{}) ([]byte, error) { + return json.MarshalIndent(v, "", " ") +} + // Handler returns an http.Handler that uses various functions for // various ACME-specified paths. func (wfe *WebFrontEndImpl) Handler() (http.Handler, error) { @@ -206,7 +210,7 @@ func (wfe *WebFrontEndImpl) Handler() (http.Handler, error) { "new-cert": wfe.NewCert, "revoke-cert": wfe.BaseURL + RevokeCertPath, } - directoryJSON, err := json.Marshal(directory) + directoryJSON, err := marshalIndent(directory) if err != nil { return nil, err } @@ -470,7 +474,7 @@ func (wfe *WebFrontEndImpl) sendError(response http.ResponseWriter, logEvent *re wfe.log.AuditErr(fmt.Errorf("Internal error - %s - %s", prob.Detail, ierr)) } - problemDoc, err := json.Marshal(prob) + problemDoc, err := marshalIndent(prob) if err != nil { // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 wfe.log.AuditErr(fmt.Errorf("Could not marshal error message: %s - %+v", err, prob)) @@ -547,7 +551,7 @@ func (wfe *WebFrontEndImpl) NewRegistration(ctx context.Context, logEvent *reque // Use an explicitly typed variable. Otherwise `go vet' incorrectly complains // that reg.ID is a string being passed to %d. regURL := fmt.Sprintf("%s%d", wfe.RegBase, reg.ID) - responseBody, err := json.Marshal(reg) + responseBody, err := marshalIndent(reg) if err != nil { // ServerInternal because we just created this registration, and it // should be OK. @@ -603,7 +607,7 @@ func (wfe *WebFrontEndImpl) NewAuthorization(ctx context.Context, logEvent *requ // Make a URL for this authz, then blow away the ID and RegID before serializing authzURL := wfe.AuthzBase + string(authz.ID) wfe.prepAuthorizationForDisplay(&authz) - responseBody, err := json.Marshal(authz) + responseBody, err := marshalIndent(authz) if err != nil { // ServerInternal because we generated the authz, it should be OK wfe.sendError(response, logEvent, probs.ServerInternal("Error marshaling authz"), err) @@ -890,7 +894,7 @@ func (wfe *WebFrontEndImpl) getChallenge( wfe.prepChallengeForDisplay(authz, challenge) - jsonReply, err := json.Marshal(challenge) + jsonReply, err := marshalIndent(challenge) if err != nil { // InternalServerError because this is a failure to decode data passed in // by the caller, which got it from the DB. @@ -962,7 +966,7 @@ func (wfe *WebFrontEndImpl) postChallenge( // assumption: UpdateAuthorization does not modify order of challenges challenge := updatedAuthorization.Challenges[challengeIndex] wfe.prepChallengeForDisplay(authz, &challenge) - jsonReply, err := json.Marshal(challenge) + jsonReply, err := marshalIndent(challenge) if err != nil { // ServerInternal because we made the challenges, they should be OK logEvent.AddError("failed to marshal challenge: %s", err) @@ -1040,7 +1044,7 @@ func (wfe *WebFrontEndImpl) Registration(ctx context.Context, logEvent *requestE return } - jsonReply, err := json.Marshal(updatedReg) + jsonReply, err := marshalIndent(updatedReg) if err != nil { // ServerInternal because we just generated the reg, it should be OK logEvent.AddError("unable to marshal updated registration: %s", err) @@ -1084,7 +1088,7 @@ func (wfe *WebFrontEndImpl) Authorization(ctx context.Context, logEvent *request wfe.prepAuthorizationForDisplay(&authz) - jsonReply, err := json.Marshal(authz) + jsonReply, err := marshalIndent(authz) if err != nil { // InternalServerError because this is a failure to decode from our DB. logEvent.AddError("Failed to JSON marshal authz: %s", err) diff --git a/wfe/web-front-end_test.go b/wfe/web-front-end_test.go index 9d91b7f40..26dbb7b23 100644 --- a/wfe/web-front-end_test.go +++ b/wfe/web-front-end_test.go @@ -18,6 +18,7 @@ import ( "net/http" "net/http/httptest" "net/url" + "reflect" "sort" "strconv" "strings" @@ -279,6 +280,17 @@ func addHeadIfGet(s []string) []string { return s } +func assertJSONEquals(t *testing.T, got, expected string) { + var gotMap, expectedMap map[string]interface{} + err := json.Unmarshal([]byte(got), &gotMap) + test.AssertNotError(t, err, "failed to parse received JSON") + err = json.Unmarshal([]byte(expected), &expectedMap) + test.AssertNotError(t, err, "failed to parse expected JSON") + if !reflect.DeepEqual(gotMap, expectedMap) { + t.Fatalf("JSON response differed from expected:\n Got: %s, Expected: %s", got, expected) + } +} + func TestHandleFunc(t *testing.T) { wfe, _ := setupWFE(t) var mux *http.ServeMux @@ -318,7 +330,7 @@ func TestHandleFunc(t *testing.T) { } else { test.AssertEquals(t, rw.Code, http.StatusMethodNotAllowed) test.AssertEquals(t, sortHeader(rw.Header().Get("Allow")), sortHeader(strings.Join(addHeadIfGet(c.allowed), ", "))) - test.AssertEquals(t, + assertJSONEquals(t, rw.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Method not allowed","status":405}`) } @@ -331,7 +343,7 @@ func TestHandleFunc(t *testing.T) { // Disallowed method returns error JSON in body runWrappedHandler(&http.Request{Method: "PUT"}, "GET", "POST") test.AssertEquals(t, rw.Header().Get("Content-Type"), "application/problem+json") - test.AssertEquals(t, rw.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Method not allowed","status":405}`) + assertJSONEquals(t, rw.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Method not allowed","status":405}`) test.AssertEquals(t, sortHeader(rw.Header().Get("Allow")), "GET, HEAD, POST") // Disallowed method special case: response to HEAD has got no body @@ -345,7 +357,7 @@ func TestHandleFunc(t *testing.T) { test.AssertEquals(t, rw.Code, http.StatusMethodNotAllowed) test.AssertEquals(t, rw.Header().Get("Content-Type"), "application/problem+json") test.AssertEquals(t, rw.Header().Get("Allow"), "POST") - test.AssertEquals(t, rw.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Method not allowed","status":405}`) + assertJSONEquals(t, rw.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Method not allowed","status":405}`) wfe.AllowOrigins = []string{"*"} testOrigin := "https://example.com" @@ -541,7 +553,7 @@ func TestDirectory(t *testing.T) { }) test.AssertEquals(t, responseWriter.Header().Get("Content-Type"), "application/json") test.AssertEquals(t, responseWriter.Code, http.StatusOK) - test.AssertEquals(t, responseWriter.Body.String(), `{"new-authz":"http://localhost:4300/acme/new-authz","new-cert":"http://localhost:4300/acme/new-cert","new-reg":"http://localhost:4300/acme/new-reg","revoke-cert":"http://localhost:4300/acme/revoke-cert"}`) + assertJSONEquals(t, responseWriter.Body.String(), `{"new-authz":"http://localhost:4300/acme/new-authz","new-cert":"http://localhost:4300/acme/new-cert","new-reg":"http://localhost:4300/acme/new-reg","revoke-cert":"http://localhost:4300/acme/revoke-cert"}`) } // TODO: Write additional test cases for: @@ -580,7 +592,7 @@ func TestIssueCertificate(t *testing.T) { Method: "GET", URL: mustParseURL(NewCertPath), }) - test.AssertEquals(t, + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Method not allowed","status":405}`) @@ -592,14 +604,14 @@ func TestIssueCertificate(t *testing.T) { "Content-Length": {"0"}, }, }) - test.AssertEquals(t, + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"No body on POST","status":400}`) // POST, but body that isn't valid JWS responseWriter.Body.Reset() wfe.NewCertificate(ctx, newRequestEvent(), responseWriter, makePostRequest("hi")) - test.AssertEquals(t, + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Parse error reading JWS","status":400}`) @@ -607,7 +619,7 @@ func TestIssueCertificate(t *testing.T) { responseWriter.Body.Reset() wfe.NewCertificate(ctx, newRequestEvent(), responseWriter, makePostRequest(signRequest(t, "foo", wfe.nonceService))) - test.AssertEquals(t, + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Request payload did not parse as JSON","status":400}`) @@ -616,7 +628,7 @@ func TestIssueCertificate(t *testing.T) { wfe.NewCertificate(ctx, newRequestEvent(), responseWriter, makePostRequest( signRequest(t, "{}", wfe.nonceService))) - test.AssertEquals(t, + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Request payload does not specify a resource","status":400}`) @@ -624,7 +636,7 @@ func TestIssueCertificate(t *testing.T) { responseWriter.Body.Reset() wfe.NewCertificate(ctx, newRequestEvent(), responseWriter, makePostRequest(signRequest(t, `{"resource":"new-cert"}`, wfe.nonceService))) - test.AssertEquals(t, + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Error unmarshaling certificate request","status":400}`) @@ -639,7 +651,7 @@ func TestIssueCertificate(t *testing.T) { "resource":"new-cert", "csr": "MIICVzCCAT8CAQAwEjEQMA4GA1UEAwwHZm9iLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKzHhqcMSTVjBu61vufGVmIYM4mMbWXgndHOUWnIqSKcNtFtPQ465tcZRT5ITIZWXGjsmgDrj31qvG3t5qLwyaF5hsTvFHK72nLMAQhdgM6481Qe9yaoaulWpkGr_9LVz4jQ9pGAaLVamXGpSxV-ipTOo79Sev4aZE8ksD9atEfWtcOD9w8_zj74vpWjTAHN49Q88chlChVqakn0zSfHPfS-jF8g0UTddBuF0Ti3sZChjxzbo6LwZ4182xX7XPnOLav3AGj0Su7j5XMl3OpenOrlWulWJeZIHq5itGW321j306XiGdbrdWH4K7JygICFds6oolwQRGBY6yinAtCgkTcCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQBxPiHOtKuBxtvecMNtLkTSuTyEkusQGnjoFDaKe5oqwGYQgy0YBii2-BbaPmqS4ZaDc-vDz_RLeKH5ZiH-NliYR1V_CRtpFLQi18g_2pLQnZLVO3ENs-SM37nU_nBGn9O93t2bkssoM3fZmtgp3R2W7I_wvx7Z8oWKa4boTeBAg_q9Gmi6QskZBddK7A4S_vOR0frU6QSPK_ksPhvovp9fwb6CVKrlJWf556UwRPWgbkW39hvTxK2KHhrUEg3oawNkWde2jZtnZ9e-9zpw8-_5O0X7-YN0ucbFTfQybce_ReuLlGepiHT5bvVavBZoIvqw1XOgSMvGgZFU8tAWMBlj" }`, wfe.nonceService))) - test.AssertEquals(t, + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:unauthorized","detail":"Error creating new cert :: Invalid signature on CSR","status":403}`) @@ -652,7 +664,7 @@ func TestIssueCertificate(t *testing.T) { "resource":"new-cert", "csr": "MIICWDCCAUACAQAwEzERMA8GA1UEAwwIbWVlcC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaqzue57mgXEoGTZZoVkkCZraebWgXI8irX2BgQB1A3iZa9onxGPMcWQMxhSuUisbEJi4UkMcVST12HX01rUwhj41UuBxJvI1w4wvdstssTAaa9c9tsQ5-UED2bFRL1MsyBdbmCF_-pu3i-ZIYqWgiKbjVBe3nlAVbo77zizwp3Y4Tp1_TBOwTAuFkHePmkNT63uPm9My_hNzsSm1o-Q519Cf7ry-JQmOVgz_jIgFVGFYJ17EV3KUIpUuDShuyCFATBQspgJSN2DoXRUlQjXXkNTj23OxxdT_cVLcLJjytyG6e5izME2R2aCkDBWIc1a4_sRJ0R396auPXG6KhJ7o_AgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEALu046p76aKgvoAEHFINkMTgKokPXf9mZ4IZx_BKz-qs1MPMxVtPIrQDVweBH6tYT7Hfj2naLry6SpZ3vUNP_FYeTFWgW1V03LiqacX-QQgbEYtn99Dt3ScGyzb7EH833ztb3vDJ_-ha_CJplIrg-kHBBrlLFWXhh-I9K1qLRTNpbhZ18ooFde4Sbhkw9o9fKivGhx9aYr7ZbjRsNtKit_DsG1nwEXz53TMJ2vB9IQY29coJv_n5NFLkvBfzbG5faRNiFcimPYBO2jFdaA2mWzfxltLtwMF_dBwzTXDpMo3TVT9zEdV8YpsWqr63igqGDZVpKenlkqvRTeGJVayVuMA" }`, wfe.nonceService))) - test.AssertEquals(t, + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:unauthorized","detail":"Error creating new cert :: Authorizations for these names not found or expired: meep.com","status":403}`) assertCsrLogged(t, mockLog) @@ -715,7 +727,7 @@ func TestGetChallenge(t *testing.T) { // be discarded by HandleFunc() anyway, so it doesn't // matter what Challenge() writes to it. if method == "GET" { - test.AssertEquals( + assertJSONEquals( t, resp.Body.String(), `{"type":"dns","uri":"/acme/challenge/valid/23"}`) } @@ -748,7 +760,7 @@ func TestChallenge(t *testing.T) { test.AssertEquals( t, responseWriter.Header().Get("Link"), `;rel="up"`) - test.AssertEquals( + assertJSONEquals( t, responseWriter.Body.String(), `{"type":"dns","uri":"/acme/challenge/valid/23"}`) @@ -759,7 +771,7 @@ func TestChallenge(t *testing.T) { makePostRequestWithPath(challengeURL, signRequest(t, `{"resource":"challenge"}`, wfe.nonceService))) test.AssertEquals(t, responseWriter.Code, http.StatusNotFound) - test.AssertEquals(t, responseWriter.Body.String(), + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Expired authorization","status":404}`) } @@ -778,7 +790,7 @@ func TestBadNonce(t *testing.T) { test.AssertNotError(t, err, "Failed to sign body") wfe.NewRegistration(ctx, newRequestEvent(), responseWriter, makePostRequest(result.FullSerialize())) - test.AssertEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:badNonce","detail":"JWS has no anti-replay nonce","status":400}`) + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:badNonce","detail":"JWS has no anti-replay nonce","status":400}`) } func TestNewECDSARegistration(t *testing.T) { @@ -822,7 +834,7 @@ func TestNewECDSARegistration(t *testing.T) { result, err = signer.Sign([]byte(`{"resource":"new-reg","contact":["mailto:person@mail.com"],"agreement":"` + agreementURL + `"}`)) wfe.NewRegistration(ctx, newRequestEvent(), responseWriter, makePostRequest(result.FullSerialize())) - test.AssertEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Registration key is already in use","status":409}`) + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Registration key is already in use","status":409}`) test.AssertEquals(t, responseWriter.Header().Get("Location"), "/acme/reg/3") test.AssertEquals(t, responseWriter.Code, 409) } @@ -910,7 +922,7 @@ func TestNewRegistration(t *testing.T) { for _, rt := range regErrTests { responseWriter := httptest.NewRecorder() mux.ServeHTTP(responseWriter, rt.r) - test.AssertEquals(t, responseWriter.Body.String(), rt.respBody) + assertJSONEquals(t, responseWriter.Body.String(), rt.respBody) } responseWriter := httptest.NewRecorder() @@ -952,7 +964,7 @@ func TestNewRegistration(t *testing.T) { wfe.NewRegistration(ctx, newRequestEvent(), responseWriter, makePostRequest(result.FullSerialize())) - test.AssertEquals(t, + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Registration key is already in use","status":409}`) test.AssertEquals( @@ -1064,7 +1076,7 @@ func TestRevokeCertificateWrongKey(t *testing.T) { wfe.RevokeCertificate(ctx, newRequestEvent(), responseWriter, makePostRequest(result.FullSerialize())) test.AssertEquals(t, responseWriter.Code, 403) - test.AssertEquals(t, responseWriter.Body.String(), + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:unauthorized","detail":"Revocation request must be signed by private key of cert to be revoked, or by the account key of the account that issued it.","status":403}`) } @@ -1105,7 +1117,7 @@ func TestRevokeCertificateAlreadyRevoked(t *testing.T) { wfe.RevokeCertificate(ctx, newRequestEvent(), responseWriter, makePostRequest(result.FullSerialize())) test.AssertEquals(t, responseWriter.Code, 409) - test.AssertEquals(t, responseWriter.Body.String(), + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Certificate already revoked","status":409}`) } @@ -1121,7 +1133,7 @@ func TestAuthorization(t *testing.T) { Method: "GET", URL: mustParseURL(NewAuthzPath), }) - test.AssertEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Method not allowed","status":405}`) + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Method not allowed","status":405}`) // POST, but no body. responseWriter.Body.Reset() @@ -1131,18 +1143,18 @@ func TestAuthorization(t *testing.T) { "Content-Length": {"0"}, }, }) - test.AssertEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"No body on POST","status":400}`) + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"No body on POST","status":400}`) // POST, but body that isn't valid JWS responseWriter.Body.Reset() wfe.NewAuthorization(ctx, newRequestEvent(), responseWriter, makePostRequest("hi")) - test.AssertEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Parse error reading JWS","status":400}`) + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Parse error reading JWS","status":400}`) // POST, Properly JWS-signed, but payload is "foo", not base64-encoded JSON. responseWriter.Body.Reset() wfe.NewAuthorization(ctx, newRequestEvent(), responseWriter, makePostRequest(signRequest(t, "foo", wfe.nonceService))) - test.AssertEquals(t, + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Request payload did not parse as JSON","status":400}`) @@ -1163,7 +1175,7 @@ func TestAuthorization(t *testing.T) { "signature": "RjUQ679fxJgeAJlxqgvDP_sfGZnJ-1RgWF2qmcbnBWljs6h1qp63pLnJOl13u81bP_bCSjaWkelGG8Ymx_X-aQ" } `)) - test.AssertEquals(t, + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"JWS verification error","status":400}`) @@ -1178,7 +1190,7 @@ func TestAuthorization(t *testing.T) { t, responseWriter.Header().Get("Link"), `;rel="next"`) - test.AssertEquals(t, responseWriter.Body.String(), `{"identifier":{"type":"dns","value":"test.com"}}`) + assertJSONEquals(t, responseWriter.Body.String(), `{"identifier":{"type":"dns","value":"test.com"}}`) var authz core.Authorization err = json.Unmarshal([]byte(responseWriter.Body.String()), &authz) @@ -1192,7 +1204,7 @@ func TestAuthorization(t *testing.T) { URL: mustParseURL(authzURL), }) test.AssertEquals(t, responseWriter.Code, http.StatusNotFound) - test.AssertEquals(t, responseWriter.Body.String(), + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Expired authorization","status":404}`) } @@ -1217,7 +1229,7 @@ func TestRegistration(t *testing.T) { URL: mustParseURL(RegPath), Body: makeBody("invalid"), }) - test.AssertEquals(t, + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Method not allowed","status":405}`) responseWriter.Body.Reset() @@ -1227,14 +1239,14 @@ func TestRegistration(t *testing.T) { Method: "GET", URL: mustParseURL(RegPath), }) - test.AssertEquals(t, + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Method not allowed","status":405}`) responseWriter.Body.Reset() // Test POST invalid JSON wfe.Registration(ctx, newRequestEvent(), responseWriter, makePostRequestWithPath("/2", "invalid")) - test.AssertEquals(t, + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Parse error reading JWS","status":400}`) responseWriter.Body.Reset() @@ -1252,7 +1264,7 @@ func TestRegistration(t *testing.T) { test.AssertNotError(t, err, "Unable to sign") wfe.Registration(ctx, newRequestEvent(), responseWriter, makePostRequestWithPath("/2", result.FullSerialize())) - test.AssertEquals(t, + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:unauthorized","detail":"No registration exists matching provided key","status":403}`) responseWriter.Body.Reset() @@ -1271,7 +1283,7 @@ func TestRegistration(t *testing.T) { // Test POST valid JSON with registration up in the mock wfe.Registration(ctx, newRequestEvent(), responseWriter, makePostRequestWithPath("/1", result.FullSerialize())) - test.AssertEquals(t, + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Provided agreement URL [https://letsencrypt.org/im-bad] does not match current agreement URL [`+agreementURL+`]","status":400}`) responseWriter.Body.Reset() @@ -1359,7 +1371,7 @@ func TestGetCertificate(t *testing.T) { mux.ServeHTTP(responseWriter, req) test.AssertEquals(t, responseWriter.Code, 404) test.AssertEquals(t, responseWriter.Header().Get("Cache-Control"), "public, max-age=0, no-cache") - test.AssertEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Certificate not found","status":404}`) + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Certificate not found","status":404}`) reqlogs = mockLog.GetAllMatching(`Terminated request`) test.AssertEquals(t, len(reqlogs), 1) @@ -1372,7 +1384,7 @@ func TestGetCertificate(t *testing.T) { mux.ServeHTTP(responseWriter, req) test.AssertEquals(t, responseWriter.Code, 404) test.AssertEquals(t, responseWriter.Header().Get("Cache-Control"), "public, max-age=0, no-cache") - test.AssertEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Certificate not found","status":404}`) + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Certificate not found","status":404}`) // Invalid serial, no cache responseWriter = httptest.NewRecorder() @@ -1380,7 +1392,7 @@ func TestGetCertificate(t *testing.T) { mux.ServeHTTP(responseWriter, req) test.AssertEquals(t, responseWriter.Code, 404) test.AssertEquals(t, responseWriter.Header().Get("Cache-Control"), "public, max-age=0, no-cache") - test.AssertEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Certificate not found","status":404}`) + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Certificate not found","status":404}`) } func assertCsrLogged(t *testing.T, mockLog *blog.Mock) { @@ -1466,7 +1478,7 @@ func TestBadKeyCSR(t *testing.T) { "csr": "MIHLMHcCAQAwEjEQMA4GA1UEAwwHZm9vLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDCZftp4x4owgjBnwOKfzihIPedT-BUmV2fuQPMqaUlc8yJUp13vcO5uxUlaBm8leM7Dj_sgTDP_JgykorlYo73AgMBAAGgADANBgkqhkiG9w0BAQsFAANBAEaQ2QBhweK-kp1ejQCedUhMit_wG-uTBtKnc3M82f6_fztLkhg1vWQ782nmhbEI5orXp6QtNHgJYnBpqA9Ut00" }`, wfe.nonceService))) - test.AssertEquals(t, + assertJSONEquals(t, responseWriter.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Invalid key in certificate request :: Key too small: 512","status":400}`) }