use azure_core::{
error::ErrorResponse,
http::{StatusCode, Transport},
json,
};
use azure_core_test::ErrorKind;
use azure_security_keyvault_secrets::{
models::SetSecretParameters, SecretClient, SecretClientOptions,
};
use example::setup;
async fn example_error_response() -> Result<(), Box<dyn std::error::Error>> {
let mut options = SecretClientOptions::default();
let (credential, transport) = setup()?;
options.client_options.transport = Some(Transport::new(transport));
let client = SecretClient::new(
"https://my-vault.vault.azure.net",
credential,
Some(options),
)?;
let secret = SetSecretParameters {
value: Some("secret_value".into()),
content_type: Some("text/plain".into()),
..Default::default()
};
let error = client
.set_secret("secret_name", secret.try_into()?, None)
.await
.unwrap_err();
let ErrorKind::HttpResponse {
status,
error_code,
raw_response: Some(raw_response),
} = error.kind()
else {
panic!("expected HTTP error response");
};
assert_eq!(*status, StatusCode::BadRequest);
assert_eq!(error_code.as_deref(), Some("BadParameter"));
assert!(error
.to_string()
.contains("The request URI contains an invalid name: secret_name"));
let error_response: ErrorResponse = json::from_json(raw_response.body())?;
let details = error_response
.error
.expect("expected HTTP error response details");
assert_eq!(details.code.as_deref(), Some("BadParameter"));
assert_eq!(
details.message.as_deref(),
Some("The request URI contains an invalid name: secret_name")
);
assert_eq!(details.target.as_deref(), Some("secret-name"));
assert_eq!(details.details.len(), 1);
assert_eq!(
details.details[0].message.as_deref(),
Some("secret-name can contain only letters, numbers, and dashes")
);
Ok(())
}
#[tokio::test]
async fn test_core_error_response() -> Result<(), Box<dyn std::error::Error>> {
example_error_response().await
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
example_error_response().await
}
mod example {
use azure_core::{
credentials::TokenCredential,
http::{headers::Headers, AsyncRawResponse, HttpClient, StatusCode},
};
use azure_core_test::{credentials::MockCredential, http::MockHttpClient};
use futures::FutureExt;
use std::sync::Arc;
#[allow(clippy::type_complexity)]
pub fn setup(
) -> Result<(Arc<dyn TokenCredential>, Arc<dyn HttpClient>), Box<dyn std::error::Error>> {
let client = MockHttpClient::new(|_| {
async move {
Ok(AsyncRawResponse::from_bytes(
StatusCode::BadRequest,
Headers::new(),
r#"{
"error": {
"code": "BadParameter",
"message": "The request URI contains an invalid name: secret_name",
"target": "secret-name",
"details": [
{"message": "secret-name can contain only letters, numbers, and dashes"}
]
}
}"#,
))
}
.boxed()
});
Ok((MockCredential::new()?, Arc::new(client)))
}
}