test_fallback.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import re
  2. from typing import List
  3. import backoff
  4. import pathlib
  5. import pytest
  6. import requests
  7. @pytest.fixture
  8. def docker_compose_files(compose_file) -> List[str]:
  9. data_dir = pathlib.Path(__file__).parent.joinpath("test_fallback.data")
  10. yield [
  11. data_dir.joinpath("compose.base.yml"),
  12. data_dir.joinpath(compose_file).as_posix()
  13. ]
  14. @pytest.fixture
  15. def get(docker_compose, nginxproxy, want_err_re):
  16. @backoff.on_exception(
  17. backoff.constant,
  18. requests.exceptions.SSLError,
  19. giveup=lambda e: want_err_re and want_err_re.search(str(e)),
  20. interval=.3,
  21. max_tries=30,
  22. jitter=None)
  23. def _get(url, want_code=None):
  24. if want_code is None:
  25. return nginxproxy.get_without_backoff(url, allow_redirects=False)
  26. else:
  27. return nginxproxy.get(url, allow_redirects=False, expected_status_code=want_code)
  28. yield _get
  29. INTERNAL_ERR_RE = re.compile("TLSV1_UNRECOGNIZED_NAME")
  30. @pytest.mark.parametrize("compose_file,url,want_code,want_err_re", [
  31. # Has default.crt.
  32. ("withdefault.yml", "http://https-and-http.nginx-proxy.test/", 301, None),
  33. ("withdefault.yml", "https://https-and-http.nginx-proxy.test/", 200, None),
  34. ("withdefault.yml", "http://https-only.nginx-proxy.test/", 503, None),
  35. ("withdefault.yml", "https://https-only.nginx-proxy.test/", 200, None),
  36. ("withdefault.yml", "http://http-only.nginx-proxy.test/", 200, None),
  37. ("withdefault.yml", "https://http-only.nginx-proxy.test/", 503, None),
  38. ("withdefault.yml", "http://missing-cert.nginx-proxy.test/", 301, None),
  39. ("withdefault.yml", "https://missing-cert.nginx-proxy.test/", 200, None),
  40. ("withdefault.yml", "http://missing-cert.default-untrusted.nginx-proxy.test/", 200, None),
  41. ("withdefault.yml", "https://missing-cert.default-untrusted.nginx-proxy.test/", None, INTERNAL_ERR_RE),
  42. ("withdefault.yml", "http://unknown.nginx-proxy.test/", 503, None),
  43. ("withdefault.yml", "https://unknown.nginx-proxy.test/", 503, None),
  44. # Same as withdefault.yml, except default.crt is not trusted (TRUST_DEFAULT_CERT=false).
  45. ("untrusteddefault.yml", "http://https-and-http.nginx-proxy.test/", 301, None),
  46. ("untrusteddefault.yml", "https://https-and-http.nginx-proxy.test/", 200, None),
  47. ("untrusteddefault.yml", "http://https-only.nginx-proxy.test/", 503, None),
  48. ("untrusteddefault.yml", "https://https-only.nginx-proxy.test/", 200, None),
  49. ("untrusteddefault.yml", "http://http-only.nginx-proxy.test/", 200, None),
  50. ("untrusteddefault.yml", "https://http-only.nginx-proxy.test/", 503, None),
  51. ("untrusteddefault.yml", "http://missing-cert.nginx-proxy.test/", 200, None),
  52. ("untrusteddefault.yml", "https://missing-cert.nginx-proxy.test/", None, INTERNAL_ERR_RE),
  53. ("untrusteddefault.yml", "http://unknown.nginx-proxy.test/", 503, None),
  54. ("untrusteddefault.yml", "https://unknown.nginx-proxy.test/", 503, None),
  55. # Same as withdefault.yml, except there is no default.crt.
  56. ("nodefault.yml", "http://https-and-http.nginx-proxy.test/", 301, None),
  57. ("nodefault.yml", "https://https-and-http.nginx-proxy.test/", 200, None),
  58. ("nodefault.yml", "http://https-only.nginx-proxy.test/", 503, None),
  59. ("nodefault.yml", "https://https-only.nginx-proxy.test/", 200, None),
  60. ("nodefault.yml", "http://http-only.nginx-proxy.test/", 200, None),
  61. ("nodefault.yml", "https://http-only.nginx-proxy.test/", None, INTERNAL_ERR_RE),
  62. ("nodefault.yml", "http://missing-cert.nginx-proxy.test/", 200, None),
  63. ("nodefault.yml", "https://missing-cert.nginx-proxy.test/", None, INTERNAL_ERR_RE),
  64. ("nodefault.yml", "http://unknown.nginx-proxy.test/", 503, None),
  65. ("nodefault.yml", "https://unknown.nginx-proxy.test/", None, INTERNAL_ERR_RE),
  66. # HTTPS_METHOD=nohttp on nginx-proxy, HTTPS_METHOD unset on the app container.
  67. ("nohttp.yml", "http://https-only.nginx-proxy.test/", 503, None),
  68. ("nohttp.yml", "https://https-only.nginx-proxy.test/", 200, None),
  69. ("nohttp.yml", "http://unknown.nginx-proxy.test/", 503, None),
  70. ("nohttp.yml", "https://unknown.nginx-proxy.test/", 503, None),
  71. # HTTPS_METHOD=redirect on nginx-proxy, HTTPS_METHOD=nohttp on the app container.
  72. ("nohttp-on-app.yml", "http://https-only.nginx-proxy.test/", 503, None),
  73. ("nohttp-on-app.yml", "https://https-only.nginx-proxy.test/", 200, None),
  74. ("nohttp-on-app.yml", "http://unknown.nginx-proxy.test/", 503, None),
  75. ("nohttp-on-app.yml", "https://unknown.nginx-proxy.test/", 503, None),
  76. # Same as nohttp.yml, except there are two vhosts with a missing cert, the second
  77. # one being configured not to trust the default certificate. This causes its
  78. # HTTPS_METHOD=nohttp setting to effectively become HTTPS_METHOD=noredirect.
  79. ("nohttp-with-missing-cert.yml", "http://https-only.nginx-proxy.test/", 503, None),
  80. ("nohttp-with-missing-cert.yml", "https://https-only.nginx-proxy.test/", 200, None),
  81. ("nohttp-with-missing-cert.yml", "http://missing-cert.nginx-proxy.test/", 503, None),
  82. ("nohttp-with-missing-cert.yml", "https://missing-cert.nginx-proxy.test/", 200, None),
  83. ("nohttp-with-missing-cert.yml", "http://missing-cert.default-untrusted.nginx-proxy.test/", 200, None),
  84. ("nohttp-with-missing-cert.yml", "https://missing-cert.default-untrusted.nginx-proxy.test/", None, INTERNAL_ERR_RE),
  85. ("nohttp-with-missing-cert.yml", "http://unknown.nginx-proxy.test/", 503, None),
  86. ("nohttp-with-missing-cert.yml", "https://unknown.nginx-proxy.test/", 503, None),
  87. # HTTPS_METHOD=nohttps on nginx-proxy, HTTPS_METHOD unset on the app container.
  88. ("nohttps.yml", "http://http-only.nginx-proxy.test/", 200, None),
  89. ("nohttps.yml", "https://http-only.nginx-proxy.test/", None, INTERNAL_ERR_RE),
  90. ("nohttps.yml", "http://unknown.nginx-proxy.test/", 503, None),
  91. ("nohttps.yml", "https://unknown.nginx-proxy.test/", None, INTERNAL_ERR_RE),
  92. # HTTPS_METHOD=redirect on nginx-proxy, HTTPS_METHOD=nohttps on the app container.
  93. ("nohttps-on-app.yml", "http://http-only.nginx-proxy.test/", 200, None),
  94. ("nohttps-on-app.yml", "https://http-only.nginx-proxy.test/", None, INTERNAL_ERR_RE),
  95. ("nohttps-on-app.yml", "http://unknown.nginx-proxy.test/", 503, None),
  96. ("nohttps-on-app.yml", "https://unknown.nginx-proxy.test/", None, INTERNAL_ERR_RE),
  97. # Custom nginx config that has a `server` directive that uses `default_server` and simply
  98. # returns 418. Nginx should successfully start (in particular, the `default_server` in the
  99. # custom config should not conflict with the fallback server generated by nginx-proxy) and nginx
  100. # should prefer that server for handling requests for unknown vhosts.
  101. ("custom-fallback.yml", "http://unknown.nginx-proxy.test/", 418, None),
  102. ])
  103. def test_fallback(get, compose_file, url, want_code, want_err_re):
  104. if want_err_re is None:
  105. r = get(url, want_code)
  106. assert r.status_code == want_code
  107. else:
  108. with pytest.raises(requests.exceptions.SSLError, match=want_err_re):
  109. get(url)