+49
-11
crates/jacquard-common/src/xrpc.rs
+49
-11
crates/jacquard-common/src/xrpc.rs
···
48
};
49
use serde::{Deserialize, Serialize};
50
use smol_str::SmolStr;
51
#[cfg(feature = "websocket")]
52
pub use subscription::{
53
BasicSubscriptionClient, MessageEncoding, SubscriptionCall, SubscriptionClient,
···
485
Resp: XrpcResp,
486
{
487
let status = http_response.status();
488
// If the server returned 401 with a WWW-Authenticate header, expose it so higher layers
489
// (e.g., DPoP handling) can detect `error="invalid_token"` and trigger refresh.
490
#[allow(deprecated)]
491
if status.as_u16() == 401 {
492
if let Some(hv) = http_response.headers().get(http::header::WWW_AUTHENTICATE) {
493
-
return Err(crate::error::ClientError::auth(
494
-
crate::error::AuthError::Other(hv.clone()),
495
-
)
496
-
.for_nsid(Resp::NSID));
497
}
498
}
499
let buffer = Bytes::from(http_response.into_body());
···
670
}
671
// 400: try typed XRPC error, fallback to generic error
672
} else if self.status.as_u16() == 400 {
673
-
match serde_json::from_slice::<_>(&self.buffer) {
674
-
Ok(error) => Err(XrpcError::Xrpc(error)),
675
Err(_) => {
676
// Fallback to generic error (InvalidRequest, ExpiredToken, etc.)
677
match serde_json::from_slice::<GenericXrpcError>(&self.buffer) {
···
730
}
731
// 400: try typed XRPC error, fallback to generic error
732
} else if self.status.as_u16() == 400 {
733
-
match serde_json::from_slice::<_>(&self.buffer) {
734
-
Ok(error) => Err(XrpcError::Xrpc(error)),
735
Err(_) => {
736
// Fallback to generic error (InvalidRequest, ExpiredToken, etc.)
737
match serde_json::from_slice::<GenericXrpcError>(&self.buffer) {
···
790
}
791
// 400: try typed XRPC error, fallback to generic error
792
} else if self.status.as_u16() == 400 {
793
-
match serde_json::from_slice::<_>(&self.buffer) {
794
-
Ok(error) => Err(XrpcError::Xrpc(error)),
795
Err(_) => {
796
// Fallback to generic error (InvalidRequest, ExpiredToken, etc.)
797
match serde_json::from_slice::<GenericXrpcError>(&self.buffer) {
···
876
// 400: try typed XRPC error, fallback to generic error
877
} else if self.status.as_u16() == 400 {
878
let error = match parse_error::<R>(&self.buffer) {
879
-
Ok(error) => XrpcError::Xrpc(error),
880
Err(_) => {
881
// Fallback to generic error (InvalidRequest, ExpiredToken, etc.)
882
match serde_json::from_slice::<GenericXrpcError>(&self.buffer) {
···
48
};
49
use serde::{Deserialize, Serialize};
50
use smol_str::SmolStr;
51
+
52
#[cfg(feature = "websocket")]
53
pub use subscription::{
54
BasicSubscriptionClient, MessageEncoding, SubscriptionCall, SubscriptionClient,
···
486
Resp: XrpcResp,
487
{
488
let status = http_response.status();
489
+
490
// If the server returned 401 with a WWW-Authenticate header, expose it so higher layers
491
// (e.g., DPoP handling) can detect `error="invalid_token"` and trigger refresh.
492
#[allow(deprecated)]
493
if status.as_u16() == 401 {
494
if let Some(hv) = http_response.headers().get(http::header::WWW_AUTHENTICATE) {
495
+
return Err(
496
+
crate::error::ClientError::auth(crate::error::AuthError::Other(hv.clone()))
497
+
.for_nsid(Resp::NSID),
498
+
);
499
}
500
}
501
let buffer = Bytes::from(http_response.into_body());
···
672
}
673
// 400: try typed XRPC error, fallback to generic error
674
} else if self.status.as_u16() == 400 {
675
+
match serde_json::from_slice::<R::Err<'_>>(&self.buffer) {
676
+
Ok(error) => {
677
+
use alloc::string::ToString;
678
+
if error.to_string().contains("InvalidToken") {
679
+
Err(XrpcError::Auth(AuthError::InvalidToken))
680
+
} else if error.to_string().contains("ExpiredToken") {
681
+
Err(XrpcError::Auth(AuthError::TokenExpired))
682
+
} else {
683
+
Err(XrpcError::Xrpc(error))
684
+
}
685
+
}
686
Err(_) => {
687
// Fallback to generic error (InvalidRequest, ExpiredToken, etc.)
688
match serde_json::from_slice::<GenericXrpcError>(&self.buffer) {
···
741
}
742
// 400: try typed XRPC error, fallback to generic error
743
} else if self.status.as_u16() == 400 {
744
+
match serde_json::from_slice::<R::Err<'_>>(&self.buffer) {
745
+
Ok(error) => {
746
+
use alloc::string::ToString;
747
+
if error.to_string().contains("InvalidToken") {
748
+
Err(XrpcError::Auth(AuthError::InvalidToken))
749
+
} else if error.to_string().contains("ExpiredToken") {
750
+
Err(XrpcError::Auth(AuthError::TokenExpired))
751
+
} else {
752
+
Err(XrpcError::Xrpc(error))
753
+
}
754
+
}
755
Err(_) => {
756
// Fallback to generic error (InvalidRequest, ExpiredToken, etc.)
757
match serde_json::from_slice::<GenericXrpcError>(&self.buffer) {
···
810
}
811
// 400: try typed XRPC error, fallback to generic error
812
} else if self.status.as_u16() == 400 {
813
+
match serde_json::from_slice::<R::Err<'_>>(&self.buffer) {
814
+
Ok(error) => {
815
+
use alloc::string::ToString;
816
+
if error.to_string().contains("InvalidToken") {
817
+
Err(XrpcError::Auth(AuthError::InvalidToken))
818
+
} else if error.to_string().contains("ExpiredToken") {
819
+
Err(XrpcError::Auth(AuthError::TokenExpired))
820
+
} else {
821
+
Err(XrpcError::Xrpc(error))
822
+
}
823
+
}
824
Err(_) => {
825
// Fallback to generic error (InvalidRequest, ExpiredToken, etc.)
826
match serde_json::from_slice::<GenericXrpcError>(&self.buffer) {
···
905
// 400: try typed XRPC error, fallback to generic error
906
} else if self.status.as_u16() == 400 {
907
let error = match parse_error::<R>(&self.buffer) {
908
+
Ok(error) => {
909
+
use alloc::string::ToString;
910
+
if error.to_string().contains("InvalidToken") {
911
+
XrpcError::Auth(AuthError::InvalidToken)
912
+
} else if error.to_string().contains("ExpiredToken") {
913
+
XrpcError::Auth(AuthError::TokenExpired)
914
+
} else {
915
+
XrpcError::Xrpc(error)
916
+
}
917
+
}
918
Err(_) => {
919
// Fallback to generic error (InvalidRequest, ExpiredToken, etc.)
920
match serde_json::from_slice::<GenericXrpcError>(&self.buffer) {