Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add test case for broken https proxying #600

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions test/cowboy-ca.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICeDCCAeGgAwIBAgIJAOvpU0y2e5J4MA0GCSqGSIb3DQEBBQUAMFUxCzAJBgNV
BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczETMBEGA1UECgwKTmluZSBOaW5lczEPMA0G
A1UECwwGQ293Ym95MRAwDgYDVQQDDAdST09UIENBMB4XDTEzMDIyODA1MTAwMVoX
DTMzMDIyMzA1MTAwMVowVTELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMRMw
EQYDVQQKDApOaW5lIE5pbmVzMQ8wDQYDVQQLDAZDb3dib3kxEDAOBgNVBAMMB1JP
T1QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMzmY7Us06yjyUbpqwPx
Iv+xh/g3V7we07ClC9GEYnvr3OQvdA1jFEHccMBUUjRoQ8DPd6uSyK5UkixABs08
Tt5B3VsnGKr0DIN+IO4SN2PkmBqIU/BN3KdcwN65YNr3iM0KsKWeFtAZdYx4CakX
7REbO0wjK20AH3xSBn3uFGiBAgMBAAGjUDBOMB0GA1UdDgQWBBRKfZ8KF2jlLBDm
NL6IuEuGY0pdbzAfBgNVHSMEGDAWgBRKfZ8KF2jlLBDmNL6IuEuGY0pdbzAMBgNV
HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAG1I0kBxXiLkM1b7rl2zPLizREYg
1m+ajb6rWzPOBg6TXjv58Be+H4tqoHIL/M/crixew5emftBkuAGjiKMhbIokjvan
aPTCV8U6HHvNvz9c68HpESWbd+56cHqfsS5XCKp1OpW5tbL2UQYpFKMP4qmbv3Ea
pBfPPmSFMBb1i2AI
-----END CERTIFICATE-----
59 changes: 59 additions & 0 deletions test/hackney_https_pool_tests.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
-module(hackney_https_pool_tests).
-include_lib("eunit/include/eunit.hrl").
-include("hackney_lib.hrl").

%% This seems necessary to list the tests including the generator
dummy_test() ->
?assertEqual(ok, ok).

multipart_test_() ->
{setup, fun start/0, fun stop/1,
[{timeout, 120, requests_to_different_servers_go_to_different_servers()}]}.

start() ->
error_logger:tty(false),
{ok, _} = application:ensure_all_started(cowboy),
{ok, _} = application:ensure_all_started(hackney),
ProxyPid = simple_proxy:start_proxy_server(),
register(proxy_server, ProxyPid),

hackney_pool:start_pool(pool_test, [{pool_size, 1}]),
Host = '_',
Resource = {"/pool", https_pool_resource1, []},
Dispatch = cowboy_router:compile([{Host, [Resource]}]),
Resource2 = {"/pool", https_pool_resource2, []},
Dispatch2 = cowboy_router:compile([{Host, [Resource2]}]),

CaCertFile = "test/cowboy-ca.crt",
CertFile = "test/server.crt",
KeyFile = "test/server.key",

cowboy:start_https(test_server, 10, [{port, 8443}, {cacertfile, CaCertFile}, {certfile, CertFile}, {keyfile, KeyFile}], [{env, [{dispatch, Dispatch}]}]),
cowboy:start_https(test_server2, 10, [{port, 8444}, {cacertfile, CaCertFile}, {certfile, CertFile}, {keyfile, KeyFile}], [{env, [{dispatch, Dispatch2}]}]).

stop({ok, _Pid}) ->
cowboy:stop_listener(test_server),
application:stop(cowboy),
hackney_pool:stop_pool(pool_test),
application:stop(hackney),
error_logger:tty(true),
exit(whereis(proxy_server), kill),
ok.

requests_to_different_servers_go_to_different_servers() ->
fun() ->
URL = <<"https://localhost:8443/pool">>,
OtherURL = <<"https://127.0.0.1:8444/pool">>,

Headers = [],
SSLOptions = [{verify, verify_none}],
Opts = [{pool, pool_test}, {connect_timeout, 100}, {ssl_options, SSLOptions}, {proxy, "http://localhost:5555"}],
{ok, _, _, Ref1} = hackney:request(get, URL, Headers, <<>>, Opts),
{ok, Body1} = hackney:body(Ref1),
?assertEqual(<<"pool_resource1">>, Body1),

{ok, _, _, Ref2} = hackney:request(get, OtherURL, Headers, <<>>, Opts),
{ok, Body2} = hackney:body(Ref2),
?assertEqual(<<"pool_resource2">>, Body2)
end.

15 changes: 15 additions & 0 deletions test/https_pool_resource1.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-module(https_pool_resource1).

-export([init/3]).
-export([handle/2]).
-export([terminate/3]).

init(_, Req, _Opts) ->
{ok, Req, undefined}.

handle(Req, State) ->
{ok, Req2} = cowboy_req:reply(200, [], <<"pool_resource1">>, Req),
{ok, Req2, State}.

terminate(_Reason, _Req, _State) ->
ok.
15 changes: 15 additions & 0 deletions test/https_pool_resource2.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-module(https_pool_resource2).

-export([init/3]).
-export([handle/2]).
-export([terminate/3]).

init(_, Req, _Opts) ->
{ok, Req, undefined}.

handle(Req, State) ->
{ok, Req2} = cowboy_req:reply(200, [], <<"pool_resource2">>, Req),
{ok, Req2, State}.

terminate(_Reason, _Req, _State) ->
ok.
17 changes: 17 additions & 0 deletions test/server.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICpTCCAg6gAwIBAgIJAOvpU0y2e5J5MA0GCSqGSIb3DQEBBQUAMFUxCzAJBgNV
BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczETMBEGA1UECgwKTmluZSBOaW5lczEPMA0G
A1UECwwGQ293Ym95MRAwDgYDVQQDDAdST09UIENBMB4XDTEzMDIyODA1MjMzNFoX
DTMzMDIyMzA1MjMzNFowVzELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMRMw
EQYDVQQKDApOaW5lIE5pbmVzMQ8wDQYDVQQLDAZDb3dib3kxEjAQBgNVBAMMCWxv
Y2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzbW1GjECzHUc/WST
qLiAGqjCNccR5saVS+yoz2SPRhpoyf0/qBrX5BY0tzmgozoTiRfE4wCiVD99Cc+D
rp/FM49r4EpZdocIovprmOmv/gwkoj95zaA6PKNn1OdmDp2hwJsX2Zm3kpbGUZTx
jDkkccmgUb4EjL7qNHq7saQtivUCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgB
hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE
FB6jTEIWI8T1ckORA4GezbyYxtbvMB8GA1UdIwQYMBaAFEp9nwoXaOUsEOY0voi4
S4ZjSl1vMA0GCSqGSIb3DQEBBQUAA4GBACMboVQjrx8u/fk3gl/sR0tbA0Wf/NcS
2Dzsy2czndgVUAG4Sqb+hfgn0dqAyUKghRrj3JDcYxYksGPIklDfPzZb7yJ39l16
6x5ZiIzhp8CAVdPvRxRznw5rZwaXesryXu1jVSZxTr3MYZdkG6KaAM0t90+YlGLZ
UG8fAicx0Bf+
-----END CERTIFICATE-----
15 changes: 15 additions & 0 deletions test/server.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDNtbUaMQLMdRz9ZJOouIAaqMI1xxHmxpVL7KjPZI9GGmjJ/T+o
GtfkFjS3OaCjOhOJF8TjAKJUP30Jz4Oun8Uzj2vgSll2hwii+muY6a/+DCSiP3nN
oDo8o2fU52YOnaHAmxfZmbeSlsZRlPGMOSRxyaBRvgSMvuo0eruxpC2K9QIDAQAB
AoGAaD85c/h6bpq7Aj7CBbLaWKhFI3OqwsTITB22vsM7SE+B4zsP02UnG1OVi3UM
zytTUxpUkKV1njQ+bYZYOVqGWF4Up8tTqUglHn0FTPok1AIemELWtz3sXvdSHC1T
lqvFBAZ9kibn13qGyVOiyCFaMwfOM/05RvV7p3jfUMTWnNECQQDs7yCJZ8Ol8MyH
TGZzvkjoN2zg1KwmTbSD1hkP6QAJtPdRuqFbjlEru0/PefgOXsWLRIa3/3v0qw2G
xGkV6AXTAkEA3kNbFisqUydjPnZIYv/P6SvPdUimHJEjXbAbfNfzS9dzszrOVJd2
XqGH7z5yzjoH3IyaIMW8GnubVzGDSjrHFwJAKSU5vELlygpwKkrNO+pelN0TLlQg
dSJnZ8GlZorq88SWcn37iX/EftivenNO7YftvEqxLoDSkOGnnrC7Iw/A+wJBAIEe
L/QY72WPJCBNJpAce/PA96vyoE1II3txqwZDjZspdpVQPDz4IFOpEwbxCFC1dYuy
Qnd3Z2cbF4r3wIWGz9ECQQCJGNhUNtY+Om1ELdqPcquxE2VRV/pucnvJSTKwyo2C
Rvm6H7kFDwPDuN23YnTOlTiho0zzCkclcIukhIVJ+dKz
-----END RSA PRIVATE KEY-----
75 changes: 75 additions & 0 deletions test/simple_proxy.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
-module(simple_proxy).

-export([handle_client/0]).
-export([proxy_server_init/0]).
-export([start_proxy_server/0]).

start_proxy_server() ->
{ok, LSock} = gen_tcp:listen(5555, [binary, {packet, http_bin}, {active, false}]),
Pid = spawn(?MODULE, proxy_server_init, []),
gen_tcp:controlling_process(LSock, Pid),
Pid ! {socket, LSock},
Pid.

proxy_server_init() ->
LSock = receive
{socket, Sock} -> Sock
end,

io:format(user, "PROXY SERVER RUNNING~n", []),
proxy_server_loop(LSock).

proxy_server_loop(LSock) ->
case gen_tcp:accept(LSock) of
{ok, Sock} ->
Pid = spawn(?MODULE, handle_client, []),
ok = gen_tcp:controlling_process(Sock, Pid),
Pid ! {socket, Sock},
proxy_server_loop(LSock);
Error ->
io:format(user, "UNEXPECTED ERROR~p~n", [Error])
end.


skip_headers(Sock) ->

{ok, Header} = gen_tcp:recv(Sock, 0, 5000),
case Header of
{http_header,_,_,_,_} -> skip_headers(Sock);
http_eoh ->
ok
end.

handle_client() ->
Sock = receive
{socket, Socket} -> Socket
end,

{ok, {http_request,<<"CONNECT">>, {scheme, Host, Port}, {1,1}}} = gen_tcp:recv(Sock, 0, 5000),
skip_headers(Sock),
IntPort = binary_to_integer(Port),
ok = inet:setopts(Sock, [{active, true}, {packet, raw}, binary]),
{ok, ForeignSock} = gen_tcp:connect(binary_to_list(Host), IntPort, [binary, {packet, raw}, {active, true}]),
io:format(user, "CONNECT TO FOREIGN ADDRESS ~p ~p ~n", [Host, IntPort]),
ok = gen_tcp:send(Sock, <<"HTTP/1.1 200 OK\r\n\r\n">>),
proxy_data_loop(Sock, ForeignSock).

proxy_data_loop(Sock, ForeignSock) ->
receive
{tcp, Sock, Data} ->
gen_tcp:send(ForeignSock, Data),
proxy_data_loop(Sock, ForeignSock);
{tcp, ForeignSock, Data} ->
gen_tcp:send(Sock, Data),
proxy_data_loop(Sock, ForeignSock);
{tcp_closed, Sock} ->
io:format(user, "CLIENT SOCK CLOSED~n", []),
gen_tcp:close(Sock);
{tcp_closed, ForeignSock} ->
io:format(user, "FOREIGN SOCK CLOSED~n", []),
gen_tcp:close(ForeignSock)
after 30000 ->
io:format(user, "TIMEOUT~n", []),
gen_tcp:close(Sock),
gen_tcp:close(ForeignSock)
end.