@@ -10,7 +10,7 @@ use std::string::{String, ToString};
1010
1111use http:: Uri ;
1212use ngx:: collections:: Vec ;
13- use serde:: { Deserialize , Serialize } ;
13+ use serde:: { de :: IgnoredAny , Deserialize , Serialize } ;
1414
1515use crate :: conf:: identifier:: Identifier ;
1616
@@ -22,6 +22,8 @@ pub struct DirectoryMetadata {
2222 pub website : Option < Uri > ,
2323 pub caa_identities : Option < Vec < String > > ,
2424 pub external_account_required : Option < bool > ,
25+ #[ serde( deserialize_with = "deserialize_null_as_default" ) ]
26+ pub profiles : std:: collections:: BTreeMap < String , IgnoredAny > ,
2527}
2628
2729/// RFC8555 Section 7.1.1 Directory
@@ -118,6 +120,8 @@ pub struct OrderRequest<'a> {
118120 pub not_before : Option < String > ,
119121 #[ serde( skip_serializing_if = "Option::is_none" ) ]
120122 pub not_after : Option < String > ,
123+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
124+ pub profile : Option < & ' a str > ,
121125}
122126
123127#[ derive( Clone , Debug , Deserialize , Eq , PartialEq ) ]
@@ -200,6 +204,7 @@ pub enum ErrorKind {
200204 ExternalAccountRequired ,
201205 IncorrectResponse ,
202206 InvalidContact ,
207+ InvalidProfile ,
203208 Malformed ,
204209 OrderNotReady ,
205210 RateLimited ,
@@ -232,6 +237,7 @@ const ERROR_KIND: &[(&str, ErrorKind)] = &[
232237 ) ,
233238 ( "incorrectResponse" , ErrorKind :: IncorrectResponse ) ,
234239 ( "invalidContact" , ErrorKind :: InvalidContact ) ,
240+ ( "invalidProfile" , ErrorKind :: InvalidProfile ) ,
235241 ( "malformed" , ErrorKind :: Malformed ) ,
236242 ( "orderNotReady" , ErrorKind :: OrderNotReady ) ,
237243 ( "rateLimited" , ErrorKind :: RateLimited ) ,
@@ -336,6 +342,7 @@ impl Problem {
336342
337343 ErrorKind :: BadCsr
338344 | ErrorKind :: Caa
345+ | ErrorKind :: InvalidProfile
339346 | ErrorKind :: RejectedIdentifier
340347 | ErrorKind :: UnsupportedIdentifier => ProblemCategory :: Order ,
341348
@@ -346,6 +353,15 @@ impl Problem {
346353 }
347354}
348355
356+ fn deserialize_null_as_default < ' de , D , T > ( deserializer : D ) -> Result < T , D :: Error >
357+ where
358+ D : serde:: de:: Deserializer < ' de > ,
359+ T : serde:: de:: Deserialize < ' de > + Default ,
360+ {
361+ let val = Option :: < T > :: deserialize ( deserializer) ?;
362+ Ok ( val. unwrap_or_default ( ) )
363+ }
364+
349365fn deserialize_vec_of_uri < ' de , D > ( deserializer : D ) -> Result < Vec < Uri > , D :: Error >
350366where
351367 D : serde:: Deserializer < ' de > ,
@@ -385,6 +401,62 @@ where
385401mod tests {
386402 use super :: * ;
387403
404+ #[ test]
405+ fn directory ( ) {
406+ // complete example
407+ let _: Directory = serde_json:: from_str (
408+ r#"{
409+ "newNonce": "https://example.com/acme/new-nonce",
410+ "newAccount": "https://example.com/acme/new-account",
411+ "newOrder": "https://example.com/acme/new-order",
412+ "newAuthz": "https://example.com/acme/new-authz",
413+ "revokeCert": "https://example.com/acme/revoke-cert",
414+ "keyChange": "https://example.com/acme/key-change",
415+ "meta": {
416+ "termsOfService": "https://example.com/acme/terms/2017-5-30",
417+ "website": "https://www.example.com/",
418+ "caaIdentities": ["example.com"],
419+ "externalAccountRequired": false,
420+ "profiles": {
421+ "profile1": "https://example.com/acme/docs/profiles#profile1",
422+ "profile2": "https://example.com/acme/docs/profiles#profile2"
423+ }
424+ }
425+ }"# ,
426+ )
427+ . unwrap ( ) ;
428+
429+ // minimal
430+ let _: Directory = serde_json:: from_str (
431+ r#"{
432+ "newNonce": "https://example.com/acme/new-nonce",
433+ "newAccount": "https://example.com/acme/new-account",
434+ "newOrder": "https://example.com/acme/new-order"
435+ }"# ,
436+ )
437+ . unwrap ( ) ;
438+
439+ // null
440+ let _: Directory = serde_json:: from_str (
441+ r#"{
442+ "newNonce": "https://example.com/acme/new-nonce",
443+ "newAccount": "https://example.com/acme/new-account",
444+ "newOrder": "https://example.com/acme/new-order",
445+ "newAuthz": null,
446+ "revokeCert": null,
447+ "keyChange": null,
448+ "meta": {
449+ "termsOfService": null,
450+ "website": null,
451+ "caaIdentities": null,
452+ "externalAccountRequired": null,
453+ "profiles": null
454+ }
455+ }"# ,
456+ )
457+ . unwrap ( ) ;
458+ }
459+
388460 #[ test]
389461 fn order ( ) {
390462 let _order: Order = serde_json:: from_str (
0 commit comments