mirror of
https://github.com/OMGeeky/google-apis-rs.git
synced 2025-12-26 17:02:24 +01:00
feat(Hub): Support custom connectors
Switch the constraints on Hub types to use public traits based on tower::service, as recommended by Hyper. This enables support for custom connectors beyond hyper_rustls::HttpsConnector Closes #337.
This commit is contained in:
@@ -27,4 +27,7 @@ cargo:
|
||||
doc_base_url: https://docs.rs
|
||||
dependencies:
|
||||
- hyper = "^ 0.14"
|
||||
- http = "^0.2"
|
||||
- tokio = "^1.0"
|
||||
- tower-service = "^0.3.1"
|
||||
- url = "= 1.7"
|
||||
|
||||
@@ -29,5 +29,7 @@ cargo:
|
||||
dependencies:
|
||||
- strsim = "^0.5"
|
||||
- clap = "^2.0"
|
||||
- http = "^0.2"
|
||||
- hyper = { version = "0.14", features = ["full"] }
|
||||
- tokio = { version = "^ 1.0", features = ["full"] }
|
||||
- tower-service = "^0.3.1"
|
||||
|
||||
@@ -19,12 +19,17 @@ use std::collections::HashMap;
|
||||
use std::cell::RefCell;
|
||||
use std::default::Default;
|
||||
use std::collections::BTreeMap;
|
||||
use std::error::Error as StdError;
|
||||
use serde_json as json;
|
||||
use std::io;
|
||||
use std::fs;
|
||||
use std::mem;
|
||||
use std::thread::sleep;
|
||||
|
||||
use http::Uri;
|
||||
use hyper::client::connect;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tower_service;
|
||||
use crate::client;
|
||||
|
||||
// ##############
|
||||
@@ -49,8 +54,8 @@ ${lib.hub_usage_example(c)}\
|
||||
</%block>
|
||||
#[derive(Clone)]
|
||||
pub struct ${hub_type}${ht_params} {
|
||||
pub client: hyper::Client<hyper_rustls::HttpsConnector<hyper::client::connect::HttpConnector>, hyper::body::Body>,
|
||||
pub auth: oauth2::authenticator::Authenticator<hyper_rustls::HttpsConnector<hyper::client::connect::HttpConnector>>,
|
||||
pub client: hyper::Client<S, hyper::body::Body>,
|
||||
pub auth: oauth2::authenticator::Authenticator<S>,
|
||||
_user_agent: String,
|
||||
_base_url: String,
|
||||
_root_url: String,
|
||||
@@ -60,7 +65,7 @@ impl<'a, ${', '.join(HUB_TYPE_PARAMETERS)}> client::Hub for ${hub_type}${ht_para
|
||||
|
||||
impl<'a, ${', '.join(HUB_TYPE_PARAMETERS)}> ${hub_type}${ht_params} {
|
||||
|
||||
pub fn new(client: hyper::Client<hyper_rustls::HttpsConnector<hyper::client::connect::HttpConnector>, hyper::body::Body>, authenticator: oauth2::authenticator::Authenticator<hyper_rustls::HttpsConnector<hyper::client::connect::HttpConnector>>) -> ${hub_type}${ht_params} {
|
||||
pub fn new(client: hyper::Client<S, hyper::body::Body>, authenticator: oauth2::authenticator::Authenticator<S>) -> ${hub_type}${ht_params} {
|
||||
${hub_type} {
|
||||
client,
|
||||
auth: authenticator,
|
||||
|
||||
@@ -132,7 +132,13 @@ pub struct ${ThisType}
|
||||
|
||||
impl${mb_tparams} ${CALL_BUILDER_MARKERT_TRAIT} for ${ThisType} {}
|
||||
|
||||
impl${mb_tparams} ${ThisType} {
|
||||
impl${mb_tparams} ${ThisType}
|
||||
where
|
||||
S: tower_service::Service<Uri> + Clone + Send + Sync + 'static,
|
||||
S::Response: hyper::client::connect::Connection + AsyncRead + AsyncWrite + Send + Unpin + 'static,
|
||||
S::Future: Send + Unpin + 'static,
|
||||
S::Error: Into<Box<dyn StdError + Send + Sync>>,
|
||||
{
|
||||
% if api.get('no_upload_prefix') is not None and ThisType.startswith(api.no_upload_prefix):
|
||||
${self._action_fn(c, resource, method, m, params, request_value, parts, doit_without_upload = True)}\
|
||||
% endif
|
||||
@@ -179,9 +185,9 @@ ${self._setter_fn(resource, method, m, p, part_prop, ThisType, c)}\
|
||||
/// Usually there is more than one suitable scope to authorize an operation, some of which may
|
||||
/// encompass more rights than others. For example, for listing resources, a *read-only* scope will be
|
||||
/// sufficient, a read-write scope will do as well.
|
||||
pub fn ${ADD_SCOPE_FN}<T, S>(mut self, scope: T) -> ${ThisType}
|
||||
where T: Into<Option<S>>,
|
||||
S: AsRef<str> {
|
||||
pub fn ${ADD_SCOPE_FN}<T, St>(mut self, scope: T) -> ${ThisType}
|
||||
where T: Into<Option<St>>,
|
||||
St: AsRef<str> {
|
||||
match scope.into() {
|
||||
Some(scope) => self.${api.properties.scopes}.insert(scope.as_ref().to_string(), ()),
|
||||
None => None,
|
||||
|
||||
@@ -36,25 +36,36 @@ use client::{InvalidOptionsError, CLIError, arg_from_str, writer_from_opts, pars
|
||||
calltype_from_str, remove_json_null_values, ComplexType, JsonType, JsonTypeInfo};
|
||||
|
||||
use std::default::Default;
|
||||
use std::error::Error as StdError;
|
||||
use std::str::FromStr;
|
||||
|
||||
use serde_json as json;
|
||||
use clap::ArgMatches;
|
||||
use http::Uri;
|
||||
use hyper::client::connect;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tower_service;
|
||||
|
||||
enum DoitError {
|
||||
IoError(String, io::Error),
|
||||
ApiError(Error),
|
||||
}
|
||||
|
||||
struct Engine<'n> {
|
||||
struct Engine<'n, S> {
|
||||
opt: ArgMatches<'n>,
|
||||
hub: ${hub_type_name},
|
||||
hub: ${hub_type_name}<S>,
|
||||
gp: ${"Vec<&'static str>"},
|
||||
gpm: Vec<(&'static str, &'static str)>,
|
||||
}
|
||||
|
||||
|
||||
impl<'n> Engine<'n> {
|
||||
impl<'n, S> Engine<'n, S>
|
||||
where
|
||||
S: tower_service::Service<Uri> + Clone + Send + Sync + 'static,
|
||||
S::Response: hyper::client::connect::Connection + AsyncRead + AsyncWrite + Send + Unpin + 'static,
|
||||
S::Future: Send + Unpin + 'static,
|
||||
S::Error: Into<Box<dyn StdError + Send + Sync>>,
|
||||
{
|
||||
% for resource in sorted(c.rta_map.keys()):
|
||||
% for method in sorted(c.rta_map[resource]):
|
||||
async fn ${call_method_ident(resource, method)}(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
@@ -102,7 +113,7 @@ impl<'n> Engine<'n> {
|
||||
}
|
||||
|
||||
// Please note that this call will fail if any part of the opt can't be handled
|
||||
async fn new(opt: ArgMatches<'n>) -> Result<Engine<'n>, InvalidOptionsError> {
|
||||
async fn new(opt: ArgMatches<'n>, connector: S) -> Result<Engine<'n, S>, InvalidOptionsError> {
|
||||
let (config_dir, secret) = {
|
||||
let config_dir = match client::assure_config_dir_exists(opt.value_of("${CONFIG_DIR_ARG}").unwrap_or("${CONFIG_DIR}")) {
|
||||
Err(e) => return Err(InvalidOptionsError::single(e, 3)),
|
||||
@@ -116,18 +127,14 @@ impl<'n> Engine<'n> {
|
||||
}
|
||||
};
|
||||
|
||||
let auth = oauth2::InstalledFlowAuthenticator::builder(
|
||||
let client = hyper::Client::builder().build(connector);
|
||||
|
||||
let auth = oauth2::InstalledFlowAuthenticator::with_client(
|
||||
secret,
|
||||
oauth2::InstalledFlowReturnMethod::HTTPRedirect,
|
||||
client.clone(),
|
||||
).persist_tokens_to_disk(format!("{}/${util.program_name()}", config_dir)).build().await.unwrap();
|
||||
|
||||
let client = hyper::Client::builder().build(
|
||||
hyper_rustls::HttpsConnectorBuilder::new().with_native_roots()
|
||||
.https_or_http()
|
||||
.enable_http1()
|
||||
.enable_http2()
|
||||
.build()
|
||||
);
|
||||
<% gpm = gen_global_parameter_names(parameters) %>\
|
||||
let engine = Engine {
|
||||
opt: opt,
|
||||
|
||||
@@ -35,8 +35,14 @@ async fn main() {
|
||||
${argparse.new(c) | indent_all_but_first_by(1)}\
|
||||
let matches = app.get_matches();
|
||||
|
||||
let debug = matches.is_present("${DEBUG_FLAG}");
|
||||
match Engine::new(matches).await {
|
||||
let debug = matches.is_present("a${DEBUG_FLAG}");
|
||||
let connector = hyper_rustls::HttpsConnectorBuilder::new().with_native_roots()
|
||||
.https_or_http()
|
||||
.enable_http1()
|
||||
.enable_http2()
|
||||
.build();
|
||||
|
||||
match Engine::new(matches, connector).await {
|
||||
Err(err) => {
|
||||
exit_status = err.exit_code;
|
||||
writeln!(io::stderr(), "{}", err).ok();
|
||||
|
||||
@@ -112,7 +112,7 @@ data_unit_multipliers = {
|
||||
'%': 1,
|
||||
}
|
||||
|
||||
HUB_TYPE_PARAMETERS = ()
|
||||
HUB_TYPE_PARAMETERS = ('S',)
|
||||
|
||||
def items(p):
|
||||
if isinstance(p, dict):
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use std::error;
|
||||
use std::error::Error as StdError;
|
||||
use std::fmt::{self, Display};
|
||||
use std::io::{self, Cursor, Read, Seek, SeekFrom, Write};
|
||||
use std::str::FromStr;
|
||||
@@ -7,7 +8,10 @@ use std::time::Duration;
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
use http::Uri;
|
||||
|
||||
use hyper::body::Buf;
|
||||
use hyper::client::connect;
|
||||
use hyper::header::{HeaderMap, AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE, USER_AGENT};
|
||||
use hyper::Method;
|
||||
use hyper::StatusCode;
|
||||
@@ -16,6 +20,9 @@ use mime::{Attr, Mime, SubLevel, TopLevel, Value};
|
||||
|
||||
use serde_json as json;
|
||||
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tower_service;
|
||||
|
||||
const LINE_ENDING: &str = "\r\n";
|
||||
|
||||
pub enum Retry {
|
||||
@@ -564,9 +571,15 @@ impl RangeResponseHeader {
|
||||
}
|
||||
|
||||
/// A utility type to perform a resumable upload from start to end.
|
||||
pub struct ResumableUploadHelper<'a, A: 'a> {
|
||||
pub struct ResumableUploadHelper<'a, A: 'a, S>
|
||||
where
|
||||
S: tower_service::Service<Uri> + Clone + Send + Sync + 'static,
|
||||
S::Response: hyper::client::connect::Connection + AsyncRead + AsyncWrite + Send + Unpin + 'static,
|
||||
S::Future: Send + Unpin + 'static,
|
||||
S::Error: Into<Box<dyn StdError + Send + Sync>>,
|
||||
{
|
||||
pub client: &'a hyper::client::Client<
|
||||
hyper_rustls::HttpsConnector<hyper::client::connect::HttpConnector>,
|
||||
S,
|
||||
hyper::body::Body,
|
||||
>,
|
||||
pub delegate: &'a mut dyn Delegate,
|
||||
@@ -580,7 +593,13 @@ pub struct ResumableUploadHelper<'a, A: 'a> {
|
||||
pub content_length: u64,
|
||||
}
|
||||
|
||||
impl<'a, A> ResumableUploadHelper<'a, A> {
|
||||
impl<'a, A, S> ResumableUploadHelper<'a, A, S>
|
||||
where
|
||||
S: tower_service::Service<Uri> + Clone + Send + Sync + 'static,
|
||||
S::Response: hyper::client::connect::Connection + AsyncRead + AsyncWrite + Send + Unpin + 'static,
|
||||
S::Future: Send + Unpin + 'static,
|
||||
S::Error: Into<Box<dyn StdError + Send + Sync>>,
|
||||
{
|
||||
async fn query_transfer_status(
|
||||
&mut self,
|
||||
) -> std::result::Result<u64, hyper::Result<hyper::Response<hyper::body::Body>>> {
|
||||
|
||||
Reference in New Issue
Block a user