Skip to content

Commit 96e92ce

Browse files
authored
Add RawResponse to ErrorKind::HttpResponse (#2983)
Renames `RawResponse` to `BufResponse` - inspired by `std::io::BufReader`, and adds a new `RawResponse` where the body is fully read and stored in `Bytes`. Refactored `Headers` and other types necessary to add `RawResponse` to `ErrorKind::HttpResponse`. Fixes #2962 Fixes #2495 Relates to #2725 Relates to #1995
1 parent 7da0184 commit 96e92ce

File tree

70 files changed

+1032
-867
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+1032
-867
lines changed

Cargo.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/core/azure_core/CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,23 @@
44

55
### Features Added
66

7+
- Added `RawResponse` to `ErrorKind::HttpResponse` that contains the HTTP status code, headers, and complete error response body.
78
- Added `RequestContent::from_slice()`.
89
- Added `TryFrom<T> for RequestContent<T, JsonFormat>` for JSON primitives.
910
- Added support for WASM to the `async_runtime` module.
1011
- Added logging policy to log HTTP requests and responses in the pipeline. As a part of this change, sanitization support was added to places which log HTTP headers and URLs. The `azure_core::http::ClientOptions` has been enhanced with a `LoggingOptions` which allows a user/service client to specify headers or URL query parameters which should be allowed. Note that the sanitization feature is disabled if you build with the `debug` feature enabled.
1112

1213
### Breaking Changes
1314

15+
- Added the ability to configure pipeline configuration independently from `ClientOptions`. This adds a new optional `PipelineOptions` parameter to `azure_core::http::Pipeline::new()`. If not specified, it defaults to the expected options for `azure_core` services.
1416
- Changed `FromStr for RequestContent<T, F>` to `RequestContent::from_str()`.
1517
- Changed `TryFrom<&'static str> for RequestContent<T, F>` to `RequestContent::from_static()`.
1618
- Changed `TryFrom<Bytes> for RequestContent<T, F>` to `From<Bytes> for RequestContent<T, F>` because it was already infallible.
1719
- Removed `TryFrom<Vec<u8>> for RequestContent<T, F>` since `RequestContent::from()` already exists.
1820
- Removed feature `reqwest_rustls_tls`. See [README.md](https://github.com/heaths/azure-sdk-for-rust/blob/main/sdk/core/azure_core/README.md) for alternative HTTP client configuration.
1921
- Removed the `fs` module including the `FileStream` and `FileStreamBuilder` types. Moved to `examples/` for `typespec_client_core` to copy if needed.
2022
- Removed the `setters` macro.
21-
- Added the ability to configure pipeline configuration independently from `ClientOptions`. This adds a new optional `PipelineOptions` parameter to `azure_core::http::Pipeline::new()`. If not specified, it defaults to the expected options for `azure_core` services.
23+
- Renamed `RawResponse` to `BufResponse`. New `RawResponse` contains complete body as `Bytes` used in `ErrorKind::HttpResponse`.
2224

2325
## 0.27.0 (2025-08-01)
2426

sdk/core/azure_core/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ ureq = { version = "3", default-features = false, features = [
483483
Then we need to implement `HttpClient` for another HTTP client like [`ureq`](https://docs.rs/ureq):
484484

485485
```rust no_run
486-
use azure_core::{error::{ErrorKind, ResultExt as _}, http::{HttpClient, RawResponse, Request}};
486+
use azure_core::{error::{ErrorKind, ResultExt as _}, http::{HttpClient, BufResponse, Request}};
487487
use ureq::tls::{TlsConfig, TlsProvider};
488488

489489
#[derive(Debug)]
@@ -507,7 +507,7 @@ impl Default for Agent {
507507

508508
#[async_trait::async_trait]
509509
impl HttpClient for Agent {
510-
async fn execute_request(&self, request: &Request) -> azure_core::Result<RawResponse> {
510+
async fn execute_request(&self, request: &Request) -> azure_core::Result<BufResponse> {
511511
let request: ::http::request::Request<Vec<u8>> = todo!("convert our request into their request");
512512
let response = self
513513
.0

sdk/core/azure_core/benches/benchmarks.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use azure_core::http::{
2-
headers::Headers, HttpClient, Method, RawResponse, Request, StatusCode, Url,
2+
headers::Headers, BufResponse, HttpClient, Method, Request, StatusCode, Url,
33
};
44
use azure_core_test::http::MockHttpClient;
55
use criterion::{black_box, criterion_group, criterion_main, Criterion};
@@ -31,7 +31,7 @@ fn http_transport_test(c: &mut Criterion) {
3131
// client to be used in the benchmark
3232
let mock_client = Arc::new(MockHttpClient::new(move |_| {
3333
async move {
34-
Ok(RawResponse::from_bytes(
34+
Ok(BufResponse::from_bytes(
3535
StatusCode::Ok,
3636
Headers::new(),
3737
vec![],

sdk/core/azure_core/benches/http_transport_benchmarks.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use azure_core::{
55
credentials::TokenCredential,
66
fmt::SafeDebug,
77
http::{
8-
ClientMethodOptions, ClientOptions, HttpClient, Method, Pipeline, RawResponse, Request,
8+
BufResponse, ClientMethodOptions, ClientOptions, HttpClient, Method, Pipeline, Request,
99
TransportOptions, Url,
1010
},
1111
Result,
@@ -85,7 +85,7 @@ impl TestServiceClient {
8585
&self,
8686
path: &str,
8787
options: Option<TestServiceClientGetMethodOptions<'_>>,
88-
) -> Result<RawResponse> {
88+
) -> Result<BufResponse> {
8989
let options = options.unwrap_or_default();
9090
let mut url = self.endpoint.clone();
9191
url.set_path(path);
@@ -103,6 +103,7 @@ impl TestServiceClient {
103103
azure_core::error::ErrorKind::HttpResponse {
104104
status: response.status(),
105105
error_code: None,
106+
raw_response: None,
106107
},
107108
format!("Failed to GET {}: {}", request.url(), response.status()),
108109
));

sdk/core/azure_core/examples/core_pager.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use azure_core::{
55
credentials::TokenCredential,
6-
http::{headers::Headers, HttpClient, Method, RawResponse, StatusCode, TransportOptions},
6+
http::{headers::Headers, BufResponse, HttpClient, Method, StatusCode, TransportOptions},
77
};
88
use azure_core_test::{credentials::MockCredential, http::MockHttpClient};
99
use azure_security_keyvault_secrets::{ResourceExt, SecretClient, SecretClientOptions};
@@ -64,7 +64,7 @@ fn setup() -> Result<(Arc<dyn TokenCredential>, Arc<dyn HttpClient>), Box<dyn st
6464
assert_eq!(request.method(), Method::Get);
6565
assert_eq!(request.url().path(), "/secrets");
6666
match idx {
67-
0 => Ok(RawResponse::from_bytes(
67+
0 => Ok(BufResponse::from_bytes(
6868
StatusCode::Ok,
6969
Headers::new(),
7070
// First page with continuation (nextLink)
@@ -74,7 +74,7 @@ fn setup() -> Result<(Arc<dyn TokenCredential>, Arc<dyn HttpClient>), Box<dyn st
7474
],
7575
"nextLink":"https://my-vault.vault.azure.net/secrets?api-version=7.4&$skiptoken=page2"}"#,
7676
)),
77-
1 => Ok(RawResponse::from_bytes(
77+
1 => Ok(BufResponse::from_bytes(
7878
StatusCode::Ok,
7979
Headers::new(),
8080
// Second (final) page without nextLink

sdk/core/azure_core/examples/core_poller.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use azure_core::{
55
credentials::TokenCredential,
66
http::{
77
headers::{Headers, RETRY_AFTER},
8-
HttpClient, Method, RawResponse, StatusCode, TransportOptions,
8+
BufResponse, HttpClient, Method, StatusCode, TransportOptions,
99
},
1010
};
1111
use azure_core_test::{credentials::MockCredential, http::MockHttpClient};
@@ -78,7 +78,7 @@ fn setup() -> Result<(Arc<dyn TokenCredential>, Arc<dyn HttpClient>), Box<dyn st
7878
assert!(request.url().path().starts_with("/certificates/my-cert/create"));
7979
let mut headers = Headers::new();
8080
headers.insert(RETRY_AFTER, "0");
81-
Ok(RawResponse::from_bytes(
81+
Ok(BufResponse::from_bytes(
8282
StatusCode::Ok,
8383
headers,
8484
r#"{"id":"https://my-vault.vault.azure.net/certificates/my-cert/pending","status":"inProgress"}"#,
@@ -88,7 +88,7 @@ fn setup() -> Result<(Arc<dyn TokenCredential>, Arc<dyn HttpClient>), Box<dyn st
8888
// Polling GET for status
8989
assert_eq!(request.method(), Method::Get);
9090
assert!(request.url().path().starts_with("/certificates/my-cert/pending"));
91-
Ok(RawResponse::from_bytes(
91+
Ok(BufResponse::from_bytes(
9292
StatusCode::Ok,
9393
Headers::new(),
9494
r#"{"id":"https://my-vault.vault.azure.net/certificates/my-cert/pending","status":"completed","target":"https://my-vault.vault.azure.net/certificates/my-cert"}"#,

sdk/core/azure_core/examples/core_remove_user_agent.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use azure_core::{
77
http::{
88
headers::Headers,
99
policies::{Policy, PolicyResult},
10-
Context, HttpClient, Method, RawResponse, Request, StatusCode, TransportOptions,
10+
BufResponse, Context, HttpClient, Method, Request, StatusCode, TransportOptions,
1111
},
1212
};
1313
use azure_core_test::{credentials::MockCredential, http::MockHttpClient};
@@ -96,7 +96,7 @@ fn setup() -> Result<(Arc<dyn TokenCredential>, Arc<dyn HttpClient>), Box<dyn st
9696
.any(|(name, _)| name.as_str().eq_ignore_ascii_case("user-agent")),
9797
"user-agent header should be absent"
9898
);
99-
Ok(RawResponse::from_bytes(
99+
Ok(BufResponse::from_bytes(
100100
StatusCode::Ok,
101101
Headers::new(),
102102
r#"{"value":"secret-value"}"#,

sdk/core/azure_core/examples/core_ureq_client.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use async_trait::async_trait;
55
use azure_core::{
66
error::ErrorKind,
7-
http::{headers::Headers, ClientOptions, HttpClient, RawResponse, Request, TransportOptions},
7+
http::{headers::Headers, BufResponse, ClientOptions, HttpClient, Request, TransportOptions},
88
};
99
use azure_identity::DeveloperToolsCredential;
1010
use azure_security_keyvault_secrets::{ResourceExt as _, SecretClient, SecretClientOptions};
@@ -35,7 +35,7 @@ impl Default for Agent {
3535
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
3636
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
3737
impl HttpClient for Agent {
38-
async fn execute_request(&self, request: &Request) -> azure_core::Result<RawResponse> {
38+
async fn execute_request(&self, request: &Request) -> azure_core::Result<BufResponse> {
3939
let request = into_request(request)?;
4040
let response = self
4141
.0
@@ -102,7 +102,7 @@ fn into_request(request: &Request) -> azure_core::Result<::http::Request<Vec<u8>
102102
Ok(req)
103103
}
104104

105-
fn into_response(response: ::http::Response<ureq::Body>) -> azure_core::Result<RawResponse> {
105+
fn into_response(response: ::http::Response<ureq::Body>) -> azure_core::Result<BufResponse> {
106106
use ::http::response::Parts;
107107
use azure_core::http::StatusCode;
108108

@@ -128,5 +128,5 @@ fn into_response(response: ::http::Response<ureq::Body>) -> azure_core::Result<R
128128
.read_to_vec()
129129
.with_context(ErrorKind::Io, || "failed to read response body")?;
130130

131-
Ok(RawResponse::from_bytes(status, response_headers, body))
131+
Ok(BufResponse::from_bytes(status, response_headers, body))
132132
}

sdk/core/azure_core/src/http/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub use pager::{ItemIterator, PageIterator, Pager};
1818
pub use pipeline::*;
1919
pub use poller::Poller;
2020
pub use request::{Body, Request, RequestContent};
21-
pub use response::{RawResponse, Response};
21+
pub use response::{BufResponse, Response};
2222

2323
pub use typespec_client_core::http::response;
2424
pub use typespec_client_core::http::{

0 commit comments

Comments
 (0)