From: Stefan Eissing Date: Wed, 15 Feb 2023 11:39:46 +0000 (+0100) Subject: tests-httpd: add proxy tests X-Git-Tag: curl-7_88_1~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=216e4b1fb6d549f007014fecdd122ac777000833;p=thirdparty%2Fcurl.git tests-httpd: add proxy tests for direct and tunneling checks on http: and https: Closes #10519 --- diff --git a/tests/tests-httpd/config.ini.in b/tests/tests-httpd/config.ini.in index 3b1d28de84..68ab0d360f 100644 --- a/tests/tests-httpd/config.ini.in +++ b/tests/tests-httpd/config.ini.in @@ -34,11 +34,13 @@ apachectl = @APACHECTL@ http_port = 5001 https_port = 5002 h3_port = 5002 +proxy_port = 5004 +proxys_port = 5005 [nghttpx] nghttpx = @HTTPD_NGHTTPX@ [caddy] caddy = @CADDY@ -http_port = 5003 -https_port = 5004 +http_port = 5010 +https_port = 5011 diff --git a/tests/tests-httpd/test_10_proxy.py b/tests/tests-httpd/test_10_proxy.py index 1c444eec0f..cde69e5efa 100644 --- a/tests/tests-httpd/test_10_proxy.py +++ b/tests/tests-httpd/test_10_proxy.py @@ -45,26 +45,89 @@ class TestProxy: os.makedirs(push_dir) # download via http: proxy (no tunnel) - def test_10_01_http_get(self, env: Env, httpd, repeat): + def test_10_01_proxy_http(self, env: Env, httpd, repeat): curl = CurlClient(env=env) url = f'http://localhost:{env.http_port}/data.json' r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, extra_args=[ - '--proxy', f'http://{env.proxy_domain}:{env.http_port}/', - '--resolve', f'{env.proxy_domain}:{env.http_port}:127.0.0.1', + '--proxy', f'http://{env.proxy_domain}:{env.proxy_port}/', + '--resolve', f'{env.proxy_domain}:{env.proxy_port}:127.0.0.1', ]) assert r.exit_code == 0 r.check_stats(count=1, exp_status=200) # download via https: proxy (no tunnel) - def test_10_02_http_get(self, env: Env, httpd, repeat): + def test_10_02_proxy_https(self, env: Env, httpd, repeat): curl = CurlClient(env=env) url = f'http://localhost:{env.http_port}/data.json' r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, extra_args=[ - '--proxy', f'https://{env.proxy_domain}:{env.https_port}/', - '--resolve', f'{env.proxy_domain}:{env.https_port}:127.0.0.1', + '--proxy', f'https://{env.proxy_domain}:{env.proxys_port}/', + '--resolve', f'{env.proxy_domain}:{env.proxys_port}:127.0.0.1', '--proxy-cacert', env.ca.cert_file, ]) assert r.exit_code == 0 r.check_stats(count=1, exp_status=200) + + # download http: via http: proxytunnel + def test_10_03_proxytunnel_http(self, env: Env, httpd, repeat): + curl = CurlClient(env=env) + url = f'http://localhost:{env.http_port}/data.json' + r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, + extra_args=[ + '--proxytunnel', + '--proxy', f'http://{env.proxy_domain}:{env.proxy_port}/', + '--resolve', f'{env.proxy_domain}:{env.proxy_port}:127.0.0.1', + ]) + assert r.exit_code == 0 + r.check_stats(count=1, exp_status=200) + + # download http: via https: proxytunnel + def test_10_04_proxy_https(self, env: Env, httpd, repeat): + curl = CurlClient(env=env) + url = f'http://localhost:{env.http_port}/data.json' + r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, + extra_args=[ + '--proxytunnel', + '--proxy', f'https://{env.proxy_domain}:{env.proxys_port}/', + '--resolve', f'{env.proxy_domain}:{env.proxys_port}:127.0.0.1', + '--proxy-cacert', env.ca.cert_file, + ]) + assert r.exit_code == 0 + r.check_stats(count=1, exp_status=200) + + # download https: with proto via http: proxytunnel + @pytest.mark.parametrize("proto", ['http/1.1', 'h2']) + def test_10_05_proxytunnel_http(self, env: Env, httpd, proto, repeat): + curl = CurlClient(env=env) + url = f'https://localhost:{env.https_port}/data.json' + r = curl.http_download(urls=[url], alpn_proto=proto, with_stats=True, + with_headers=True, + extra_args=[ + '--proxytunnel', + '--proxy', f'http://{env.proxy_domain}:{env.proxy_port}/', + '--resolve', f'{env.proxy_domain}:{env.proxy_port}:127.0.0.1', + ]) + assert r.exit_code == 0 + r.check_stats(count=1, exp_status=200) + exp_proto = 'HTTP/2' if proto == 'h2' else 'HTTP/1.1' + assert r.response['protocol'] == exp_proto + + # download https: with proto via https: proxytunnel + @pytest.mark.parametrize("proto", ['http/1.1', 'h2']) + def test_10_06_proxy_https(self, env: Env, httpd, proto, repeat): + curl = CurlClient(env=env) + url = f'https://localhost:{env.https_port}/data.json' + r = curl.http_download(urls=[url], alpn_proto=proto, with_stats=True, + with_headers=True, + extra_args=[ + '--proxytunnel', + '--proxy', f'https://{env.proxy_domain}:{env.proxys_port}/', + '--resolve', f'{env.proxy_domain}:{env.proxys_port}:127.0.0.1', + '--proxy-cacert', env.ca.cert_file, + ]) + assert r.exit_code == 0 + r.check_stats(count=1, exp_status=200) + exp_proto = 'HTTP/2' if proto == 'h2' else 'HTTP/1.1' + assert r.response['protocol'] == exp_proto + diff --git a/tests/tests-httpd/testenv/env.py b/tests/tests-httpd/testenv/env.py index 07eb999e9e..f468043dd8 100644 --- a/tests/tests-httpd/testenv/env.py +++ b/tests/tests-httpd/testenv/env.py @@ -97,6 +97,8 @@ class EnvConfig: self.http_port = self.config['test']['http_port'] self.https_port = self.config['test']['https_port'] + self.proxy_port = self.config['test']['proxy_port'] + self.proxys_port = self.config['test']['proxys_port'] self.h3_port = self.config['test']['h3_port'] self.httpd = self.config['httpd']['httpd'] self.apachectl = self.config['httpd']['apachectl'] @@ -115,7 +117,7 @@ class EnvConfig: self.domain2 = f"two.{self.tld}" self.proxy_domain = f"proxy.{self.tld}" self.cert_specs = [ - CertificateSpec(domains=[self.domain1], key_type='rsa2048'), + CertificateSpec(domains=[self.domain1, 'localhost'], key_type='rsa2048'), CertificateSpec(domains=[self.domain2], key_type='rsa2048'), CertificateSpec(domains=[self.proxy_domain], key_type='rsa2048'), CertificateSpec(name="clientsX", sub_specs=[ @@ -300,7 +302,6 @@ class Env: def proxy_domain(self) -> str: return self.CONFIG.proxy_domain - @property def http_port(self) -> str: return self.CONFIG.http_port @@ -313,6 +314,14 @@ class Env: def h3_port(self) -> str: return self.CONFIG.h3_port + @property + def proxy_port(self) -> str: + return self.CONFIG.proxy_port + + @property + def proxys_port(self) -> str: + return self.CONFIG.proxys_port + @property def caddy(self) -> str: return self.CONFIG.caddy diff --git a/tests/tests-httpd/testenv/httpd.py b/tests/tests-httpd/testenv/httpd.py index 21e10e65cc..4e027dfb54 100644 --- a/tests/tests-httpd/testenv/httpd.py +++ b/tests/tests-httpd/testenv/httpd.py @@ -226,6 +226,8 @@ class Httpd: f'H2MaxWorkers 128', f'Listen {self.env.http_port}', f'Listen {self.env.https_port}', + f'Listen {self.env.proxy_port}', + f'Listen {self.env.proxys_port}', f'TypesConfig "{self._conf_dir}/mime.types', ] conf.extend([ # plain http host for domain1 @@ -239,33 +241,6 @@ class Httpd: f'', f'', ]) - conf.extend([ # http forward proxy - f'', - f' ServerName {proxy_domain}', - f' Protocols http/1.1', - f' ProxyRequests On', - f' ProxyVia On', - f' AllowCONNECT {self.env.http_port} {self.env.https_port}', - f' ', - f' Require ip 127.0.0.1', - f' ', - f'', - ]) - conf.extend([ # https forward proxy - f'', - f' ServerName {proxy_domain}', - f' Protocols http/1.1', - f' SSLEngine on', - f' SSLCertificateFile {proxy_creds.cert_file}', - f' SSLCertificateKeyFile {proxy_creds.pkey_file}', - f' ProxyRequests On', - f' ProxyVia On', - f' AllowCONNECT {self.env.http_port} {self.env.https_port}', - f' ', - f' Require ip 127.0.0.1', - f' ', - f'', - ]) conf.extend([ # https host for domain1, h1 + h2 f'', f' ServerName {domain1}', @@ -298,6 +273,33 @@ class Httpd: f'', f'', ]) + conf.extend([ # http forward proxy + f'', + f' ServerName {proxy_domain}', + f' Protocols h2c, http/1.1', + f' ProxyRequests On', + f' ProxyVia On', + f' AllowCONNECT {self.env.http_port} {self.env.https_port}', + f' ', + f' Require ip 127.0.0.1', + f' ', + f'', + ]) + conf.extend([ # https forward proxy + f'', + f' ServerName {proxy_domain}', + f' Protocols h2, http/1.1', + f' SSLEngine on', + f' SSLCertificateFile {proxy_creds.cert_file}', + f' SSLCertificateKeyFile {proxy_creds.pkey_file}', + f' ProxyRequests On', + f' ProxyVia On', + f' AllowCONNECT {self.env.http_port} {self.env.https_port}', + f' ', + f' Require ip 127.0.0.1', + f' ', + f'', + ]) fd.write("\n".join(conf)) with open(os.path.join(self._conf_dir, 'mime.types'), 'w') as fd: fd.write("\n".join([