https_proxy 0.3.0

Stealth HTTPS forward proxy with automatic Let's Encrypt TLS and nginx camouflage
Documentation
mod common;

use common::test_server::TestServer;
use https_proxy::config::UserConfig;

fn test_users() -> Vec<UserConfig> {
    vec![UserConfig {
        username: "testuser".to_string(),
        password: "testpass".to_string(),
    }]
}

#[tokio::test]
async fn test_missing_auth_gets_404() {
    let server = TestServer::start(test_users()).await;
    let client = server.reqwest_client();

    // Send a CONNECT-style request without auth — we send it as a regular request
    // with the proxy-authorization header missing. Since reqwest can't easily send
    // a raw CONNECT, we test via a direct request with an absolute-form URI header.
    // The proxy sees it as a proxy request (via the custom header approach won't work).
    // Instead, we test that a request to the proxy URL without proxy-auth gets 404.
    let resp = client
        .get(format!("{}/", server.proxy_url()))
        .send()
        .await
        .unwrap();

    // Non-proxy request (relative URI) → stealth 404
    assert_eq!(resp.status(), 404);
}

#[tokio::test]
async fn test_wrong_credentials_gets_404() {
    let server = TestServer::start(test_users()).await;
    let client = server.reqwest_client();

    // Even with wrong proxy-auth, a relative URI request hits stealth first
    let resp = client
        .get(format!("{}/", server.proxy_url()))
        .header(
            "proxy-authorization",
            format!(
                "Basic {}",
                base64::Engine::encode(&base64::engine::general_purpose::STANDARD, "wrong:creds")
            ),
        )
        .send()
        .await
        .unwrap();

    assert_eq!(resp.status(), 404);
}

#[tokio::test]
async fn test_malformed_auth_gets_404() {
    let server = TestServer::start(test_users()).await;
    let client = server.reqwest_client();

    let resp = client
        .get(format!("{}/", server.proxy_url()))
        .header("proxy-authorization", "Bearer some-token")
        .send()
        .await
        .unwrap();

    assert_eq!(resp.status(), 404);
}