diff --git a/src/lib.rs b/src/lib.rs index 36e9ac2..29b308f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -366,10 +366,16 @@ impl Account { /// Revokes a previously issued certificate pub async fn revoke<'a>(&'a self, payload: &RevocationRequest<'a>) -> Result<(), Error> { - let rsp = self - .inner - .post(Some(payload), None, &self.inner.client.urls.revoke_cert) - .await?; + let revoke_url = match self.inner.client.urls.revoke_cert.as_deref() { + Some(url) => url, + // This happens because the current account credentials were deserialized from an + // older version which only serialized a subset of the directory URLs. You should + // make sure the account credentials include a `directory` field containing a + // string with the server's directory URL. + None => return Err("no revokeCert URL found".into()), + }; + + let rsp = self.inner.post(Some(payload), None, revoke_url).await?; // The body is empty if the request was successful let _ = Problem::from_response(rsp).await?; Ok(()) diff --git a/src/types.rs b/src/types.rs index 1cd26d3..dfd73dd 100644 --- a/src/types.rs +++ b/src/types.rs @@ -60,6 +60,9 @@ pub struct AccountCredentials { #[serde(with = "pkcs8_serde")] pub(crate) key_pkcs8: Vec, pub(crate) directory: Option, + /// We never serialize `urls` by default, but we support deserializing them + /// in order to support serialized data from older versions of the library. + #[serde(skip_serializing_if = "Option::is_none")] pub(crate) urls: Option, } @@ -359,7 +362,12 @@ pub(crate) struct DirectoryUrls { pub(crate) new_nonce: String, pub(crate) new_account: String, pub(crate) new_order: String, - pub(crate) revoke_cert: String, + // The fields below were added later and old `AccountCredentials` may not have it. + // Newer deserialized account credentials grab a fresh set of `DirectoryUrls` on + // deserialization, so they should be fine. Newer fields should be optional, too. + pub(crate) new_authz: Option, + pub(crate) revoke_cert: Option, + pub(crate) key_change: Option, } #[derive(Serialize)]