diff --git a/docs/rest_api.rst b/docs/rest_api.rst index ad1ac75c..5a2879d3 100644 --- a/docs/rest_api.rst +++ b/docs/rest_api.rst @@ -7,7 +7,7 @@ Patroni has a rich REST API, which is used by Patroni itself during the leader r Health check endpoints ---------------------- -For all health check ``GET`` requests Patroni returns a JSON document with the status of the node, along with the HTTP status code. If you don't want or don't need the JSON document, you might consider using the ``OPTIONS`` method instead of ``GET``. +For all health check ``GET`` requests Patroni returns a JSON document with the status of the node, along with the HTTP status code. If you don't want or don't need the JSON document, you might consider using the ``HEAD`` or ``OPTIONS`` method instead of ``GET``. - The following requests to Patroni REST API will return HTTP status code **200** only when the Patroni node is running as the primary with leader lock: diff --git a/extras/confd/templates/haproxy.tmpl b/extras/confd/templates/haproxy.tmpl index 752986f3..31f88194 100644 --- a/extras/confd/templates/haproxy.tmpl +++ b/extras/confd/templates/haproxy.tmpl @@ -18,14 +18,14 @@ listen stats listen master bind *:5000 - option httpchk OPTIONS /master + option httpchk HEAD /master http-check expect status 200 default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions {{range gets "/members/*"}} server {{base .Key}} {{$data := json .Value}}{{base (replace (index (split $data.conn_url "/") 2) "@" "/" -1)}} maxconn 100 check port {{index (split (index (split $data.api_url "/") 2) ":") 1}} {{end}} listen replicas bind *:5001 - option httpchk OPTIONS /replica + option httpchk HEAD /replica http-check expect status 200 default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions {{range gets "/members/*"}} server {{base .Key}} {{$data := json .Value}}{{base (replace (index (split $data.conn_url "/") 2) "@" "/" -1)}} maxconn 100 check port {{index (split (index (split $data.api_url "/") 2) ":") 1}} diff --git a/patroni/api.py b/patroni/api.py index 3b7b4192..963be433 100644 --- a/patroni/api.py +++ b/patroni/api.py @@ -38,6 +38,7 @@ class RestApiHandler(BaseHTTPRequestHandler): self.log_request(status_code) def _write_response(self, status_code, body, content_type='text/html', headers=None): + # TODO: try-catch ConnectionResetError: [Errno 104] Connection reset by peer and log it in DEBUG level self.send_response(status_code) headers = headers or {} if content_type: @@ -185,6 +186,9 @@ class RestApiHandler(BaseHTTPRequestHandler): def do_OPTIONS(self): self.do_GET(write_status_code_only=True) + def do_HEAD(self): + self.do_GET(write_status_code_only=True) + def do_GET_liveness(self): self._write_status_code_only(200) diff --git a/tests/test_api.py b/tests/test_api.py index 01e5dc89..681814b0 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -286,6 +286,9 @@ class TestRestApiHandler(unittest.TestCase): def test_do_OPTIONS(self): self.assertIsNotNone(MockRestApiServer(RestApiHandler, 'OPTIONS / HTTP/1.0')) + def test_do_HEAD(self): + self.assertIsNotNone(MockRestApiServer(RestApiHandler, 'HEAD / HTTP/1.0')) + def test_do_GET_liveness(self): self.assertIsNotNone(MockRestApiServer(RestApiHandler, 'GET /liveness HTTP/1.0'))