summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Harlow <harlowja@yahoo-inc.com>2015-09-11 11:40:29 -0700
committerJoshua Harlow <harlowja@yahoo-inc.com>2015-09-17 15:22:43 -0700
commitcc4577394253d23ac3c7903c5a56b9e7bea9ba78 (patch)
tree26d743a9a4973e8f38beecdf7ab6d0d758dbc123
parentccff90e5b604904831e2085b173ea9a66d0441b8 (diff)
downloadoslo-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__.py37
-rw-r--r--oslo_middleware/tests/test_healthcheck.py25
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',