test_fallback.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import os.path
  2. import re
  3. import backoff
  4. import pytest
  5. import requests
  6. @pytest.fixture
  7. def data_dir():
  8. return f"{os.path.splitext(__file__)[0]}.data"
  9. @pytest.fixture
  10. def docker_compose_file(data_dir, compose_file):
  11. return os.path.join(data_dir, compose_file)
  12. @pytest.fixture
  13. def get(docker_compose, nginxproxy, want_err_re):
  14. @backoff.on_exception(
  15. backoff.constant,
  16. requests.exceptions.RequestException,
  17. giveup=lambda e: want_err_re and want_err_re.search(str(e)),
  18. interval=.3,
  19. max_tries=30,
  20. jitter=None)
  21. def _get(url):
  22. return nginxproxy.get(url, allow_redirects=False)
  23. return _get
  24. INTERNAL_ERR_RE = re.compile("TLSV1_ALERT_INTERNAL_ERROR")
  25. CONNECTION_REFUSED_RE = re.compile("Connection refused")
  26. @pytest.mark.parametrize("compose_file,url,want_code,want_err_re", [
  27. # Has default.crt.
  28. ("withdefault.yml", "http://https-and-http.nginx-proxy.test/", 301, None),
  29. ("withdefault.yml", "https://https-and-http.nginx-proxy.test/", 200, None),
  30. ("withdefault.yml", "http://https-only.nginx-proxy.test/", 503, None),
  31. ("withdefault.yml", "https://https-only.nginx-proxy.test/", 200, None),
  32. ("withdefault.yml", "http://http-only.nginx-proxy.test/", 200, None),
  33. ("withdefault.yml", "https://http-only.nginx-proxy.test/", 503, None),
  34. ("withdefault.yml", "http://missing-cert.nginx-proxy.test/", 301, None),
  35. ("withdefault.yml", "https://missing-cert.nginx-proxy.test/", 500, None),
  36. ("withdefault.yml", "http://unknown.nginx-proxy.test/", 503, None),
  37. ("withdefault.yml", "https://unknown.nginx-proxy.test/", 503, None),
  38. # Same as withdefault.yml, except there is no default.crt.
  39. ("nodefault.yml", "http://https-and-http.nginx-proxy.test/", 301, None),
  40. ("nodefault.yml", "https://https-and-http.nginx-proxy.test/", 200, None),
  41. ("nodefault.yml", "http://https-only.nginx-proxy.test/", 503, None),
  42. ("nodefault.yml", "https://https-only.nginx-proxy.test/", 200, None),
  43. ("nodefault.yml", "http://http-only.nginx-proxy.test/", 200, None),
  44. ("nodefault.yml", "https://http-only.nginx-proxy.test/", None, INTERNAL_ERR_RE),
  45. ("nodefault.yml", "http://missing-cert.nginx-proxy.test/", 301, None),
  46. ("nodefault.yml", "https://missing-cert.nginx-proxy.test/", None, INTERNAL_ERR_RE),
  47. ("nodefault.yml", "http://unknown.nginx-proxy.test/", 503, None),
  48. ("nodefault.yml", "https://unknown.nginx-proxy.test/", None, INTERNAL_ERR_RE),
  49. # HTTPS_METHOD=nohttp on nginx-proxy, HTTPS_METHOD unset on the app container.
  50. ("nohttp.yml", "http://https-only.nginx-proxy.test/", None, CONNECTION_REFUSED_RE),
  51. ("nohttp.yml", "https://https-only.nginx-proxy.test/", 200, None),
  52. ("nohttp.yml", "http://unknown.nginx-proxy.test/", None, CONNECTION_REFUSED_RE),
  53. ("nohttp.yml", "https://unknown.nginx-proxy.test/", 503, None),
  54. # HTTPS_METHOD=redirect on nginx-proxy, HTTPS_METHOD=nohttp on the app container.
  55. ("nohttp-on-app.yml", "http://https-only.nginx-proxy.test/", None, CONNECTION_REFUSED_RE),
  56. ("nohttp-on-app.yml", "https://https-only.nginx-proxy.test/", 200, None),
  57. ("nohttp-on-app.yml", "http://unknown.nginx-proxy.test/", None, CONNECTION_REFUSED_RE),
  58. ("nohttp-on-app.yml", "https://unknown.nginx-proxy.test/", 503, None),
  59. # Same as nohttp.yml, except there is a vhost with a missing cert. The missing cert should not
  60. # cause that vhost to downgrade from https to http.
  61. ("nohttp-with-missing-cert.yml", "http://https-only.nginx-proxy.test/", None, CONNECTION_REFUSED_RE),
  62. ("nohttp-with-missing-cert.yml", "https://https-only.nginx-proxy.test/", 200, None),
  63. ("nohttp-with-missing-cert.yml", "http://missing-cert.nginx-proxy.test/", None, CONNECTION_REFUSED_RE),
  64. ("nohttp-with-missing-cert.yml", "https://missing-cert.nginx-proxy.test/", 500, None),
  65. ("nohttp-with-missing-cert.yml", "http://unknown.nginx-proxy.test/", None, CONNECTION_REFUSED_RE),
  66. ("nohttp-with-missing-cert.yml", "https://unknown.nginx-proxy.test/", 503, None),
  67. # HTTPS_METHOD=nohttps on nginx-proxy, HTTPS_METHOD unset on the app container.
  68. ("nohttps.yml", "http://http-only.nginx-proxy.test/", 200, None),
  69. ("nohttps.yml", "https://http-only.nginx-proxy.test/", None, CONNECTION_REFUSED_RE),
  70. ("nohttps.yml", "http://unknown.nginx-proxy.test/", 503, None),
  71. ("nohttps.yml", "https://unknown.nginx-proxy.test/", None, CONNECTION_REFUSED_RE),
  72. # HTTPS_METHOD=redirect on nginx-proxy, HTTPS_METHOD=nohttps on the app container.
  73. ("nohttps-on-app.yml", "http://http-only.nginx-proxy.test/", 200, None),
  74. ("nohttps-on-app.yml", "https://http-only.nginx-proxy.test/", None, CONNECTION_REFUSED_RE),
  75. ("nohttps-on-app.yml", "http://unknown.nginx-proxy.test/", 503, None),
  76. ("nohttps-on-app.yml", "https://unknown.nginx-proxy.test/", None, CONNECTION_REFUSED_RE),
  77. # Custom nginx config that has a `server` directive that uses `default_server` and simply
  78. # returns 418. Nginx should successfully start (in particular, the `default_server` in the
  79. # custom config should not conflict with the fallback server generated by nginx-proxy) and nginx
  80. # should prefer that server for handling requests for unknown vhosts.
  81. ("custom-fallback.yml", "http://unknown.nginx-proxy.test/", 418, None),
  82. ])
  83. def test_fallback(get, url, want_code, want_err_re):
  84. if want_err_re is None:
  85. r = get(url)
  86. assert r.status_code == want_code
  87. else:
  88. with pytest.raises(requests.exceptions.RequestException, match=want_err_re):
  89. get(url)