tafia/hyper-proxy

Unsecured proxy doesn't work with HTTPS destinations

kylegentle opened this issue · 2 comments

With an unsecured proxy, hyper_proxy appears to work fine for HTTP destinations (e.g. http://github.com), but fails for HTTPS sites (e.g. https://github.com).

It fails with either connection closed before message completed or invalid HTTP version parsed, depending on the site.

Am I doing something wrong in configuring the client/connector, or is this a bug?

Minimal repro

Proxy setup

squid proxy in my LAN at 192.168.1.20 with the following in squid.conf:

http_port 3128
http_access allow all
cache deny all  # don't cache anything

Code

Example repo
Direct file link

use hyper::client::HttpConnector;
use hyper::Body;
use hyper::Client;
use hyper_proxy::Intercept;
use hyper_proxy::Proxy;
use hyper_proxy::ProxyConnector;

#[tokio::main]
async fn main() {
    let proxy = {
        let proxy_uri = "http://192.168.1.20:3128".parse().unwrap();
        let proxy = Proxy::new(Intercept::All, proxy_uri);
        let connector = hyper::client::HttpConnector::new();
        let proxy_connector = ProxyConnector::from_proxy_unsecured(connector, proxy);
        proxy_connector
    };

    let client: Client<ProxyConnector<HttpConnector<_>>, Body> =
        hyper::Client::builder().build(proxy);

    let req = client.get("http://github.com".parse().unwrap());
    let res = req.await;

    println!("HTTP Uri");
    println!("========");
    match res {
        Ok(body) => println!("{:?}", body),
        Err(x) => eprintln!("{:}", x.message()),
    }

    let req = client.get("https://github.com".parse().unwrap());
    let res = req.await;

    println!("\n\nHTTPS Uri (github)");
    println!("==================");
    match res {
        Ok(body) => println!("{:?}", body),
        Err(x) => eprintln!("{:}", x.message()),
    }

    let req = client.get("https://instagram.com".parse().unwrap());
    let res = req.await;

    println!("\n\nHTTPS Uri (instagram)");
    println!("=====================");
    match res {
        Ok(body) => println!("{:?}", body),
        Err(x) => eprintln!("{:}", x.message()),
    }
}

Run output

HTTP Uri
========
Response { status: 301, version: HTTP/1.1, headers: {"date": "Sat, 09 Jul 2022 01:31:18 GMT", "content-length": "0", "location": "https://github.com/", "x-cache": "MISS from 6bd9b44c254b", "x-cache-lookup": "MISS from 6bd9b44c254b:3128", "via": "1.1 6bd9b44c254b (squid/3.5.12)", "connection": "keep-alive"}, body: Body(Empty) }


HTTPS Uri (github)
==================
connection closed before message completed


HTTPS Uri (instagram)
=====================
invalid HTTP version parsed

@tafia, I know you've mentioned in other issues that you have low bandwidth for a while.

Being able to access HTTPS sites is critical to my use case, so I'm strongly motivated to help towards a fix.

If you don't have the capacity to work on this near term, perhaps you can share some guidance or thoughts on how this might be failing? If you can point me in the right direction and help with code review/merging, I'm happy to attempt a PR 😊

...I've discovered after some experimenting that this is expected behavior.

I thought that "unsecured" meant "not requiring any authentication", but in this library it seems to mean "HTTP only".

I was able to resolve my issue by switching my from_proxy_unsecured call to from_proxy.