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),
|
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> {
|
pub fn downcast<T: Transport<R> + 'static, R: ServiceRole>(self) -> Result<T::Error, Self> {
|
||||||
if !self.is::<T, R>() {
|
if !self.is::<T, R>() {
|
||||||
Err(self)
|
Err(self)
|
||||||
|
|
|
||||||
|
|
@ -284,21 +284,28 @@ impl StreamableHttpClientTransport<reqwest::Client> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::parse_json_rpc_error;
|
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]
|
#[test]
|
||||||
fn insufficient_scope_error_can_upgrade() {
|
fn insufficient_scope_error_can_upgrade() {
|
||||||
let with_scope = InsufficientScopeError {
|
let with_scope = InsufficientScopeError::new(
|
||||||
www_authenticate_header: "Bearer scope=\"admin\"".to_string(),
|
"Bearer scope=\"admin\"".to_string(),
|
||||||
required_scope: Some("admin".to_string()),
|
Some("admin".to_string()),
|
||||||
};
|
);
|
||||||
assert!(with_scope.can_upgrade());
|
assert!(with_scope.can_upgrade());
|
||||||
assert_eq!(with_scope.get_required_scope(), Some("admin"));
|
assert_eq!(with_scope.get_required_scope(), Some("admin"));
|
||||||
|
|
||||||
let without_scope = InsufficientScopeError {
|
let without_scope =
|
||||||
www_authenticate_header: "Bearer error=\"insufficient_scope\"".to_string(),
|
InsufficientScopeError::new("Bearer error=\"insufficient_scope\"".to_string(), None);
|
||||||
required_scope: None,
|
|
||||||
};
|
|
||||||
assert!(!without_scope.can_upgrade());
|
assert!(!without_scope.can_upgrade());
|
||||||
assert_eq!(without_scope.get_required_scope(), None);
|
assert_eq!(without_scope.get_required_scope(), None);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,15 @@ pub struct AuthRequiredError {
|
||||||
pub www_authenticate_header: String,
|
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)]
|
#[derive(Debug)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub struct InsufficientScopeError {
|
pub struct InsufficientScopeError {
|
||||||
|
|
@ -37,6 +46,14 @@ pub struct InsufficientScopeError {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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)
|
/// check if scope upgrade is possible (i.e., we know what scope is required)
|
||||||
pub fn can_upgrade(&self) -> bool {
|
pub fn can_upgrade(&self) -> bool {
|
||||||
self.required_scope.is_some()
|
self.required_scope.is_some()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue