Skip to content

Commit 4391eed

Browse files
committed
Consolidate HTTP client errors and flatten exports
This change replaces the per-HTTP-client error types with a single generic `HttpClientError` type shared by all the built-in clients. This allows us to remove the public `reqwest`, `curl`, and `ureq` modules and directly re-export those crates from the root, which allows imports such as `oauth2::reqwest` instead of `oauth2::reqwest::reqwest`. BREAKING CHANGES: - Removed `reqwest`, `curl`, and `ureq` modules. The corresponding crates are now re-exported from the root of this crate. - `CurlHttpClient` is now exported from the root of this crate when the `curl` feature is enabled. - Per-client error enums (e.g., `oauth2::reqwest::Error`) have been replaced with a generic `HttpClientError` type (e.g., `oauth2::HttpClientError<reqwest::Error>`).
1 parent 5ab6607 commit 4391eed

14 files changed

+163
-170
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ jobs:
5858
- name: Doc tests
5959
run: |
6060
cargo test --doc
61+
cargo test --doc --no-default-features
6162
cargo test --doc --all-features
6263
- name: Test with all features enabled
6364
run: cargo test --all-features

examples/github.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
//!
1515
1616
use oauth2::basic::BasicClient;
17-
use oauth2::reqwest::reqwest;
17+
use oauth2::reqwest;
1818
use oauth2::{
1919
AuthUrl, AuthorizationCode, ClientId, ClientSecret, CsrfToken, RedirectUrl, Scope,
2020
TokenResponse, TokenUrl,

examples/github_async.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
//!
1515
1616
use oauth2::basic::BasicClient;
17-
use oauth2::reqwest::reqwest;
17+
use oauth2::reqwest;
1818
use oauth2::{
1919
AuthUrl, AuthorizationCode, ClientId, ClientSecret, CsrfToken, RedirectUrl, Scope,
2020
TokenResponse, TokenUrl,

examples/google.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
//! ...and follow the instructions.
1414
//!
1515
16-
use oauth2::reqwest::reqwest;
16+
use oauth2::reqwest;
1717
use oauth2::{basic::BasicClient, StandardRevocableToken, TokenResponse};
1818
use oauth2::{
1919
AuthUrl, AuthorizationCode, ClientId, ClientSecret, CsrfToken, PkceCodeChallenge, RedirectUrl,

examples/google_devicecode.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
//!
1515
1616
use oauth2::basic::BasicClient;
17-
use oauth2::reqwest::reqwest;
17+
use oauth2::reqwest;
1818
use oauth2::{
1919
AuthType, AuthUrl, ClientId, ClientSecret, DeviceAuthorizationResponse, DeviceAuthorizationUrl,
2020
ExtraDeviceAuthorizationFields, Scope, TokenUrl,

examples/microsoft_devicecode_tenant_user.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use oauth2::basic::BasicClient;
2-
use oauth2::reqwest::reqwest;
2+
use oauth2::reqwest;
33
use oauth2::StandardDeviceAuthorizationResponse;
44
use oauth2::{AuthUrl, ClientId, DeviceAuthorizationUrl, Scope, TokenUrl};
55

examples/msgraph.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
//!
2222
2323
use oauth2::basic::BasicClient;
24-
use oauth2::reqwest::reqwest;
24+
use oauth2::reqwest;
2525
use oauth2::{
2626
AuthType, AuthUrl, AuthorizationCode, ClientId, ClientSecret, CsrfToken, PkceCodeChallenge,
2727
RedirectUrl, Scope, TokenUrl,

examples/wunderlist.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use oauth2::basic::{
1818
BasicErrorResponse, BasicRevocationErrorResponse, BasicTokenIntrospectionResponse,
1919
BasicTokenType,
2020
};
21-
use oauth2::reqwest::reqwest;
21+
use oauth2::reqwest;
2222
use oauth2::{
2323
AccessToken, AuthUrl, AuthorizationCode, Client, ClientId, ClientSecret, CsrfToken,
2424
EmptyExtraTokenFields, EndpointNotSet, ExtraTokenFields, RedirectUrl, RefreshToken, Scope,

src/curl.rs

Lines changed: 0 additions & 87 deletions
This file was deleted.

src/curl_client.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use crate::{HttpClientError, HttpRequest, HttpResponse, SyncHttpClient};
2+
3+
use curl::easy::Easy;
4+
use http::header::{HeaderValue, CONTENT_TYPE};
5+
use http::method::Method;
6+
use http::status::StatusCode;
7+
8+
use std::io::Read;
9+
10+
/// A synchronous HTTP client using [`curl`].
11+
pub struct CurlHttpClient;
12+
impl SyncHttpClient for CurlHttpClient {
13+
type Error = HttpClientError<curl::Error>;
14+
15+
fn call(&self, request: HttpRequest) -> Result<HttpResponse, Self::Error> {
16+
let mut easy = Easy::new();
17+
easy.url(&request.uri().to_string()[..]).map_err(Box::new)?;
18+
19+
let mut headers = curl::easy::List::new();
20+
for (name, value) in request.headers() {
21+
headers
22+
.append(&format!(
23+
"{}: {}",
24+
name,
25+
// TODO: Unnecessary fallibility, curl uses a CString under the hood
26+
value.to_str().map_err(|_| HttpClientError::Other(format!(
27+
"invalid `{name}` header value {:?}",
28+
value.as_bytes()
29+
)))?
30+
))
31+
.map_err(Box::new)?
32+
}
33+
34+
easy.http_headers(headers).map_err(Box::new)?;
35+
36+
if let Method::POST = *request.method() {
37+
easy.post(true).map_err(Box::new)?;
38+
easy.post_field_size(request.body().len() as u64)
39+
.map_err(Box::new)?;
40+
} else {
41+
assert_eq!(*request.method(), Method::GET);
42+
}
43+
44+
let mut form_slice = &request.body()[..];
45+
let mut data = Vec::new();
46+
{
47+
let mut transfer = easy.transfer();
48+
49+
transfer
50+
.read_function(|buf| Ok(form_slice.read(buf).unwrap_or(0)))
51+
.map_err(Box::new)?;
52+
53+
transfer
54+
.write_function(|new_data| {
55+
data.extend_from_slice(new_data);
56+
Ok(new_data.len())
57+
})
58+
.map_err(Box::new)?;
59+
60+
transfer.perform().map_err(Box::new)?;
61+
}
62+
63+
let mut builder = http::Response::builder().status(
64+
StatusCode::from_u16(easy.response_code().map_err(Box::new)? as u16)
65+
.map_err(http::Error::from)?,
66+
);
67+
68+
if let Some(content_type) = easy
69+
.content_type()
70+
.map_err(Box::new)?
71+
.map(HeaderValue::from_str)
72+
.transpose()
73+
.map_err(http::Error::from)?
74+
{
75+
builder = builder.header(CONTENT_TYPE, content_type);
76+
}
77+
78+
builder.body(data).map_err(HttpClientError::Http)
79+
}
80+
}

0 commit comments

Comments
 (0)