Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
The azure_core crate provides fundamental types, traits, and abstractions that form the foundation of all Azure SDK for Rust crates. This article demonstrates how to implement custom HTTP clients, create custom policies for request/response processing, and access detailed error information from Azure services.
Crates | API reference documentation | Source code
HTTP requests
This section covers how to customize HTTP client behavior and implement custom HTTP clients for Azure SDK operations.
Implement a custom HTTP client
You can replace the default HTTP client (reqwest) with your own implementation by implementing the HttpClient trait. This is useful when you need specific HTTP client features, want to avoid tokio dependencies, or need to integrate with existing HTTP infrastructure. This example shows how to use the ureq HTTP client, which is a synchronous client that can be useful in embedded or resource-constrained environments.
First, implement the HttpClient trait for your custom client:
#[derive(Debug)]
struct Agent(ureq::Agent);
impl Default for Agent {
fn default() -> Self {
Self(
ureq::Agent::config_builder()
.https_only(true)
.tls_config(
TlsConfig::builder()
.provider(TlsProvider::NativeTls)
.build(),
)
.build()
.into(),
)
}
}
Then, configure the client with your custom HTTP implementation:
#[async_trait]
impl HttpClient for Agent {
async fn execute_request(&self, request: &Request) -> azure_core::Result<AsyncRawResponse> {
let request = into_request(request)?;
let response = self
.0
.run(request)
.with_context_fn(ErrorKind::Io, || "failed to send request")?;
into_response(response)
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let vault_url = env::var("AZURE_KEYVAULT_URL")
.map_err(|_| "Environment variable AZURE_KEYVAULT_URL is required")?;
let credential = DeveloperToolsCredential::new(None)?;
let agent = Arc::new(Agent::default());
let options = SecretClientOptions {
client_options: ClientOptions {
transport: Some(Transport::new(agent)),
..Default::default()
},
..Default::default()
};
let client = SecretClient::new(&vault_url, credential.clone(), Some(options))?;
let mut pager = client.list_secret_properties(None)?;
while let Some(secret) = pager.try_next().await? {
let name = secret.resource_id()?.name;
println!("Secret: {name}");
}
Ok(())
}
Implement custom HTTP policies
You can customize request and response processing by implementing the Policy trait. Policies let you modify requests before they're sent or inspect responses before they're returned. This example shows how to create a policy that removes the request's User-Agent header:
#[derive(Debug)]
struct RemoveUserAgent;
#[async_trait]
impl Policy for RemoveUserAgent {
async fn send(
&self,
ctx: &Context,
request: &mut Request,
next: &[Arc<dyn Policy>],
) -> PolicyResult {
let headers = request.headers_mut();
// Note: HTTP headers are case-insensitive but client-added headers are normalized to lowercase.
headers.remove("user-agent");
next[0].send(ctx, request, &next[1..]).await
}
}
Add your custom policy to the client options object:
// Policies are created in an Arc to be generally shared.
let remove_user_agent = Arc::new(RemoveUserAgent);
// Construct client options with your policy that runs after the built-in per-call UserAgentPolicy.
let mut options = SecretClientOptions::default();
options
.client_options
.per_call_policies
.push(remove_user_agent);
Then construct the client:
let client = SecretClient::new(
"https://my-vault.vault.azure.net",
credential.clone(),
Some(options),
)?;
Service error details
You can access detailed errors returned by the Azure service. The following example demonstrates deserializing a standard Azure error response to get more details such as the error_code and error details.
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");
};
Next steps
- Authenticate with Azure services
- OpenTelemetry in Azure SDK for Rust crates
- Use Azure SDK for Rust crates
- Azure SDK crates on Crates.io - List of available Azure SDK crates
- Azure SDK design guidelines - Design principles and patterns
- Azure SDK for Rust GitHub repository - Issues and source code
- Cargo documentation - Complete Cargo reference