diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1556865b..ea0d51d1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
- When saving a phone number, remove any invisible unicode characers
- Update the read-only dashboard's CSS for better mobile support (#442)
- Reduce the number of SQL queries used in the "Get Checks" API call
+- Add support for script's exit status in ping URLs (#429)
## v1.17.0 - 2020-10-14
diff --git a/hc/api/tests/test_ping.py b/hc/api/tests/test_ping.py
index 023a141c..81af3f84 100644
--- a/hc/api/tests/test_ping.py
+++ b/hc/api/tests/test_ping.py
@@ -224,3 +224,23 @@ class PingTestCase(BaseTestCase):
ping = Ping.objects.latest("id")
self.assertEqual(ping.scheme, "http")
self.assertEqual(ping.kind, "ign")
+
+ def test_zero_exit_status_works(self):
+ r = self.client.get("/ping/%s/0" % self.check.code)
+ self.assertEqual(r.status_code, 200)
+
+ self.check.refresh_from_db()
+ self.assertEqual(self.check.status, "up")
+
+ ping = Ping.objects.latest("id")
+ self.assertEqual(ping.kind, None)
+
+ def test_nonzero_exit_status_works(self):
+ r = self.client.get("/ping/%s/123" % self.check.code)
+ self.assertEqual(r.status_code, 200)
+
+ self.check.refresh_from_db()
+ self.assertEqual(self.check.status, "down")
+
+ ping = Ping.objects.latest("id")
+ self.assertEqual(ping.kind, "fail")
diff --git a/hc/api/urls.py b/hc/api/urls.py
index a2109e03..7546b68a 100644
--- a/hc/api/urls.py
+++ b/hc/api/urls.py
@@ -32,6 +32,7 @@ urlpatterns = [
path("ping/
In this example, we run certbot renew
, capture its output, and submit
-the captured output to SITE_NAME:
In this example, we run certbot renew
, capture its output (both the stdout
+and stderr streams), and submit the captured output to SITE_NAME:
#!/bin/sh
m=$(/usr/bin/certbot renew 2>&1)
@@ -13,24 +13,13 @@ curl -fsS -m 10 --retry 5 --data-r
/fail
Endpoint/fail
and /{exit-status}
EndpointsWe can extend the previous example and signal either success or failure depending on the exit code:
#!/bin/sh
-url=PING_URL
-
m=$(/usr/bin/certbot renew 2>&1)
-
-if [ $? -ne 0 ]; then url=$url/fail; fi
-curl -fsS -m 10 --retry 5 --data-raw "$m" $url
-
The above script can be packaged in a single line. The one-line -version sacrifices some readability, but it can be used directly in crontab, -without using a wrapper script:
-m=$(/usr/bin/certbot renew 2>&1); curl -fsS --data-raw "$m" "PING_URL$([ $? -ne 0 ] && echo -n /fail)"
+curl -fsS -m 10 --retry 5 --data-raw "$m" PING_URL/$?
You can append /fail
to any ping URL and use the resulting URL to actively
-signal a failure. The following example:
/usr/bin/certbot renew
PING_URL
PING_URL/fail
You can append /fail
or /{exit-status}
to any ping URL and use the resulting URL
+to actively signal a failure. The exit status should be a 0-255 integer.
+SITE_NAME will interpret exit status 0 as success, and all non-zero values as failures.
The following example runs /usr/bin/certbot renew
, and uses the $?
variable to
+look up its exit status:
#!/bin/sh
# Payload here:
/usr/bin/certbot renew
# Ping SITE_NAME
-curl -m 10 --retry 5 "PING_URL$([ $? -ne 0 ] && echo -n /fail)"
+curl -m 10 --retry 5 PING_URL/$?
HTTP/1.1 200 OK
+Server: nginx
+Date: Wed, 29 Jan 2020 09:58:23 GMT
+Content-Type: text/plain; charset=utf-8
+Content-Length: 2
+Connection: close
+Access-Control-Allow-Origin: *
+
+OK
+
HEAD|GET|POST PING_ENDPOINT{uuid}/{exit-status}
+
Sends a success or failure signal depending on the exit status +included in the URL. The exit status is a 0-255 integer. SITE_NAME +interprets 0 as success, and all other values as failure.
+Example
+GET /5bf66975-d4c7-4bf5-bcc8-b8d8a82ea278/1 HTTP/1.0
+Host: hc-ping.com
+
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 29 Jan 2020 09:58:23 GMT
diff --git a/templates/docs/http_api.md b/templates/docs/http_api.md
index 66c03d02..7beca14b 100644
--- a/templates/docs/http_api.md
+++ b/templates/docs/http_api.md
@@ -105,3 +105,32 @@ Access-Control-Allow-Origin: *
OK
```
+
+## Report Script's Exit Status
+
+```text
+HEAD|GET|POST PING_ENDPOINT{uuid}/{exit-status}
+```
+
+Sends a success or failure signal depending on the exit status
+included in the URL. The exit status is a 0-255 integer. SITE_NAME
+interprets 0 as success, and all other values as failure.
+
+**Example**
+
+```http
+GET /5bf66975-d4c7-4bf5-bcc8-b8d8a82ea278/1 HTTP/1.0
+Host: hc-ping.com
+```
+
+```http
+HTTP/1.1 200 OK
+Server: nginx
+Date: Wed, 29 Jan 2020 09:58:23 GMT
+Content-Type: text/plain; charset=utf-8
+Content-Length: 2
+Connection: close
+Access-Control-Allow-Origin: *
+
+OK
+```
diff --git a/templates/docs/signalling_failures.html b/templates/docs/signalling_failures.html
index 564a3ff5..ba7b065b 100644
--- a/templates/docs/signalling_failures.html
+++ b/templates/docs/signalling_failures.html
@@ -1,19 +1,26 @@
Signalling failures
-Append /fail
to a ping URL and use it to actively signal a failure.
-Requesting the /fail
URL will immediately mark the check as "down".
-You can use this feature to minimize the delay from your monitored service failing
-to you getting a notification.
+You can actively signal a failure to SITE_NAME by slightly changing the
+ping URL: append either /fail
or /{exit-status}
to your normal ping URL.
+The exit status should be a 0-255 integer. SITE_NAME will interpret
+exit status 0 as success, and all non-zero values as failures.
+Examples:
+# Reports failure by appending the /fail suffix:
+curl --retry 3 PING_URL/fail
+
+# Reports failure by appending a non-zero exit status:
+curl --retry 3 PING_URL/1
+
+
+
+By actively signalling failures to SITE_NAME, you can minimize the delay from your
+monitored service encountering a problem to you getting notified about it.
Shell Scripts
-The below shell script sends either a "success" or "failure" ping depending on
-command's (certbot in this example) exit code:
+The below shell script appends $?
(a special variable which contains the
+exit status of the last executed command) to the ping URL:
#!/bin/sh
-url=PING_URL
-
/usr/bin/certbot renew
-
-if [ $? -ne 0 ]; then url=$url/fail; fi
-curl --retry 3 $url
+curl --retry 3 PING_URL/$?
diff --git a/templates/docs/signalling_failures.md b/templates/docs/signalling_failures.md
index 1b69164c..50376591 100644
--- a/templates/docs/signalling_failures.md
+++ b/templates/docs/signalling_failures.md
@@ -1,24 +1,35 @@
# Signalling failures
-Append `/fail` to a ping URL and use it to actively signal a failure.
-Requesting the `/fail` URL will immediately mark the check as "down".
-You can use this feature to minimize the delay from your monitored service failing
-to you getting a notification.
+You can actively signal a failure to SITE_NAME by slightly changing the
+ping URL: append either `/fail` or `/{exit-status}` to your normal ping URL.
+The exit status should be a 0-255 integer. SITE_NAME will interpret
+exit status 0 as success, and all non-zero values as failures.
+
+Examples:
+
+```bash
+
+# Reports failure by appending the /fail suffix:
+curl --retry 3 PING_URL/fail
+
+# Reports failure by appending a non-zero exit status:
+curl --retry 3 PING_URL/1
+```
+
+By actively signalling failures to SITE_NAME, you can minimize the delay from your
+monitored service encountering a problem to you getting notified about it.
## Shell Scripts
-The below shell script sends either a "success" or "failure" ping depending on
-command's (certbot in this example) exit code:
+The below shell script appends `$?` (a special variable which contains the
+exit status of the last executed command) to the ping URL:
```bash
#!/bin/sh
-url=PING_URL
-
/usr/bin/certbot renew
+curl --retry 3 PING_URL/$?
-if [ $? -ne 0 ]; then url=$url/fail; fi
-curl --retry 3 $url
```
## Python