diff options
author | Joshua Harlow <harlowja@yahoo-inc.com> | 2015-09-11 11:40:29 -0700 |
---|---|---|
committer | Joshua Harlow <harlowja@yahoo-inc.com> | 2015-09-17 15:22:43 -0700 |
commit | cc4577394253d23ac3c7903c5a56b9e7bea9ba78 (patch) | |
tree | 26d743a9a4973e8f38beecdf7ab6d0d758dbc123 | |
parent | ccff90e5b604904831e2085b173ea9a66d0441b8 (diff) | |
download | oslo-middleware-cc4577394253d23ac3c7903c5a56b9e7bea9ba78.tar.gz |
Avoid any body when request is a HEAD request
Instead of creating a body for a request that is known
to be a HEAD request avoid creating any body in the first
place and just return the status code determined from
the health evaluation.
Closes-Bug: #1494533
Change-Id: I39abee3cdfff4af40355f91d22607e3a2aa52e29
-rw-r--r-- | oslo_middleware/healthcheck/__init__.py | 37 | ||||
-rw-r--r-- | oslo_middleware/tests/test_healthcheck.py | 25 |
2 files changed, 53 insertions, 9 deletions
diff --git a/oslo_middleware/healthcheck/__init__.py b/oslo_middleware/healthcheck/__init__.py index 9aa2c2e..4a17295 100644 --- a/oslo_middleware/healthcheck/__init__.py +++ b/oslo_middleware/healthcheck/__init__.py @@ -54,6 +54,22 @@ class Healthcheck(base.ConfigurableMiddleware): can provide details (or no details, depending on if configured) about the activity of the server. + Example requests/responses: + + $ curl -i -X HEAD "http://0.0.0.0:8775/status" + HTTP/1.1 204 No Content + Content-Type: text/plain; charset=UTF-8 + Content-Length: 0 + Date: Fri, 11 Sep 2015 18:55:08 GMT + + $ curl -i "http://0.0.0.0:8775/status" + HTTP/1.1 200 OK + Content-Type: text/plain; charset=UTF-8 + Content-Length: 2 + Date: Fri, 11 Sep 2015 18:55:43 GMT + + OK + Example of paste configuration: .. code-block:: ini @@ -101,6 +117,10 @@ class Healthcheck(base.ConfigurableMiddleware): True: webob.exc.HTTPOk.code, False: webob.exc.HTTPServiceUnavailable.code, } + HEAD_HEALTHY_TO_STATUS_CODES = { + True: webob.exc.HTTPNoContent.code, + False: webob.exc.HTTPServiceUnavailable.code, + } PLAIN_RESPONSE_TEMPLATE = """ {% for reason in reasons %} {% if reason %}{{reason}}{% endif -%} @@ -198,6 +218,9 @@ class Healthcheck(base.ConfigurableMiddleware): } return (self._pretty_json_dumps(body), 'application/json') + def _make_head_response(self, results, healthy): + return ( "", "text/plain") + def _make_html_response(self, results, healthy): try: hostname = socket.gethostname() @@ -225,11 +248,15 @@ class Healthcheck(base.ConfigurableMiddleware): return None results = [ext.obj.healthcheck() for ext in self._backends] healthy = self._are_results_healthy(results) - accept_type = req.accept.best_match(self._accept_order) - if not accept_type: - accept_type = self._default_accept - functor = self._accept_to_functor[accept_type] + if req.method == "HEAD": + functor = self._make_head_response + status = self.HEAD_HEALTHY_TO_STATUS_CODES[healthy] + else: + status = self.HEALTHY_TO_STATUS_CODES[healthy] + accept_type = req.accept.best_match(self._accept_order) + if not accept_type: + accept_type = self._default_accept + functor = self._accept_to_functor[accept_type] body, content_type = functor(results, healthy) - status = self.HEALTHY_TO_STATUS_CODES[healthy] return webob.response.Response(status=status, body=body, content_type=content_type) diff --git a/oslo_middleware/tests/test_healthcheck.py b/oslo_middleware/tests/test_healthcheck.py index b516d0c..144d274 100644 --- a/oslo_middleware/tests/test_healthcheck.py +++ b/oslo_middleware/tests/test_healthcheck.py @@ -29,16 +29,18 @@ class HealthcheckTests(test_base.BaseTestCase): return 'Hello, World!!!' def _do_test_request(self, conf={}, path='/healthcheck', - accept='text/plain'): + accept='text/plain', method='GET'): self.app = healthcheck.Healthcheck(self.application, conf) - req = webob.Request.blank(path, accept=accept) + req = webob.Request.blank(path, accept=accept, method=method) res = req.get_response(self.app) return res def _do_test(self, conf={}, path='/healthcheck', expected_code=webob.exc.HTTPOk.code, - expected_body=b'', accept='text/plain'): - res = self._do_test_request(conf=conf, path=path, accept=accept) + expected_body=b'', accept='text/plain', + method='GET'): + res = self._do_test_request(conf=conf, path=path, + accept=accept, method=method) self.assertEqual(expected_code, res.status_int) self.assertEqual(expected_body, res.body) @@ -74,6 +76,12 @@ class HealthcheckTests(test_base.BaseTestCase): self._do_test(conf, expected_body=b'OK') self.assertIn('disable_by_file', self.app._backends.names()) + def test_disablefile_enabled_head(self): + conf = {'backends': 'disable_by_file', + 'disable_by_file_path': '/foobar'} + self._do_test(conf, expected_body=b'', method='HEAD', + expected_code=webob.exc.HTTPNoContent.code) + def test_disablefile_enabled_html_detailed(self): conf = {'backends': 'disable_by_file', 'disable_by_file_path': '/foobar', 'detailed': True} @@ -91,6 +99,15 @@ class HealthcheckTests(test_base.BaseTestCase): expected_body=b'DISABLED BY FILE') self.assertIn('disable_by_file', self.app._backends.names()) + def test_disablefile_disabled_head(self): + filename = self.create_tempfiles([('test', 'foobar')])[0] + conf = {'backends': 'disable_by_file', + 'disable_by_file_path': filename} + self._do_test(conf, + expected_code=webob.exc.HTTPServiceUnavailable.code, + expected_body=b'', method='HEAD') + self.assertIn('disable_by_file', self.app._backends.names()) + def test_disablefile_disabled_html_detailed(self): filename = self.create_tempfiles([('test', 'foobar')])[0] conf = {'backends': 'disable_by_file', |