Skip to content

Commit 457bd53

Browse files
authored
add HttpError, StreamError & CosmosError (#251)
1 parent e3950fe commit 457bd53

File tree

1,335 files changed

+252009
-1276669
lines changed

Some content is hidden

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

1,335 files changed

+252009
-1276669
lines changed

sdk/core/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ categories = ["api-bindings"]
1313
edition = "2018"
1414

1515
[dependencies]
16-
base64 = "0.13"
1716
chrono = "0.4"
1817
http = "0.2"
1918
futures = "0.3"

sdk/core/src/bytes_stream.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1+
use crate::errors::StreamError;
2+
use crate::SeekableStream;
13
use bytes::Bytes;
24
use futures::io::AsyncRead;
35
use futures::stream::Stream;
46
use std::pin::Pin;
57
use std::task::Poll;
68

7-
use crate::SeekableStream;
8-
99
/// Convenience struct that maps a `bytes::Bytes` buffer into a stream.
1010
///
1111
/// This struct implements both `Stream` and `SeekableStream` for an
@@ -38,7 +38,7 @@ impl From<Bytes> for BytesStream {
3838
}
3939

4040
impl Stream for BytesStream {
41-
type Item = Result<Bytes, Box<dyn std::error::Error + Send + Sync>>;
41+
type Item = Result<Bytes, StreamError>;
4242

4343
fn poll_next(
4444
self: Pin<&mut Self>,
@@ -59,7 +59,7 @@ impl Stream for BytesStream {
5959

6060
#[async_trait::async_trait]
6161
impl SeekableStream for BytesStream {
62-
async fn reset(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
62+
async fn reset(&mut self) -> Result<(), StreamError> {
6363
self.bytes_read = 0;
6464
Ok(())
6565
}

sdk/core/src/errors.rs

Lines changed: 92 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
1-
use http::header::ToStrError;
21
use http::StatusCode;
32
#[cfg(feature = "enable_hyper")]
43
use hyper::{self, body, Body};
5-
use std::io::Error as IOError;
6-
use std::num;
7-
use std::num::ParseIntError;
8-
use std::str;
9-
use std::str::ParseBoolError;
10-
use std::string;
11-
use url::ParseError as URLParseError;
4+
#[cfg(feature = "enable_hyper")]
5+
type HttpClientError = hyper::Error;
6+
#[cfg(feature = "enable_reqwest")]
7+
type HttpClientError = reqwest::Error;
128

139
#[derive(Debug, thiserror::Error)]
1410
pub enum ParsingError {
@@ -23,7 +19,7 @@ pub enum ParseError {
2319
#[error("Expected split char \'{}\' not found", 0)]
2420
SplitNotFound(char),
2521
#[error("Parse int error {}", 0)]
26-
ParseIntError(ParseIntError),
22+
ParseIntError(std::num::ParseIntError),
2723
}
2824

2925
#[derive(Debug, thiserror::Error)]
@@ -73,52 +69,76 @@ impl From<UnexpectedHTTPResult> for AzureError {
7369
}
7470
}
7571

76-
impl UnexpectedHTTPResult {
77-
pub fn new(expected: StatusCode, received: StatusCode, body: &str) -> UnexpectedHTTPResult {
78-
UnexpectedHTTPResult {
72+
#[derive(Debug, thiserror::Error)]
73+
pub enum StreamError {
74+
#[error("Stream poll error: {}", 0)]
75+
PollError(std::io::Error),
76+
#[error("Stream read error: {}", 0)]
77+
ReadError(HttpClientError),
78+
}
79+
80+
#[derive(Debug, thiserror::Error)]
81+
pub enum HttpError {
82+
#[error("Failed to serialize request body as json: {}", 0)]
83+
BodySerializationError(serde_json::Error),
84+
#[error(
85+
"Unexpected HTTP result (expected: {:?}, received: {:?}, body: {:?})",
86+
expected,
87+
received,
88+
body
89+
)]
90+
UnexpectedStatusCode {
91+
expected: Vec<StatusCode>,
92+
received: StatusCode,
93+
body: String,
94+
},
95+
#[error("UTF8 conversion error: {}", 0)]
96+
UTF8Error(#[from] std::str::Utf8Error),
97+
#[error("From UTF8 conversion error: {}", 0)]
98+
FromUtf8Error(#[from] std::string::FromUtf8Error),
99+
#[error("Failed to build request: {}", 0)]
100+
BuildRequestError(http::Error),
101+
#[error("Failed to build request: {}", 0)]
102+
BuildClientRequestError(HttpClientError),
103+
#[error("Failed to execute request: {}", 0)]
104+
ExecuteRequestError(HttpClientError),
105+
#[error("Failed to read response as bytes: {}", 0)]
106+
ReadBytesError(HttpClientError),
107+
#[error("Failed to read response as stream: {}", 0)]
108+
ReadStreamError(HttpClientError),
109+
#[error("Failed to build response: {}", 0)]
110+
BuildResponseError(http::Error),
111+
#[error("to str error: {}", 0)]
112+
ToStrError(#[from] http::header::ToStrError),
113+
#[error("Failed to reset stream: {}", 0)]
114+
StreamResetError(StreamError),
115+
}
116+
117+
impl HttpError {
118+
pub fn new_unexpected_status_code(
119+
expected: StatusCode,
120+
received: StatusCode,
121+
body: &str,
122+
) -> HttpError {
123+
HttpError::UnexpectedStatusCode {
79124
expected: vec![expected],
80125
received,
81126
body: body.to_owned(),
82127
}
83128
}
84129

85-
pub fn new_multiple(
130+
pub fn new_multiple_unexpected_status_code(
86131
allowed: Vec<StatusCode>,
87132
received: StatusCode,
88133
body: &str,
89-
) -> UnexpectedHTTPResult {
90-
UnexpectedHTTPResult {
134+
) -> HttpError {
135+
HttpError::UnexpectedStatusCode {
91136
expected: allowed,
92137
received,
93138
body: body.to_owned(),
94139
}
95140
}
96-
97-
pub fn status_code(&self) -> StatusCode {
98-
self.received
99-
}
100141
}
101-
102-
impl std::fmt::Display for UnexpectedHTTPResult {
103-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104-
write!(
105-
f,
106-
"Unexpected HTTP result (expected: {:?}, received: {:?})",
107-
self.expected, self.received
108-
)
109-
}
110-
}
111-
112-
impl std::error::Error for UnexpectedHTTPResult {
113-
fn description(&self) -> &str {
114-
"Unexpected HTTP result"
115-
}
116-
117-
fn cause(&self) -> Option<&dyn std::error::Error> {
118-
None
119-
}
120-
}
121-
122142
#[derive(Debug, thiserror::Error)]
123143
pub enum Not512ByteAlignedError {
124144
#[error("start range not 512-byte aligned: {}", 0)]
@@ -143,37 +163,31 @@ pub enum Parse512AlignedError {
143163
#[error("split not found")]
144164
SplitNotFound,
145165
#[error("parse int error: {}", 0)]
146-
ParseIntError(#[from] ParseIntError),
166+
ParseIntError(#[from] std::num::ParseIntError),
147167
#[error("not 512 byte aligned error: {}", 0)]
148168
Not512ByteAlignedError(#[from] Not512ByteAlignedError),
149169
}
150170

151171
#[derive(Debug, thiserror::Error)]
152172
pub enum AzureError {
173+
#[error("http error: {}", 0)]
174+
HttpError(#[from] HttpError),
153175
#[error("{}-{} is not 512 byte aligned", start, end)]
154176
PageNot512ByteAlignedError { start: u64, end: u64 },
155177
#[error("{} is not 512 byte aligned", size)]
156178
Not512ByteAlignedError { size: u64 },
157179
#[error("Operation not supported. Operation == {}, reason == {}", 0, 1)]
158180
OperationNotSupported(String, String),
159-
#[error("base64 decode error: {}", 0)]
160-
Base64DecodeError(#[from] base64::DecodeError),
161-
#[error("digest length {} bytes instead of 16", 0)]
162-
DigestNot16BytesLong(u64),
163-
#[error("CRC64 length {} bytes instead of 8", 0)]
164-
CRC64Not8BytesLong(u64),
165181
#[error("parse bool error: {}", 0)]
166-
ParseBoolError(#[from] ParseBoolError),
182+
ParseBoolError(#[from] std::str::ParseBoolError),
167183
#[error("to str error: {}", 0)]
168-
ToStrError(#[from] ToStrError),
184+
ToStrError(#[from] http::header::ToStrError),
169185
#[error("json error: {}", 0)]
170186
JSONError(#[from] serde_json::Error),
171-
#[error("Hyper error: {}", 0)]
172-
HyperError(#[from] Box<dyn std::error::Error + Sync + Send>),
173187
#[error("Permission error: {}", 0)]
174188
PermissionError(#[from] PermissionError),
175189
#[error("IO error: {}", 0)]
176-
IOError(#[from] IOError),
190+
IOError(#[from] std::io::Error),
177191
#[error("UnexpectedXMLError: {}", 0)]
178192
UnexpectedXMLError(String),
179193
#[error("Azure Path parse error: {}", 0)]
@@ -198,7 +212,7 @@ pub enum AzureError {
198212
#[error("Traversing error: {}", 0)]
199213
ResponseParsingError(#[from] TraversingError),
200214
#[error("Parse int error: {}", 0)]
201-
ParseIntError(#[from] num::ParseIntError),
215+
ParseIntError(#[from] std::num::ParseIntError),
202216
#[error("Parse float error: {}", 0)]
203217
ParseFloatError(#[from] std::num::ParseFloatError),
204218
#[error("Parse error: {}", 0)]
@@ -212,17 +226,17 @@ pub enum AzureError {
212226
#[error("Input parameters error: {}", 0)]
213227
InputParametersError(String),
214228
#[error("URL parse error: {}", 0)]
215-
URLParseError(#[from] URLParseError),
229+
URLParseError(#[from] url::ParseError),
216230
#[error("Error preparing HTTP request: {}", 0)]
217231
HttpPrepareError(#[from] http::Error),
218232
#[error("uuid error: {}", 0)]
219233
ParseUuidError(#[from] uuid::Error),
220234
#[error("Chrono parser error: {}", 0)]
221235
ChronoParserError(#[from] chrono::ParseError),
222236
#[error("UTF8 conversion error: {}", 0)]
223-
UTF8Error(#[from] str::Utf8Error),
237+
UTF8Error(#[from] std::str::Utf8Error),
224238
#[error("FromUTF8 error: {}", 0)]
225-
FromUtf8Error(#[from] string::FromUtf8Error),
239+
FromUtf8Error(#[from] std::string::FromUtf8Error),
226240
#[error("A required header is missing: {}", 0)]
227241
MissingHeaderError(String),
228242
#[error(
@@ -257,7 +271,7 @@ pub enum TraversingError {
257271
#[error("Text not found")]
258272
TextNotFound,
259273
#[error("Parse int error: {}", 0)]
260-
ParseIntError(#[from] num::ParseIntError),
274+
ParseIntError(#[from] std::num::ParseIntError),
261275
#[error("Generic parse error: {}", 0)]
262276
GenericParseError(String),
263277
#[error("Parsing error: {:?}", 0)]
@@ -270,51 +284,49 @@ impl From<()> for AzureError {
270284
}
271285
}
272286

273-
#[cfg(feature = "enable_hyper")]
274-
impl From<hyper::Error> for AzureError {
275-
fn from(error: hyper::Error) -> AzureError {
276-
AzureError::HyperError(error.into())
277-
}
278-
}
279-
280287
#[cfg(feature = "enable_hyper")]
281288
#[inline]
282289
pub async fn extract_status_headers_and_body(
283290
resp: hyper::client::ResponseFuture,
284291
) -> Result<(hyper::StatusCode, hyper::HeaderMap, body::Bytes), AzureError> {
285-
let res = resp.await?;
292+
let res = resp.await.map_err(HttpError::ExecuteRequestError)?;
286293
let (head, body) = res.into_parts();
287294
let status = head.status;
288295
let headers = head.headers;
289-
let body = body::to_bytes(body).await?;
290-
296+
let body = body::to_bytes(body)
297+
.await
298+
.map_err(HttpError::ReadBytesError)?;
291299
Ok((status, headers, body))
292300
}
293301

294302
#[cfg(feature = "enable_hyper")]
295303
#[inline]
296304
pub async fn extract_status_and_body(
297305
resp: hyper::client::ResponseFuture,
298-
) -> Result<(StatusCode, String), AzureError> {
299-
let res = resp.await?;
306+
) -> Result<(StatusCode, String), HttpError> {
307+
let res = resp.await.map_err(HttpError::ExecuteRequestError)?;
300308
let status = res.status();
301-
let body = body::to_bytes(res.into_body()).await?;
302-
Ok((status, str::from_utf8(&body)?.to_owned()))
309+
let body = body::to_bytes(res.into_body())
310+
.await
311+
.map_err(HttpError::ReadBytesError)?;
312+
Ok((status, std::str::from_utf8(&body)?.to_owned()))
303313
}
304314

305315
#[cfg(feature = "enable_hyper")]
306316
#[inline]
307317
pub async fn extract_location_status_and_body(
308318
resp: hyper::client::ResponseFuture,
309-
) -> Result<(http::StatusCode, String, String), AzureError> {
310-
let res = resp.await?;
319+
) -> Result<(http::StatusCode, String, String), HttpError> {
320+
let res = resp.await.map_err(HttpError::ExecuteRequestError)?;
311321
let status = res.status();
312322
let location: String = match res.headers().get("Location") {
313323
Some(header_value) => header_value.to_str()?.to_owned(),
314324
_ => "".to_owned(),
315325
};
316-
let body = body::to_bytes(res.into_body()).await?;
317-
Ok((status, location, str::from_utf8(&body)?.to_owned()))
326+
let body = body::to_bytes(res.into_body())
327+
.await
328+
.map_err(HttpError::ReadBytesError)?;
329+
Ok((status, location, std::str::from_utf8(&body)?.to_owned()))
318330
}
319331

320332
#[cfg(feature = "enable_hyper")]
@@ -327,11 +339,7 @@ pub async fn check_status_extract_body(
327339
if status == expected_status_code {
328340
Ok(body)
329341
} else {
330-
Err(AzureError::UnexpectedHTTPResult(UnexpectedHTTPResult::new(
331-
expected_status_code,
332-
status,
333-
&body,
334-
)))
342+
Err(HttpError::new_unexpected_status_code(expected_status_code, status, &body).into())
335343
}
336344
}
337345

@@ -341,16 +349,13 @@ pub async fn check_status_extract_body_2(
341349
expected_status: StatusCode,
342350
) -> Result<String, AzureError> {
343351
let received_status = resp.status();
344-
345-
let body = body::to_bytes(resp.into_body()).await?;
352+
let body = body::to_bytes(resp.into_body())
353+
.await
354+
.map_err(HttpError::ReadBytesError)?;
346355
let s = String::from_utf8(body.to_vec())?;
347356
debug!("body: {}", s);
348357
if received_status != expected_status {
349-
Err(AzureError::UnexpectedHTTPResult(UnexpectedHTTPResult::new(
350-
expected_status,
351-
received_status,
352-
&s,
353-
)))
358+
Err(HttpError::new_unexpected_status_code(expected_status, received_status, &s).into())
354359
} else {
355360
Ok(s)
356361
}
@@ -385,18 +390,4 @@ mod test {
385390
fn test_azure_error_sync() {
386391
error_generator().map_err(sync_fn).unwrap();
387392
}
388-
389-
// This does not compile
390-
//#[test]
391-
//fn test_not_send() {
392-
// let a = std::rc::Rc::new(100);
393-
// send_fn(a);
394-
//}
395-
396-
// This does not compile
397-
//#[test]
398-
//fn test_not_sync() {
399-
// let a = std::cell::Cell::new(500);
400-
// sync_fn(a);
401-
//}
402393
}

sdk/core/src/headers/mod.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,13 @@ pub const LEASE_BREAK_PERIOD: &str = "x-ms-lease-break-period";
6363
pub const PROPOSED_LEASE_ID: &str = "x-ms-proposed-lease-id";
6464
pub const LEASE_TIME: &str = "x-ms-lease-time";
6565
pub const CREATION_TIME: &str = "x-ms-creation-time";
66-
pub const COPY_ID: &str = "x-ms-copy-id";
6766
pub const COPY_STATUS_DESCRIPTION: &str = "x-ms-copy-status-description";
6867
pub const COPY_COMPLETION_TIME: &str = "x-ms-copy-completion-time";
6968
pub const COPY_PROGRESS: &str = "x-ms-copy-progress";
7069
pub const COPY_SOURCE: &str = "x-ms-copy-source";
7170
pub const COPY_STATUS: &str = "x-ms-copy-status";
72-
pub const CONTENT_MD5: &str = "Content-MD5";
7371
pub const SERVER_ENCRYPTED: &str = "x-ms-server-encrypted";
7472
pub const BLOB_TYPE: &str = "x-ms-blob-type";
75-
pub const CONTENT_CRC64: &str = "x-ms-content-crc64";
7673
pub const BLOB_CONTENT_LENGTH: &str = "x-ms-blob-content-length";
7774
pub const BLOB_ACCESS_TIER: &str = "x-ms-access-tier";
7875
pub const BLOB_SEQUENCE_NUMBER: &str = "x-ms-blob-sequence-number";

0 commit comments

Comments
 (0)