Erlang HTTP Client support for an HTTPS Proxy

Hello,

I’m in search of an Erlang HTTP Client Library that supports an HTTPS Proxy. There are many that support an HTTP Proxy of course, but the proxy I’m attempting to connect to is expecting clients to make a TLS connection right off the bat.

This is a feature that’s supported in curl, and detailed in a blog post here..

Here’s a sample working curl request for reference. Notice that the proxy argument has ‘https’

curl --proxy https://my-https-proxy.example.com https://www.google.com/

I’ve attempted to replicate this working example in ibrowse, gun, and hackney, but I’ve not had success. They appear to all expect an HTTP Proxy. Does anyone have any recommendations?

Here is my attempt using hackney.

fun() ->
    application:ensure_all_started(hackney),

    ProxyHost = "my-https-proxy.example.com",
    ProxyPort = 443,

    Transport = hackney_ssl,
    Host = <<"friendpaste.com">>,
    Port = 443,
    Options = [{connect_host, Host},
               {connect_port, Port},
               {connect_transport, Transport}],
    Timeout = 10000,

    % Fails here, returns {error,closed}
    {ok, ConnRef} = hackney_http_connect:connect(ProxyHost, ProxyPort, Options, Timeout),

    ReqBody = << "{ \"snippet\": \"some snippet\" }" >>,
    ReqHeaders = [{<<"Content-Type">>, <<"application/json">>}],
    NextPath = <<"/">>,
    NextMethod = post,
    NextReq = {NextMethod, NextPath, ReqHeaders, ReqBody},
    {ok, StatusCode, _, ConnRef} = hackney:send_request(ConnRef, NextReq),
    StatusCode
end().

Thanks!
Jesse

3 Likes

I was able to get gun working. Providing the example here for future readers.

fun() ->
    application:ensure_all_started(gun),
    {ok, ConnPid} = gun:open("my-https-proxy.example.com", 443,
        #{trace => false, protocols => [http], transport => tls, tls_opts => [{verify, verify_none}]}),
    {ok, http} = gun:await_up(ConnPid),
    ConnectRef = gun:connect(ConnPid,
        #{host => "www.google.com",
          port => 443,
          protocols => [http],
          transport => tls,
          tls_opts => [{verify, verify_none}]
          }),
    {response, fin, 200, _} = gun:await(ConnPid, ConnectRef),
    GetRef = gun:get(ConnPid, "/", #{}, #{tunnel => ConnectRef}),
    Result = gun:await(ConnPid, GetRef),
    gun:close(Result),
    Result
end().
2 Likes