feat(transport): add constructors for non_exhaustive error types (#806)
AuthRequiredError, InsufficientScopeError, and DynamicTransportError were marked #[non_exhaustive] in #715/#768 but don't have constructors usable by external crates. Add new() for the error types and from_parts() for DynamicTransportError (the existing new() requires a Transport type parameter, making it unusable for test fixtures). Fixes #805
This commit is contained in:
parent
a743f15654
commit
ad3997268d
3 changed files with 51 additions and 9 deletions
|
|
@ -252,6 +252,24 @@ impl DynamicTransportError {
|
|||
error: Box::new(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a `DynamicTransportError` from raw parts.
|
||||
///
|
||||
/// Unlike [`new`](Self::new), this does not require a concrete [`Transport`] type,
|
||||
/// making it usable in test fixtures and other contexts where a real transport
|
||||
/// implementation is not available.
|
||||
pub fn from_parts(
|
||||
transport_name: impl Into<Cow<'static, str>>,
|
||||
transport_type_id: std::any::TypeId,
|
||||
error: Box<dyn std::error::Error + Send + Sync>,
|
||||
) -> Self {
|
||||
Self {
|
||||
transport_name: transport_name.into(),
|
||||
transport_type_id,
|
||||
error,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn downcast<T: Transport<R> + 'static, R: ServiceRole>(self) -> Result<T::Error, Self> {
|
||||
if !self.is::<T, R>() {
|
||||
Err(self)
|
||||
|
|
|
|||
|
|
@ -284,21 +284,28 @@ impl StreamableHttpClientTransport<reqwest::Client> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::parse_json_rpc_error;
|
||||
use crate::{model::JsonRpcMessage, transport::streamable_http_client::InsufficientScopeError};
|
||||
use crate::{
|
||||
model::JsonRpcMessage,
|
||||
transport::streamable_http_client::{AuthRequiredError, InsufficientScopeError},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn auth_required_error_new() {
|
||||
let err = AuthRequiredError::new("Bearer realm=\"test\"".to_string());
|
||||
assert_eq!(err.www_authenticate_header, "Bearer realm=\"test\"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insufficient_scope_error_can_upgrade() {
|
||||
let with_scope = InsufficientScopeError {
|
||||
www_authenticate_header: "Bearer scope=\"admin\"".to_string(),
|
||||
required_scope: Some("admin".to_string()),
|
||||
};
|
||||
let with_scope = InsufficientScopeError::new(
|
||||
"Bearer scope=\"admin\"".to_string(),
|
||||
Some("admin".to_string()),
|
||||
);
|
||||
assert!(with_scope.can_upgrade());
|
||||
assert_eq!(with_scope.get_required_scope(), Some("admin"));
|
||||
|
||||
let without_scope = InsufficientScopeError {
|
||||
www_authenticate_header: "Bearer error=\"insufficient_scope\"".to_string(),
|
||||
required_scope: None,
|
||||
};
|
||||
let without_scope =
|
||||
InsufficientScopeError::new("Bearer error=\"insufficient_scope\"".to_string(), None);
|
||||
assert!(!without_scope.can_upgrade());
|
||||
assert_eq!(without_scope.get_required_scope(), None);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,15 @@ pub struct AuthRequiredError {
|
|||
pub www_authenticate_header: String,
|
||||
}
|
||||
|
||||
impl AuthRequiredError {
|
||||
/// Create a new `AuthRequiredError` instance.
|
||||
pub fn new(www_authenticate_header: String) -> Self {
|
||||
Self {
|
||||
www_authenticate_header,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
pub struct InsufficientScopeError {
|
||||
|
|
@ -37,6 +46,14 @@ pub struct InsufficientScopeError {
|
|||
}
|
||||
|
||||
impl InsufficientScopeError {
|
||||
/// Create a new `InsufficientScopeError` instance.
|
||||
pub fn new(www_authenticate_header: String, required_scope: Option<String>) -> Self {
|
||||
Self {
|
||||
www_authenticate_header,
|
||||
required_scope,
|
||||
}
|
||||
}
|
||||
|
||||
/// check if scope upgrade is possible (i.e., we know what scope is required)
|
||||
pub fn can_upgrade(&self) -> bool {
|
||||
self.required_scope.is_some()
|
||||
|
|
|
|||
Loading…
Reference in a new issue