diff --git a/wfe2/wfe.go b/wfe2/wfe.go index 0665db0960d..ada0b21686b 100644 --- a/wfe2/wfe.go +++ b/wfe2/wfe.go @@ -2054,7 +2054,7 @@ func (wfe *WebFrontEndImpl) KeyRollover( type orderJSON struct { Status core.AcmeStatus `json:"status"` - Expires time.Time `json:"expires"` + Expires *time.Time `json:"expires,omitempty"` Identifiers identifier.ACMEIdentifiers `json:"identifiers"` Authorizations []string `json:"authorizations"` Finalize string `json:"finalize"` @@ -2073,12 +2073,16 @@ func (wfe *WebFrontEndImpl) orderToOrderJSON(request *http.Request, order *corep fmt.Sprintf("%d", order.RegistrationID), fmt.Sprintf("%d", order.Id)) respObj := orderJSON{ Status: core.AcmeStatus(order.Status), - Expires: order.Expires.AsTime(), Identifiers: identifier.FromProtoSlice(order.Identifiers), Finalize: finalizeURL, Profile: order.CertificateProfileName, Replaces: order.Replaces, } + // Omit expires when unset rather than serialize a zero-value timestamp. + if !core.IsAnyNilOrZero(order.Expires) { + expires := order.Expires.AsTime() + respObj.Expires = &expires + } // If there is an order error, prefix its type with the V2 namespace if order.Error != nil { prob, err := bgrpc.PBToProblemDetails(order.Error) diff --git a/wfe2/wfe_test.go b/wfe2/wfe_test.go index ab0e4b92b46..441f4dc0e1c 100644 --- a/wfe2/wfe_test.go +++ b/wfe2/wfe_test.go @@ -3812,6 +3812,32 @@ func TestOrderToOrderJSONV2Authorizations(t *testing.T) { }) } +func TestOrderToOrderJSONExpires(t *testing.T) { + wfe, _, _ := setupWFE(t) + + expires := time.Date(2024, 1, 2, 3, 4, 5, 0, time.UTC) + withExpiry := wfe.orderToOrderJSON(&http.Request{}, &corepb.Order{ + Id: 1, + RegistrationID: 1, + Identifiers: []*corepb.Identifier{identifier.NewDNS("a").ToProto()}, + Status: string(core.StatusPending), + Expires: timestamppb.New(expires), + }) + got, err := json.Marshal(withExpiry) + test.AssertNotError(t, err, "marshaling order with an expiry") + test.AssertContains(t, string(got), `"expires":"2024-01-02T03:04:05Z"`) + + withoutExpiry := wfe.orderToOrderJSON(&http.Request{}, &corepb.Order{ + Id: 1, + RegistrationID: 1, + Identifiers: []*corepb.Identifier{identifier.NewDNS("a").ToProto()}, + Status: string(core.StatusPending), + }) + got, err = json.Marshal(withoutExpiry) + test.AssertNotError(t, err, "marshaling order without an expiry") + test.AssertNotContains(t, string(got), "expires") +} + func TestAccountMarshaling(t *testing.T) { acct := &core.Registration{ ID: 1987,