Skip to content

Commit

Permalink
Update to futures 0.3.0 and async await syntax (#71)
Browse files Browse the repository at this point in the history
Add `futures-01` and `futures-03` feature flags. The `futures-03`
feature flag adds a dependency on `reqwest` 0.10 (currently unstable),
while the default `reqwest` feature flag continues to rely on `reqwest`
0.9, which doesn't support async/await.
  • Loading branch information
marcelbuesing authored and ramosbugs committed Nov 18, 2019
1 parent 405f6b3 commit e51417e
Show file tree
Hide file tree
Showing 15 changed files with 543 additions and 203 deletions.
32 changes: 21 additions & 11 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
language: rust
rust:
- 1.34.0
- stable
- beta
- nightly
sudo: false
cache: cargo
branches:
only:
- master
- support/1.x
- support/2.x
before_script:
- cargo install --force cargo-audit
- cargo install --force cargo-when
- cargo when -v ^1.39 install --force cargo-audit
script:
- cargo test
- cargo test --example google
- cargo test --example github
- cargo test --example msgraph
- cargo audit
# Tests should run on all supported rustc versions
- cargo test --tests --examples
# Docs rely on async/await and only work on rustc >= 1.39.0
- cargo when -v ^1.39 -- test --doc
# Enabling all features (including async/await) requires rustc >= 1.39.0
- cargo when -v ^1.39 -- test --all-features
- cargo when -v ^1.39 -- test --tests --examples --no-default-features --features futures-03
# Blocking reqwest using reqwest 0.9
- cargo test --tests --examples --features reqwest --no-default-features
# Futures 0.1 without reqwest (examples will not build)
- cargo test --tests --features futures-01 --no-default-features
# Futures 0.3 without reqwest 0.9 (but includes reqwest 0.10)
- cargo when -v ^1.39 -- test --tests --examples --features futures-03 --no-default-features
# Futures 0.1 with reqwest 0.9
- cargo test --tests --examples --features reqwest,futures-01 --no-default-features
# Futures 0.3 with reqwest 0.9 (included by default)
- cargo when -v ^1.39 -- test --tests --examples --features futures-03
- cargo when -v ^1.39 audit
notifications:
email:
on_success: never
16 changes: 11 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,30 @@ version = "3.0.0-alpha.5"
license = "MIT/Apache-2.0"
description = "Bindings for exchanging OAuth 2 tokens"
repository = "https://github.com/ramosbugs/oauth2-rs"
edition = "2018"

[features]
default = ["reqwest"]
futures-01 = ["futures-0-1"]
futures-03 = ["futures-0-3", "async-std", "async-trait", "reqwest-0-10"]
reqwest = ["reqwest-0-9"]

[dependencies]
async-std = { version = "1.0", optional = true }
async-trait = { version = "0.1", optional = true }
base64 = "0.10"
curl = { version = "0.4.0", optional = true }
failure = "0.1"
failure_derive = "0.1"
futures = "0.1"
futures-0-1 = { version = "0.1", optional = true, package = "futures" }
futures-0-3 = { version = "0.3", optional = true, package = "futures" }
http = "0.1"
rand = "0.6"
reqwest = { version = "0.9", optional = true }
serde = "1.0"
reqwest-0-9 = { version = "0.9", optional = true, package = "reqwest" }
reqwest-0-10 = { version = "0.10.0-alpha.2", optional = true, features = ["blocking"], package = "reqwest" }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_derive = "1.0"
sha2 = "0.7"
tokio-io = "0.1"
url = "2.1"

[dev-dependencies]
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,23 @@ Build:
cargo build
```

using futures 0.3:
this requires at least rust 1.39.0
```
cargo build --no-default-features --features "futures-03"
```

Run tests:

```
cargo test
```

using futures 0.3:
```
cargo test --no-default-features --features "futures-03"
```

Release:

```
Expand Down
6 changes: 1 addition & 5 deletions examples/github.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,8 @@
//! ...and follow the instructions.
//!

extern crate base64;
extern crate oauth2;
extern crate rand;
extern crate url;

use oauth2::basic::BasicClient;

// Alternatively, this can be `oauth2::curl::http_client` or a custom client.
use oauth2::reqwest::http_client;
use oauth2::{
Expand Down
5 changes: 0 additions & 5 deletions examples/google.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@
//! ...and follow the instructions.
//!

extern crate base64;
extern crate oauth2;
extern crate rand;
extern crate url;

use oauth2::basic::BasicClient;
// Alternatively, this can be oauth2::curl::http_client or a custom.
use oauth2::reqwest::http_client;
Expand Down
5 changes: 0 additions & 5 deletions examples/msgraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@
//! ...and follow the instructions.
//!

extern crate base64;
extern crate oauth2;
extern crate rand;
extern crate url;

use oauth2::basic::BasicClient;
// Alternatively, this can be `oauth2::curl::http_client` or a custom client.
use oauth2::reqwest::http_client;
Expand Down
6 changes: 0 additions & 6 deletions examples/wunderlist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@
//! ...and follow the instructions.
//!

extern crate base64;
extern crate oauth2;
extern crate rand;
extern crate serde;
extern crate url;

use oauth2::basic::{BasicErrorResponse, BasicTokenType};
use oauth2::TokenType;
// Alternatively, this can be `oauth2::curl::http_client` or a custom client.
Expand Down
185 changes: 185 additions & 0 deletions src/async_internal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
use crate::{
token_response, ClientCredentialsTokenRequest, CodeTokenRequest, ErrorResponse, HttpRequest,
HttpResponse, PasswordTokenRequest, RefreshTokenRequest, RequestTokenError, TokenResponse,
TokenType,
};
use async_trait::async_trait;
use failure::Fail;
use futures_0_3::Future;

///
/// Asynchronous request to exchange an authorization code for an access token.
///
#[async_trait]
pub trait AsyncCodeTokenRequest<TE, TR, TT>
where
TE: ErrorResponse + 'static,
TR: TokenResponse<TT> + Send,
TT: TokenType + Send,
{
///
/// Asynchronously sends the request to the authorization server.
///
async fn request_async<C, F, RE>(self, http_client: C) -> Result<TR, RequestTokenError<RE, TE>>
where
C: FnOnce(HttpRequest) -> F + Send,
F: Future<Output = Result<HttpResponse, RE>> + Send,
RE: Fail;
}

#[async_trait]
impl<TE, TR, TT> AsyncCodeTokenRequest<TE, TR, TT> for CodeTokenRequest<'_, TE, TR, TT>
where
TE: ErrorResponse + 'static,
TR: TokenResponse<TT> + Send,
TT: TokenType + Send,
{
///
/// Asynchronously sends the request to the authorization server and returns a Future.
///
async fn request_async<C, F, RE>(self, http_client: C) -> Result<TR, RequestTokenError<RE, TE>>
where
C: FnOnce(HttpRequest) -> F + Send,
F: Future<Output = Result<HttpResponse, RE>> + Send,
RE: Fail,
{
let http_request = self.prepare_request()?;
let http_response = http_client(http_request)
.await
.map_err(RequestTokenError::Request)?;
token_response(http_response)
}
}

///
/// Asynchronous request to exchange a refresh token for an access token.
///
#[async_trait]
pub trait AsyncRefreshTokenRequest<TE, TR, TT>
where
TE: ErrorResponse + 'static,
TR: TokenResponse<TT> + Send,
TT: TokenType + Send,
{
///
/// Asynchronously sends the request to the authorization server and awaits a response.
///
async fn request_async<C, F, RE>(self, http_client: C) -> Result<TR, RequestTokenError<RE, TE>>
where
C: FnOnce(HttpRequest) -> F + Send,
F: Future<Output = Result<HttpResponse, RE>> + Send,
RE: Fail;
}

#[async_trait]
impl<TE, TR, TT> AsyncRefreshTokenRequest<TE, TR, TT> for RefreshTokenRequest<'_, TE, TR, TT>
where
TE: ErrorResponse + 'static,
TR: TokenResponse<TT> + Send,
TT: TokenType + Send,
{
///
/// Asynchronously sends the request to the authorization server and awaits a response.
///
async fn request_async<C, F, RE>(self, http_client: C) -> Result<TR, RequestTokenError<RE, TE>>
where
C: FnOnce(HttpRequest) -> F + Send,
F: Future<Output = Result<HttpResponse, RE>> + Send,
RE: Fail,
{
let http_request = self.prepare_request()?;
let http_response = http_client(http_request)
.await
.map_err(RequestTokenError::Request)?;
token_response(http_response)
}
}

///
/// Asynchronous request to exchange resource owner credentials for an access token.
///
#[async_trait]
pub trait AsyncPasswordTokenRequest<TE, TR, TT>
where
TE: ErrorResponse + 'static,
TR: TokenResponse<TT> + Send,
TT: TokenType + Send,
{
///
/// Asynchronously sends the request to the authorization server and awaits a response.
///
async fn request_async<C, F, RE>(self, http_client: C) -> Result<TR, RequestTokenError<RE, TE>>
where
C: FnOnce(HttpRequest) -> F + Send,
F: Future<Output = Result<HttpResponse, RE>> + Send,
RE: Fail;
}

#[async_trait]
impl<TE, TR, TT> AsyncPasswordTokenRequest<TE, TR, TT> for PasswordTokenRequest<'_, TE, TR, TT>
where
TE: ErrorResponse + 'static,
TR: TokenResponse<TT> + Send,
TT: TokenType + Send,
{
///
/// Asynchronously sends the request to the authorization server and awaits a response.
///
async fn request_async<C, F, RE>(self, http_client: C) -> Result<TR, RequestTokenError<RE, TE>>
where
C: FnOnce(HttpRequest) -> F + Send,
F: Future<Output = Result<HttpResponse, RE>> + Send,
RE: Fail,
{
let http_request = self.prepare_request()?;
let http_response = http_client(http_request)
.await
.map_err(RequestTokenError::Request)?;
token_response(http_response)
}
}

///
/// Asynchronous request to exchange client credentials for an access token.
///
#[async_trait]
pub trait AsyncClientCredentialsTokenRequest<TE, TR, TT>
where
TE: ErrorResponse + 'static,
TR: TokenResponse<TT> + Send,
TT: TokenType + Send,
{
///
/// Asynchronously sends the request to the authorization server and awaits a response.
///
async fn request_async<C, F, RE>(self, http_client: C) -> Result<TR, RequestTokenError<RE, TE>>
where
C: FnOnce(HttpRequest) -> F + Send,
F: Future<Output = Result<HttpResponse, RE>> + Send,
RE: Fail;
}

#[async_trait]
impl<TE, TR, TT> AsyncClientCredentialsTokenRequest<TE, TR, TT>
for ClientCredentialsTokenRequest<'_, TE, TR, TT>
where
TE: ErrorResponse + 'static,
TR: TokenResponse<TT> + Send,
TT: TokenType + Send,
{
///
/// Asynchronously sends the request to the authorization server and awaits a response.
///
async fn request_async<C, F, RE>(self, http_client: C) -> Result<TR, RequestTokenError<RE, TE>>
where
C: FnOnce(HttpRequest) -> F + Send,
F: Future<Output = Result<HttpResponse, RE>> + Send,
RE: Fail,
{
let http_request = self.prepare_request()?;
let http_response = http_client(http_request)
.await
.map_err(RequestTokenError::Request)?;
token_response(http_response)
}
}
4 changes: 2 additions & 2 deletions src/basic.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
extern crate serde_json;

use std::fmt::Error as FormatterError;
use std::fmt::{Debug, Display, Formatter};

Expand All @@ -9,6 +7,8 @@ use super::{
StandardTokenResponse, TokenType,
};

use serde::{Deserialize, Serialize};

///
/// Basic OAuth2 client specialization, suitable for most applications.
///
Expand Down
2 changes: 1 addition & 1 deletion src/curl.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::io::Read;

use curl_::easy::Easy;
use curl::easy::Easy;
use failure::Fail;
use http::header::{HeaderMap, HeaderValue, CONTENT_TYPE};
use http::method::Method;
Expand Down
Loading

0 comments on commit e51417e

Please sign in to comment.