Skip to content

Add support for HTTPS proxies (available to trio/asyncio) - #745

Merged
karpetrosyan merged 13 commits into
encode:masterfrom
karpetrosyan:add-support-for-https-proxy
Sep 1, 2023
Merged

Add support for HTTPS proxies (available to trio/asyncio)#745
karpetrosyan merged 13 commits into
encode:masterfrom
karpetrosyan:add-support-for-https-proxy

Conversation

@karpetrosyan

@karpetrosyankarpetrosyan commented Jul 4, 2023

Copy link
Copy Markdown
Contributor

Refs #722

Related #732 (Required for sync support)

TODO

  • Add proxy_ssl_context argument to AsyncForwardHTTPConnection, AsyncTunnelHTTPConnection and AsyncHTTPProxy classes
  • Add changelog

@karpetrosyankarpetrosyan changed the title Add support for HTTPS ProxyAdd support for HTTPS ProxiesJul 4, 2023
@karpetrosyankarpetrosyan added the enhancement New feature or request label Jul 7, 2023
@lovelydinosaur

Copy link
Copy Markdown
Contributor

Looks like we could do with a docs update here...

https://www.encode.io/httpcore/proxies/

We probably want to split "Proxy SSL and HTTP Versions" into "Proxy SSL" which documents the proxy_ssl_context argument, and HTTP Versions which notes the HTTP/1.1 constraint.

@lovelydinosaur

Copy link
Copy Markdown
Contributor

Okay, so attempting to test this...

I'm using trio in this example, so as not to be blocked by #732.

Installation...

$ pip install httpcore trio trustme proxy.py

Use trustme to generate certs...

$ python-mtrustmeGeneratedacertificatefor'localhost', '127.0.0.1', '::1'Configureyourservertousethefollowingfiles:
cert=/Users/tomchristie/GitHub/encode/httpcore/server.pemkey=/Users/tomchristie/GitHub/encode/httpcore/server.keyConfigureyourclienttousethefollowingfiles:
cert=/Users/tomchristie/GitHub/encode/httpcore/client.pem

Running the proxy...

$ proxy --cert-file server.pem --key-file server.key 

Make the requests...

importsslimporttrioimporthttpcorectx=ssl.create_default_context()
ctx.load_verify_locations('client.pem')
asyncdefmain():
asyncwithhttpcore.AsyncHTTPProxy(proxy_url="http://127.0.0.1:8899/", proxy_ssl_context=ctx) ashttp:
response=awaithttp.request("GET", "https://www.example.com/")
print(response)
response=awaithttp.request("GET", "http://www.example.com/")
print(response)
trio.run(main)

Fails with...

[...]
ssl.SSLError: [SSL: HTTPS_PROXY_REQUEST] httpsproxyrequest (_ssl.c:992)

What am I getting wrong here?

@lovelydinosaur

lovelydinosaur commented Aug 30, 2023

Copy link
Copy Markdown
Contributor

Also, occurs to me that something we could do here would be decouple this from #732.

Indicate in the CHANGELOG/docs that HTTPS proxies are only supported with trio and asyncio, and ensure that we raise a runtime error if TLS-in-TLS is attempted with the sync backend.

@T-256

Copy link
Copy Markdown
Contributor

Fails with...

[...]
ssl.SSLError: [SSL: HTTPS_PROXY_REQUEST] httpsproxyrequest (_ssl.c:992)

I think problem is here:

ifself._origin.scheme==b"https":

Where you set proxy_url="http://127.0.0.1:8899/", so self._origin.scheme is http, and it won't do tls handshake.

@T-256

Copy link
Copy Markdown
Contributor

I also had this problem on #734 and ended up by scheme checking.
IMO we should do ssl context checking instead of scheme checking. (e.g. here too)

@karpetrosyan

karpetrosyan commented Aug 31, 2023

Copy link
Copy Markdown
ContributorAuthor

What am I getting wrong here?

Just change the proxy url scheme to https.

@karpetrosyan

Copy link
Copy Markdown
ContributorAuthor

Also, occurs to me that something we could do here would be decouple this from #732.

Indicate in the CHANGELOG/docs that HTTPS proxies are only supported with trio and asyncio, and ensure that we raise a runtime error if TLS-in-TLS is attempted with the sync backend.

We should probably merge #732 first, then go over this one.

@lovelydinosaur

Copy link
Copy Markdown
Contributor

Wonderful thanks, tested now and all working as expected.

Okay so, should we add the following error cases here?...

  • If proxy_url is set to https and proxy_ssl_context is unset, then raise an exception.
  • If proxy_url is set to http and proxy_ssl_context is set, then raise an exception.

I'd suggest that this PR is neat and uncontentious, so let's work to getting it merged, as "Add support for HTTPS proxies (available to trio/asyncio)". Then follow up with the more awkward sync support.

Remaining here is...

  • Documentation.
  • Raise an error in the sync backend if TLS-in-TLS is attempted.

Comment threaddocs/proxies.md
```

## Proxy SSL and HTTP Versions
## Proxy SSL

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These docs are really nice, thanks! 💚

@lovelydinosaurlovelydinosaur mentioned this pull request Sep 1, 2023
@karpetrosyan

Copy link
Copy Markdown
ContributorAuthor

If proxy_url is set to https and proxy_ssl_context is unset, then raise an exception.

Because most users do not interact with SSL contexts, we can allow this behavior to keep things as simple as possible.

When using the public HTTPS proxy, for example, the user must create the default SSL context and pass it to the HTTPProxy class without any modifications or configurations.

If proxy_url is set to http and proxy_ssl_context is set, then raise an exception.

Agree

@karpetrosyankarpetrosyan changed the title Add support for HTTPS ProxiesAdd support for HTTPS proxies (available to trio/asyncio)Sep 1, 2023
Comment threaddocs/proxies.md Outdated
Comment threadCHANGELOG.md Outdated
Comment threadCHANGELOG.md Outdated
@lovelydinosaur

Copy link
Copy Markdown
Contributor

Great - No objections to this.

Welcome to merge once you're also happy with it @karosis88.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or request

Development

Successfully merging this pull request may close these issues.

3 participants

@karpetrosyan@lovelydinosaur@T-256