@@ -516,57 +516,105 @@ fn receive<Response: DeserializeOwned>(
516516 } else {
517517 // Read the reponse body, as `mod_http_oauth2` isn’t very
518518 // expressive with HTTP status codes.
519- let error = response
519+ let json = response
520520 . body_mut ( )
521- . read_json :: < crate :: Error < self :: ApiError > > ( )
522- . context ( "Could not decode Prosody OAuth 2.0 API error" ) ?
523- . into_inner ( ) ;
524-
525- match error. name . as_ref ( ) {
526- // Unauthorized.
527- "not-authorized" | "expired_token" | "invalid_grant" | "login_required" => {
528- tracing:: debug!( "{error}" ) ;
529- Err ( self :: Error :: Unauthorized ( anyhow:: Error :: new ( error) ) )
530- }
531- "invalid_request" if error. description . as_deref ( ) == Some ( "invalid JID" ) => {
532- tracing:: debug!( "{error}" ) ;
533- Err ( self :: Error :: Unauthorized ( anyhow:: Error :: new ( error) ) )
534- }
521+ . read_json :: < serde_json :: Value > ( )
522+ . context ( "Prosody OAuth 2.0 API error is not valid JSON " ) ?;
523+
524+ match serde_json :: from_value :: < self :: ApiError > ( json . clone ( ) ) {
525+ Ok ( error ) => match error. name . as_ref ( ) {
526+ // Unauthorized.
527+ "expired_token" | "invalid_grant" | "login_required" => {
528+ tracing:: debug!( "{error}" ) ;
529+ Err ( self :: Error :: Unauthorized ( anyhow:: Error :: new ( error) ) )
530+ }
531+ "invalid_request" if error. description . as_deref ( ) == Some ( "invalid JID" ) => {
532+ tracing:: debug!( "{error}" ) ;
533+ Err ( self :: Error :: Unauthorized ( anyhow:: Error :: new ( error) ) )
534+ }
535535
536- // Forbidden.
537- "forbidden" | "access_denied" => {
538- tracing:: warn!( "{error}" ) ;
539- Err ( self :: Error :: Forbidden ( anyhow:: Error :: new ( error) ) )
540- }
536+ // Forbidden.
537+ "access_denied" => {
538+ tracing:: warn!( "{error}" ) ;
539+ Err ( self :: Error :: Forbidden ( anyhow:: Error :: new ( error) ) )
540+ }
541541
542- // Internal errors.
543- "internal-server-error"
544- | "feature-not-implemented"
545- | "invalid_client"
546- | "invalid_client_metadata"
547- | "invalid_redirect_uri"
548- | "invalid_request"
549- | "invalid_scope"
550- | "temporarily_unavailable"
551- | "unsupported_response_type" => {
552- tracing:: error!( "{error}" ) ;
553- Err ( self :: Error :: Internal ( anyhow:: Error :: new ( error) ) )
554- }
555- "unauthorized_client" => {
556- tracing:: warn!(
557- "OAuth 2.0 client unauthorized ({error}). \
558- Make sure to register one before making calls."
559- ) ;
560- Err ( self :: Error :: Internal ( anyhow:: Error :: new ( error) ) )
561- }
542+ // Internal errors.
543+ "invalid_client"
544+ | "invalid_client_metadata"
545+ | "invalid_redirect_uri"
546+ | "invalid_request"
547+ | "invalid_scope"
548+ | "temporarily_unavailable"
549+ | "unsupported_response_type" => {
550+ tracing:: error!( "{error}" ) ;
551+ Err ( self :: Error :: Internal ( anyhow:: Error :: new ( error) ) )
552+ }
553+ "unauthorized_client" => {
554+ tracing:: warn!(
555+ "OAuth 2.0 client unauthorized ({error}). \
556+ Make sure to register one before making calls."
557+ ) ;
558+ Err ( self :: Error :: Internal ( anyhow:: Error :: new ( error) ) )
559+ }
562560
563- // Catch-all.
564- _ => {
565- tracing:: error!( "{error}" ) ;
566- if cfg ! ( debug_assertions) {
567- panic ! ( "Unknown error" )
561+ // Catch-all.
562+ _ => {
563+ tracing:: error!( "{error}" ) ;
564+ if cfg ! ( debug_assertions) {
565+ panic ! ( "Unknown error" )
566+ }
567+ Err ( self :: Error :: Internal ( anyhow:: Error :: new ( error) ) )
568+ }
569+ } ,
570+ Err ( _) => {
571+ // TODO: Factor this case so it’s shared between all mods.
572+ let error = serde_json:: from_value :: < crate :: Error > ( json)
573+ . context ( "Could not decode Prosody OAuth 2.0 API error" ) ?;
574+
575+ match error. condition . as_ref ( ) {
576+ // Unauthorized.
577+ "not-authorized" => {
578+ tracing:: debug!( "{error}" ) ;
579+ Err ( self :: Error :: Unauthorized ( anyhow:: Error :: new ( error) ) )
580+ }
581+
582+ // Forbidden.
583+ "forbidden" => {
584+ tracing:: warn!( "{error}" ) ;
585+ Err ( self :: Error :: Forbidden ( anyhow:: Error :: new ( error) ) )
586+ }
587+
588+ // Internal errors.
589+ "internal-server-error"
590+ | "feature-not-implemented"
591+ | "invalid_client"
592+ | "invalid_client_metadata"
593+ | "invalid_redirect_uri"
594+ | "invalid_request"
595+ | "invalid_scope"
596+ | "temporarily_unavailable"
597+ | "unsupported_response_type" => {
598+ tracing:: error!( "{error}" ) ;
599+ Err ( self :: Error :: Internal ( anyhow:: Error :: new ( error) ) )
600+ }
601+ "unauthorized_client" => {
602+ tracing:: warn!(
603+ "OAuth 2.0 client unauthorized ({error}). \
604+ Make sure to register one before making calls."
605+ ) ;
606+ Err ( self :: Error :: Internal ( anyhow:: Error :: new ( error) ) )
607+ }
608+
609+ // Catch-all.
610+ _ => {
611+ tracing:: error!( "{error}" ) ;
612+ if cfg ! ( debug_assertions) {
613+ panic ! ( "Unknown error" )
614+ }
615+ Err ( self :: Error :: Internal ( anyhow:: Error :: new ( error) ) )
616+ }
568617 }
569- Err ( self :: Error :: Internal ( anyhow:: Error :: new ( error) ) )
570618 }
571619 }
572620 }
0 commit comments