New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update to futures 0.3.0 and async await syntax #71
Conversation
b56111a
to
754b943
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for the PR!
I'm hesitant to crate a separate branch since it may create a maintenance hassle. is it possible to offer an async/await interface alongside the existing interface, gated behind a feature flag? not sure if that compiles on older rustc versions or not.
I also don't think we're ready to require the 2018 edition for this crate. Maybe for a future 4.x release...
Thinking about this some more, as long as the crate compiles on older rustc versions with 2018 mode enabled, I'd be willing to discontinue support for 2015 with the async/await API behind a feature flag. So, there should be three interfaces in this crate:
|
Ok I just added it behind a feature flag. Good thing is I assume this will also be necessary for the next stable reqwest versions, as far as I can tell it does not look like reqwest will continue support of futures 0.1 in new versions (at least there is no feature flag gating). Downside some duplicate code, and feature flags also required in doc tests (this may be confusing I assume for some when looking at the docs). I am not entirely sure about 2018/2015 rustc downwards compatibility. The reason why I used the runtime crate instead of the latest tokio alpha for the async/await lib doc test was that I did not figure out how to handle two different tokio dev-dependencies. Using the package renaming did work not in this case. |
Really appreciate the work you've put into this! I spent a bit of time testing compatibility, and it looks like this effectively sets the minimum Rust version to 1.36.0 (2019-07-04). In anything prior, I get:
(even with It's one thing to drop support for the 2015 edition, but 1.36 seems a bit too recent (<4 months) to require in order for people to use the 3.x release of this crate. I think it would be prudent to wait a couple of months before imposing the 1.36 requirement (possibly on a 4.x release train), unless we can figure out a way to make it work on older toolchains. I wonder if there's a way to use proc macros to generate the async/await code only when the feature is enabled, or something. |
Fair point, I think it certainly makes sense to somehow make it work for users that can not use a 1.36+ version. I have seen multiple issues with older versions. 1.32.0
1.33.0
1.34.0
1.35.0
If you have a particular version in mind I'll try to make it work somehow. Maybe 1.34.0 would be a good candidate, I assume the await keyword problem is solvable. |
Interesting, I didn't realize the crate was already broken for versions < 1.34. If that's indeed the case, then I can't foresee this PR causing any new problems if we can make it work for 1.34.0 and newer versions. I'll try to update the Travis-CI config so that it tests 1.34 compatibility going forward. I suspect breaking 1.33 and earlier was unintentional. |
Ok I asked here because I did not come up with an idea how to fix the keyword problem on 1.34. Regarding "Downstream can still use async.await even if you don't internally." When using async/await I'm not a big fan of using the compatibility layer in my code (although I think it's great that it exists!) since it makes the the code a lot more verbose, adding Anyway I'm kind of uncertain how to proceed, what do you think? |
Oh that's really interesting. If that indeed works, what if we:
Then, using the |
2403d22
to
e5e2bf7
Compare
It seems to work. Still requires some cleanup and documentation and I'm unsure whether all the Send constraints are a good idea, but in general it works if the async trait crate is used. CI currently fails because cargo audit fails on 1.34.0. Besides that, I have not found a way to make tests compile on 1.34.0 because async_std does not build on 1.34.0 but can not be made optional, since apparently dev-dependencies can not be made optional. |
Thanks! I'm planning to look this over fully this weekend, probably tomorrow.
I think we should be able to use |
src/reqwest.rs
Outdated
use reqwest::RedirectPolicy; | ||
|
||
#[cfg(feature = "futures-03")] | ||
use reqwest_futures_03::blocking; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah I didn't realize futures-01
and futures-03
would be mutually exclusive. when building with --all-features
, this causes:
error[E0252]: the name `blocking` is defined multiple times
--> /Users/daramos/Documents/Projects/oauth2-rs/src/reqwest.rs:17:5
|
10 | use reqwest as blocking;
| ------------------- previous import of the module `blocking` here
...
17 | use reqwest_futures_03::blocking;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `blocking` reimported here
|
= note: `blocking` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
17 | use reqwest_futures_03::blocking as other_blocking;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
is it possible to make them coexist?
Cargo.toml
Outdated
|
||
[features] | ||
default = ["reqwest"] | ||
default = ["futures-01"] | ||
futures-01 = ["futures-0-1", "reqwest"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we make the reqwest/curl (or neither) feature flags orthogonal to futures-01/futures-03? ideally library users should be able to request features ["reqwest", "futures-03"]
to indicate that they want both a reqwest
client and future-03
. the type of reqwest
client can be inferred from the type of futures, I think
src/async_internal.rs
Outdated
/// | ||
/// Asynchronous HTTP client. | ||
/// | ||
pub async fn async_http_client(request: HttpRequest) -> Result<HttpResponse, Error> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it be possible to move this to the reqwest
module? I think we can do a similar trick and put this in a private module inside oauth2::reqwest
and then conditionally pub use
it.
to avoid the name conflict, maybe we should rename the old async interface to future_http_client
and each of the old request_async
interfaces to request_future
? that should allow them to coexist, I think, and fix the --all-features
issue. it should also make the library easier to use since users can specify any combination of features without running into compilation errors.
src/reqwest.rs
Outdated
.map_err(Error::Reqwest) | ||
}) | ||
}) | ||
// Following redirects opens the client up to SSRF vulnerabilities. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doesn't cargo fmt
indent this?
Start removal of pre 2018 edition source code artifacts
This way reqwest and futures may also be used without each other.
d9bc6c6
to
8eb2d9d
Compare
thanks again! |
Awesome, I actually I did not think it would be possible to make it compile with all features! Looks great! |
Since async/await is about to be stabilized (7. Nov as far as I know) I think it would be great to have a branch until then that prepares the crate for that.
extern crates...
Not sure why the nightly CI is failing, it works locally using
nightly-2019-10-20