google-apis-rs
google-apis-rs copied to clipboard
[drive3] "there is no reactor running, must be called from the context of a Tokio 1.x runtime"
I get:
thread 'main' panicked at 'there is no reactor running, must be called from the context of a Tokio 1.x runtime', /Users/moritz/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.8.1/src/runtime/context.rs:18:26
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
I tried just wrapping a main around the example from the docs:
use google_drive3 as drive3;
use hyper;
use hyper_rustls;
use yup_oauth2 as oauth2;
use drive3::DriveHub;
use drive3::Error;
use std::default::Default;
use futures::executor::block_on;
fn main() {
let future = gdrive();
block_on(future);
}
async fn gdrive() {
// Get an ApplicationSecret instance by some means. It contains the `client_id` and
// `client_secret`, among other things.
let secret: oauth2::ApplicationSecret = Default::default();
// Instantiate the authenticator. It will choose a suitable authentication flow for you,
// unless you replace `None` with the desired Flow.
// Provide your own `AuthenticatorDelegate` to adjust the way it operates and get feedback about
// what's going on. You probably want to bring in your own `TokenStorage` to persist tokens and
// retrieve them from storage.
let auth = yup_oauth2::InstalledFlowAuthenticator::builder(
secret,
yup_oauth2::InstalledFlowReturnMethod::HTTPRedirect,
)
.build()
.await
.unwrap();
let hub = DriveHub::new(
hyper::Client::builder().build(hyper_rustls::HttpsConnector::with_native_roots()),
auth,
);
// You can configure optional parameters by calling the respective setters at will, and
// execute the final call using `doit()`.
// Values shown here are possibly random and not representative !
let result = hub
.files()
.list()
.team_drive_id("invidunt")
.supports_team_drives(true)
.supports_all_drives(true)
.spaces("sed")
.q("ut")
.page_token("gubergren")
.page_size(-16)
.order_by("est")
.include_team_drive_items(true)
.include_permissions_for_view("ipsum")
.include_items_from_all_drives(true)
.drive_id("ea")
.corpus("dolor")
.corpora("Lorem")
.doit()
.await;
match result {
Err(e) => match e {
// The Error enum provides details about what exactly happened.
// You can also just use its `Debug`, `Display` or `Error` traits
Error::HttpError(_)
| Error::Io(_)
| Error::MissingAPIKey
| Error::MissingToken(_)
| Error::Cancelled
| Error::UploadSizeLimitExceeded(_, _)
| Error::Failure(_)
| Error::BadRequest(_)
| Error::FieldClash(_)
| Error::JsonDecodeError(_, _) => println!("{}", e),
},
Ok(res) => println!("Success: {:?}", res),
}
}
Thanks for the hint! That's probably an oversight.
Were you able to verify that adding the tokio runtime via derive (for example like #[tokio::runtime] fn main()…) works as expected?
If so, it should be trivial to add this part to the generated code blocks
So after fixing this (for others running into this, tokio needs the full feature enabled or the main macro to work), I get it to run and print:
Please direct your browser to ?scope=https://www.googleapis.com/auth/drive.metadata.readonly&access_type=offline&redirect_uri=http://127.0.0.1:65018&response_type=code&client_id= and follow the instructions displayed there.
Opening that link in Chrome gives me:
You are receiving this error either because your input OAuth2 scope name is invalid or it refers to a newer scope that is outside the domain of this legacy API.
This API was built at a time when the scope name format was not yet standardized. This is no longer the case and all valid scope names (both old and new) are catalogued at https://developers.google.com/identity/protocols/oauth2/scopes. Use that webpage to lookup (manually) the scope name associated with the API you are trying to call and use it to craft your OAuth2 request.
Aka: no cigar. :/
For reference, my code now looks like this:
use google_drive3 as drive3;
use hyper;
use hyper_rustls;
use yup_oauth2 as oauth2;
use drive3::DriveHub;
use drive3::Error;
use std::default::Default;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let secret: oauth2::ApplicationSecret = Default::default();
let auth = yup_oauth2::InstalledFlowAuthenticator::builder(
secret,
yup_oauth2::InstalledFlowReturnMethod::HTTPRedirect,
)
.build()
.await
.unwrap();
let hub = DriveHub::new(
hyper::Client::builder().build(hyper_rustls::HttpsConnector::with_native_roots()),
auth,
);
let result = hub
.files()
.list()
.team_drive_id("invidunt")
.supports_team_drives(true)
.supports_all_drives(true)
.spaces("sed")
.q("ut")
.page_token("gubergren")
.page_size(-16)
.order_by("est")
.include_team_drive_items(true)
.include_permissions_for_view("ipsum")
.include_items_from_all_drives(true)
.drive_id("ea")
.corpus("dolor")
.corpora("Lorem")
.doit()
.await;
match result {
Err(e) => match e {
// The Error enum provides details about what exactly happened.
// You can also just use its `Debug`, `Display` or `Error` traits
Error::HttpError(_)
| Error::Io(_)
| Error::MissingAPIKey
| Error::MissingToken(_)
| Error::Cancelled
| Error::UploadSizeLimitExceeded(_, _)
| Error::Failure(_)
| Error::BadRequest(_)
| Error::FieldClash(_)
| Error::JsonDecodeError(_, _) => println!("{}", e),
},
Ok(res) => println!("Success: {:?}", res),
}
Ok(())
}
Thanks a lot, this will help!
Regarding authentication, that's probably a bit under-documented in the documentation right now. I would expect that the yup-oauth2 docs should more helpful to get this to work. In short, one would have to setup an application and respective API assignments in the google dev console to get a JSON secret for use in the application. The default one it generates was one linked to my account but it expired long ago.
Came across this and just wanted to clarify for people seeing this in the future. From my testing (as of 5.0.3), I was able to make the OAuth2 request go through by specifying the fields:
secret.client_id = "client_id".to_string();
secret.client_secret = "client_secret".to_string();
secret.project_id = Some("project_id".to_string());
secret.auth_uri = "https://accounts.google.com/o/oauth2/auth".to_string();
secret.token_uri = "https://oauth2.googleapis.com/token".to_string();
secret.auth_provider_x509_cert_url =
Some("https://www.googleapis.com/oauth2/v1/certs".to_string());
The fields can be found in the token file generated preliminary :) Reference