Skip to content
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

Connecting with proxy #752

Open
finkandreas opened this issue Feb 16, 2025 · 3 comments
Open

Connecting with proxy #752

finkandreas opened this issue Feb 16, 2025 · 3 comments

Comments

@finkandreas
Copy link

Hello,
I was a bit surprised to see that by default the environment variables http_proxy/https_proxy are not respected.
I am in an environment, where connections to the internet are only possible through the proxy.
Following the example of custom-client, I was able to connect, this is what I had to change in the example:

    let mut proxy_str = match std::env::var("https_proxy") {
        Ok(val) => val,
        Err(_) => String::from(""),
    };
    proxy_str = match std::env::var("HTTPS_PROXY") {
        Ok(val) => val,
        Err(_) => proxy_str,
    };

    let octocrab = match proxy_str.as_str() {
        "" =>
            OctocrabBuilder::new_empty()
                .with_service(Client::builder(TokioExecutor::new()).build(
                    HttpsConnectorBuilder::new()
                        .with_native_roots()
                        .unwrap()
                        .https_only()
                        .enable_http1()
                        .build()))
            .with_layer(&BaseUriLayer::new(Uri::from_static(
                "https://api.github.com",
            )))
            .with_layer(&ExtraHeadersLayer::new(Arc::new(vec![
                (USER_AGENT, "octocrab".parse().unwrap()),
                (AUTHORIZATION, format!("Bearer {}", "<my_token>").parse().unwrap()),
            ])))
            .with_auth(AuthState::None)
            .build()
            .unwrap()
        ,
        _ =>
            OctocrabBuilder::new_empty()
                .with_service(Client::builder(TokioExecutor::new()).build(
                                   ProxyConnector::from_proxy(HttpConnector::new(),
                                          Proxy::new(Intercept::All,
                                                     proxy_str.parse().unwrap()))
                                          .unwrap()))
            .with_layer(&BaseUriLayer::new(Uri::from_static(
                "https://api.github.com",
            )))
            .with_layer(&ExtraHeadersLayer::new(Arc::new(vec![
                (USER_AGENT, "octocrab".parse().unwrap()),
                (AUTHORIZATION, format!("Bearer {}", "<my_token>").parse().unwrap()),
            ])))
            .with_auth(AuthState::None)
            .build()
            .unwrap()
        ,
    };

This uses the project https://github.com/metalbear-co/hyper-http-proxy.
Would you consider adding sth like this to the default-client, which would respect https_proxy envvars?
To be honest, I am a bit surprised that such a basic feature is not implemented already in hyper / hyper_util.

I did not figure out, how I could have the common setup outside of the match, because the types are different, and only collapse to a common type after the full octocrab object is built (but I also did not spend too much time, to figure out if there is some better way to deal with it).

@fmhall
Copy link

fmhall commented Mar 14, 2025

Also interested in this line of work.

@finkandreas - Do you mind sharing the the full list of imports and maybe your cargo toml? I'm having trouble recreating your above example:

use anyhow::Result;
use http::{
    header::{AUTHORIZATION, USER_AGENT},
    Uri,
};
use hyper_proxy::{Intercept, Proxy, ProxyConnector};
use hyper_rustls::HttpsConnectorBuilder;
use hyper_util::client::legacy::Client;
use hyper_util::client::legacy::connect::HttpConnector;

use hyper_util::rt::TokioExecutor;
use octocrab::{
    service::middleware::{base_uri::BaseUriLayer, extra_headers::ExtraHeadersLayer},
    AuthState, Octocrab, OctocrabBuilder,
};
use std::sync::Arc;

/// An Octocrab instance configured with the provided token and proxy settings if available
pub fn create_octocrab(proxy_str: Option<String>) -> Result<Octocrab> {

    let octocrab = match proxy_str {
        None => OctocrabBuilder::new_empty()
            .with_service(
                Client::builder(TokioExecutor::new()).build(
                    HttpsConnectorBuilder::new()
                        .with_native_roots()
                        .unwrap()
                        .https_only()
                        .enable_http1()
                        .build(),
                ),
            )
            .with_layer(&BaseUriLayer::new(Uri::from_static(
                "https://api.github.com",
            )))
            .with_layer(&ExtraHeadersLayer::new(Arc::new(vec![
                (USER_AGENT, "octocrab".parse().unwrap()),
                (
                    AUTHORIZATION,
                    format!("Bearer {}", "<my_token>").parse().unwrap(),
                ),
            ])))
            .with_auth(AuthState::None)
            .build()
            .unwrap(),
        Some(proxy_str) => OctocrabBuilder::new_empty()
            .with_service(
                Client::builder(TokioExecutor::new()).build(
                    ProxyConnector::from_proxy(
                        HttpConnector::new(),
                        Proxy::new(Intercept::All, proxy_str.parse().unwrap()),
                    )
                    .unwrap(),
                ),
            )
            .with_layer(&BaseUriLayer::new(Uri::from_static(
                "https://api.github.com",
            )))
            .with_layer(&ExtraHeadersLayer::new(Arc::new(vec![
                (USER_AGENT, "octocrab".parse().unwrap()),
                (
                    AUTHORIZATION,
                    format!("Bearer {}", "<my_token>").parse().unwrap(),
                ),
            ])))
            .with_auth(AuthState::None)
            .build()
            .unwrap(),
    };

    Ok(octocrab)
}

Has a bunch of errors related to creating the connectors.

@finkandreas
Copy link
Author

finkandreas commented Mar 14, 2025

Here's the commit of interest: finkandreas@c324cdd

Of course the lines with AUTHORIZATION need the actual github token.

@fmhall
Copy link

fmhall commented Mar 14, 2025

Super helpful, thanks! Best of luck here. I do plan on contributing to octocrab eventually, lots of QoL features I have in mind. This one would be nice for sure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants