-
Notifications
You must be signed in to change notification settings - Fork 33
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
Add Proxy Support #487
Add Proxy Support #487
Conversation
I test it today manually and it works. User can create a client with proxy like this: use graph_rs_sdk::{
identity::ConfidentialClientApplication, GraphClient, GraphClientConfiguration, Proxy,
};
fn main() {
const TANENT_ID: &str = "xxx";
const CLIENT_ID: &str = "yyy";
const CLIENT_SECRET: &str = "zzz";
let confidential_client_application = ConfidentialClientApplication::builder(CLIENT_ID)
.with_client_secret(CLIENT_SECRET)
.with_tenant(TANENT_ID)
.build();
let proxy = Proxy::new("http://myporxy.com:3128").unwrap(); // <- here
let graph_client: GraphClient = GraphClientConfiguration::new()
.client_application(confidential_client_application)
.proxy(proxy) // <- here
.into();
// do something with graph_client ...
} |
Nice, i'll take a look at your PR and review it hopefully within a couple of days but it may be a little longer. Thanks for taking the initiative. |
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.
Hey, thanks for the PR. This looks good except for a few minor changes.
As far as abstracting the reqwest client. I mean yes, there are some controls for the reqwest client that the crate would like to abstract for various reasons. One of them being there are features that we would maybe like to enable, such as a socks proxy, but there are also features that we don't want to enable. Thats not the only reason but its an example. So to a certain extent there needs to be some abstraction and limits on what can be done with the http client from the perspective of someone using this crate.
But, as far as using another crates types for things in this case its completley fine. Its the same as reexporting the header types from reqwest for others to use. That may not always be the case with every type though, so it depends on a case by case basis.
graph-http/src/client.rs
Outdated
/// This is a thin wrapper for [`reqwest::Proxy`]. | ||
#[derive(Debug, Clone)] | ||
pub struct Proxy { | ||
proxy: reqwest::Proxy, | ||
} | ||
|
||
impl Proxy { | ||
/// Create proxy by a proxy url. | ||
/// | ||
/// If not a valid proxy url, return `None`. | ||
/// | ||
/// # Examples | ||
/// | ||
/// ```ignore | ||
/// assert!(Proxy::new("http://127.0.0.1:3128").is_some()); | ||
/// assert!(Proxy::new("ftp://192.168.0.1").is_none()); | ||
/// | ||
/// // `socks5` scheme require `socks-proxy` feature. | ||
/// assert!(Proxy::new("socks5://myproxyserver.com").is_some()); | ||
/// ``` | ||
pub fn new(url: &str) -> Option<Self> { | ||
reqwest::Proxy::all(url).ok().map(|proxy| Self { proxy }) | ||
} | ||
|
||
/// Set the `Proxy-Authorization` header using Basic auth. | ||
pub fn basic_auth(self, username: &str, password: &str) -> Self { | ||
Self { | ||
proxy: self.proxy.basic_auth(username, password), | ||
} | ||
} | ||
|
||
/// Set the `Proxy-Authorization` header to a specified value. | ||
pub fn custom_http_auth(self, header_value: HeaderValue) -> Self { | ||
Self { | ||
proxy: self.proxy.custom_http_auth(header_value), | ||
} | ||
} | ||
} | ||
|
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.
This isn't really needed. In the GraphClientConfiguration method just use the reqwest proxy as the type.
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.
Removed.
src/lib.rs
Outdated
@@ -234,7 +234,7 @@ pub static GRAPH_URL_BETA: &str = "https://graph.microsoft.com/beta"; | |||
|
|||
pub use crate::client::{Graph, GraphClient}; | |||
pub use graph_error::{GraphFailure, GraphResult}; | |||
pub use graph_http::api_impl::{GraphClientConfiguration, ODataQuery}; | |||
pub use graph_http::api_impl::{GraphClientConfiguration, ODataQuery, Proxy}; |
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.
This should be under the http mod. You can add it to some of the other reqwest reexports here:
Line 258 in 7aa756a
pub use reqwest::tls::Version; |
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 point out, now I expose reqwest::{Proxy, NoProxy}
here.
The fact that you just found this crate and were able to find where to add the proxy support and the features for socks means your doing good haha.
Yeah that one im not sure what the use case would be. But regardless I don't think... its an issue? I could see this being a use case if someone wants to proxy specific requests to one proxy while others may go to a different proxy. So they setup an exclusion list of proxy servers for some requests. I've havn't used proxies much so thats just a guess on my end. Regardless I think its fine that they can do that.
Yeah I think this one is solved by allowing the user to pass the reqwest::Proxy object instead as I mentioned in the pr review. That way the user has to deal with any issues regarding the proxy before adding to the configuration.
Thanks! I appreciate it. |
e0e06c3
to
be1288b
Compare
Thanks for suggestions. I force push a new commit to fix all issues you list here. Here is new examples: use graph_rs_sdk::{
identity::ConfidentialClientApplication, GraphClient, GraphClientConfiguration, http::Proxy,
};
fn main() {
const TANENT_ID: &str = "xxx";
const CLIENT_ID: &str = "yyy";
const CLIENT_SECRET: &str = "zzz";
let confidential_client_application = ConfidentialClientApplication::builder(CLIENT_ID)
.with_client_secret(CLIENT_SECRET)
.with_tenant(TANENT_ID)
.build();
let proxy = Proxy::all("http://myproxy.com:3128").unwrap(); // <- here
let graph_client: GraphClient = GraphClientConfiguration::new()
.client_application(confidential_client_application)
.proxy(proxy) // <- here
.into();
// do something with graph_client ...
} This new commit also change feature flag |
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.
@visig9 Looks good. Thanks for the PR!
By the way you don't need to force push changes to your PR branch. You can just make new commits and push them up. At least not when making changes to this repository. I know of other repositories on GitHub who do request that.
@visig9 Released in crate version 2.0.1 https://crates.io/crates/graph-rs-sdk/2.0.1 |
Hello, I just found this crate this morning and consider use it for my project recently. But after quick skim it seem like no proxy support (which is necessary part for me). So I try to add it.
I'm not familiar current codebase so some decision may be little weird. Here is something I'm not so sure:
Proxy
struct as thin wrapper ofreqwest::Proxy
, because...request::Proxy
methods may not suit for this case (e.g.,request::Proxy::no_proxy()
)Proxy::new()
return anOption
but notResult
, because ...Option
for now but this may not good enough.How your feel? Please let me know. Thanks.
BTW, thanks for your cool project!