Add support for HTTPS proxies for HTTPS connections#492
Open
ericmj wants to merge 1 commit into
Open
Conversation
Establish CONNECT tunnels through TLS proxies by nesting the TLS session to the host inside the TLS session to the proxy. The established :ssl socket acts as the transport for the nested connection through the :cb_info option, with Mint.Core.Transport.SSL.Tunnel as the callback module. The proxy connection is now also closed when the tunnel upgrade fails, and transport errors returned from upgrades are no longer wrapped twice.
Coverage Report for CI Build 0Coverage increased (+0.08%) to 87.621%Details
Uncovered Changes
Coverage Regressions1 previously-covered line in 1 file lost coverage.
Coverage Stats
💛 - Coveralls |
ericmj
marked this pull request as ready for review
July 18, 2026 22:09
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds TLS-in-TLS tunneling:
Mint.HTTP.connect(:https, host, port, proxy: {:https, proxy_host, proxy_port, opts})now establishes a CONNECT tunnel over a TLS connection to the proxy, with the TLS session to the host nested inside it. Previously this combination raised"nested SSL sessions are not supported".The nesting uses OTP's documented
cb_infotransport option: the established:sslsocket to the proxy acts as the transport for the inner:ssl.connect/3, with the newMint.Core.Transport.SSL.Tunnelmodule (delegating to:ssl) as the gen_tcp-shaped callback. No intermediary process is needed, so this fits Mint's process-less design. The inner handshake goes through the samessl_opts/2pipeline as direct connections, soverify_peer, CA trust, SNI, hostname verification, and ALPN (HTTP/2 negotiation) all apply through the tunnel.cb_infois forced after merging user transport options so it cannot be overridden. Works on all supported OTP versions (the upgrade form of:ssl.connect/3accepts a non-port socket withcb_infosince at least OTP 24; verified empirically on 27/28 and by source inspection on 24.3).Two adjacent fixes are included: the proxy connection is now closed when the tunnel upgrade fails (previously the socket leaked, for
:httpproxies too), andMint.Negotiate.connect_upgrade/6no longer double-wraps%TransportError{}returned by transport upgrades.Tests come in two layers. An offline suite (
test/mint/https_proxy_test.exs, runs on the whole CI matrix including OTP 24.3) drives the public API through a local TLS-terminating CONNECT proxy: HTTP/1 and HTTP/2 (both ALPN-negotiated and forced), certificate verification through the tunnel using runtime-generated chains via:public_key.pkix_test_data/1(including a rejection test), inner-handshake failure surfacing clean error tuples plus tunnel teardown, and a guard that user-suppliedcb_infocannot displace the tunnel transport. A docker-based integration layer adds a real TLS-terminating Squid proxy (test/docker/squid-https, bound to loopback since it is an open proxy) and exercises HTTP/1 and HTTP/2 through Squid to the Caddy-fronted httpbin with real certificate verification on the inner hop; these run under the existing--include proxyCI step with no workflow changes.The permanently-skipped nested-HTTPS test against tinyproxy (which cannot terminate TLS) and the test asserting the old raise are removed, superseded by the above.