aboutsummaryrefslogtreecommitdiff
path: root/examples.sh
diff options
context:
space:
mode:
Diffstat (limited to 'examples.sh')
-rwxr-xr-xexamples.sh356
1 files changed, 249 insertions, 107 deletions
diff --git a/examples.sh b/examples.sh
index 69c1eb8..4efbc75 100755
--- a/examples.sh
+++ b/examples.sh
@@ -1,162 +1,304 @@
#!/bin/bash
# Example usage of posthook API
+#
+# If your Posthook instance is behind oauth2-proxy, provide the cookie value:
+# OAUTH2_PROXY_COOKIE="<cookie value>" ./examples.sh
+# ./examples.sh --cookie "<cookie value>"
+#
+# Optionally override the base URL:
+# BASE_URL="http://localhost:9000" ./examples.sh
+# ./examples.sh --base-url "http://localhost:9000"
+
+set -euo pipefail
+
+usage() {
+ cat <<'EOF'
+Usage: ./examples.sh [--base-url <url>] [--cookie <value>]
+
+Options:
+ --base-url <url> Posthook base URL (or set BASE_URL)
+ --cookie <value> Value for the _oauth2_proxy cookie (or set OAUTH2_PROXY_COOKIE)
+ -h, --help Show this help
+EOF
+}
+
+require_cmd() {
+ if ! command -v "$1" >/dev/null 2>&1; then
+ echo "Missing required command: $1" >&2
+ exit 1
+ fi
+}
BASE_URL="${BASE_URL:-http://localhost:9000}"
+OAUTH2_PROXY_COOKIE="${OAUTH2_PROXY_COOKIE:-}"
+
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ --base-url)
+ BASE_URL="$2"
+ shift 2
+ ;;
+ --cookie|--oauth2-proxy-cookie)
+ OAUTH2_PROXY_COOKIE="$2"
+ shift 2
+ ;;
+ -h|--help)
+ usage
+ exit 0
+ ;;
+ *)
+ echo "Unknown argument: $1" >&2
+ usage >&2
+ exit 1
+ ;;
+ esac
+done
+
+require_cmd curl
+require_cmd jq
+
+CURL_AUTH_ARGS=()
+if [[ -n "$OAUTH2_PROXY_COOKIE" ]]; then
+ if [[ "$OAUTH2_PROXY_COOKIE" == _oauth2_proxy=* ]]; then
+ CURL_AUTH_ARGS=(-b "$OAUTH2_PROXY_COOKIE")
+ else
+ CURL_AUTH_ARGS=(-b "_oauth2_proxy=$OAUTH2_PROXY_COOKIE")
+ fi
+fi
+
+curl_with_status() {
+ local method="$1"
+ local url="$2"
+ local content_type="${3:-}"
+ local data="${4:-}"
+
+ local curl_args=("${CURL_AUTH_ARGS[@]}" -sS)
+
+ if [[ -n "$content_type" ]]; then
+ curl_args+=(-H "Content-Type: $content_type")
+ fi
+
+ # Avoid curl's "Unnecessary use of -X" warning when POST already inferred.
+ if [[ "$method" != "POST" || -z "$data" ]]; then
+ curl_args+=(-X "$method")
+ fi
+
+ if [[ -n "$data" ]]; then
+ curl_args+=(-d "$data")
+ fi
+
+ curl "${curl_args[@]}" "$url" -w $'\n%{http_code}'
+}
+
+expect_json() {
+ local label="$1"
+ local method="$2"
+ local url="$3"
+ local content_type="${4:-}"
+ local data="${5:-}"
+ local expected_status="$6"
+ local jq_check="$7"
+
+ local out body status
+ out="$(curl_with_status "$method" "$url" "$content_type" "$data")"
+ status="${out##*$'\n'}"
+ body="${out%$'\n'*}"
+
+ if [[ "$status" != "$expected_status" ]]; then
+ echo "$label: unexpected HTTP $status (expected $expected_status)" >&2
+ echo "$body" >&2
+ exit 1
+ fi
+
+ if ! echo "$body" | jq -e "$jq_check" >/dev/null; then
+ echo "$label: response did not match expected JSON" >&2
+ echo "$body" >&2
+ exit 1
+ fi
+
+ echo "$body"
+}
+
+expect_redirect() {
+ local label="$1"
+ local url="$2"
+ local content_type="$3"
+ local data="$4"
+ local expected_status="$5"
+ local expected_location="$6"
+
+ local out header_text status location
+ out="$(curl "${CURL_AUTH_ARGS[@]}" -sS -o /dev/null -D - -H "Content-Type: $content_type" -d "$data" "$url" -w $'\n%{http_code}')"
+ status="${out##*$'\n'}"
+ header_text="${out%$'\n'*}"
+
+ if [[ "$status" != "$expected_status" ]]; then
+ echo "$label: unexpected HTTP $status (expected $expected_status)" >&2
+ echo "$header_text" >&2
+ exit 1
+ fi
+
+ location=""
+ while IFS= read -r line; do
+ line="${line%$'\r'}"
+ case "$line" in
+ [Ll]ocation:*)
+ location="${line#*: }"
+ ;;
+ esac
+ done <<< "$header_text"
+
+ if [[ "$location" != "$expected_location" ]]; then
+ echo "$label: unexpected Location: $location" >&2
+ echo "$header_text" >&2
+ exit 1
+ fi
+
+ echo "HTTP $status"
+ echo "Location: $location"
+}
echo "=== Posthook Examples ==="
echo
# 1. Register a simple JSON webhook
echo "1. Registering a simple JSON webhook..."
-curl -X POST "$BASE_URL/admin/routes" \
- -H "Content-Type: application/json" \
- -d '{
- "name": "simple-webhook",
- "contentType": "json",
- "hcaptchaProtected": false
- }'
-echo
+ROUTE_SIMPLE_JSON="$(cat <<'JSON'
+{
+ "name": "simple-webhook",
+ "contentType": "json",
+ "hcaptchaProtected": false
+}
+JSON
+)"
+expect_json "register simple-webhook" POST "$BASE_URL/admin/routes" "application/json" "$ROUTE_SIMPLE_JSON" 200 '.ok.success == true'
echo
-# 2. Register a form webhook
echo "2. Registering a form webhook..."
-curl -X POST "$BASE_URL/admin/routes" \
- -H "Content-Type: application/json" \
- -d '{
- "name": "form-webhook",
- "contentType": "form",
- "hcaptchaProtected": false
- }'
-echo
+ROUTE_FORM_JSON="$(cat <<'JSON'
+{
+ "name": "form-webhook",
+ "contentType": "form",
+ "hcaptchaProtected": false
+}
+JSON
+)"
+expect_json "register form-webhook" POST "$BASE_URL/admin/routes" "application/json" "$ROUTE_FORM_JSON" 200 '.ok.success == true'
echo
-# 3. Register an hCaptcha-protected webhook
echo "3. Registering an hCaptcha-protected webhook..."
-curl -X POST "$BASE_URL/admin/routes" \
- -H "Content-Type: application/json" \
- -d '{
- "name": "protected-webhook",
- "contentType": "json",
- "hcaptchaProtected": true,
- "hcaptchaSecret": "0x0000000000000000000000000000000000000000"
- }'
-echo
+ROUTE_HCAPTCHA_JSON="$(cat <<'JSON'
+{
+ "name": "protected-webhook",
+ "contentType": "json",
+ "hcaptchaProtected": true,
+ "hcaptchaSecret": "0x0000000000000000000000000000000000000000"
+}
+JSON
+)"
+expect_json "register protected-webhook" POST "$BASE_URL/admin/routes" "application/json" "$ROUTE_HCAPTCHA_JSON" 200 '.ok.success == true'
echo
-# 3b. Register a webhook with ntfy notifications
echo "3b. Registering a webhook with ntfy notifications..."
-curl -X POST "$BASE_URL/admin/routes" \
- -H "Content-Type: application/json" \
- -d '{
- "name": "ntfy-webhook",
- "contentType": "json",
- "hcaptchaProtected": false,
- "ntfy": {
- "enabled": true,
- "server": "https://ntfy.sh",
- "topic": "posthook-demo-alerts"
- }
- }'
-echo
-echo
-
-# 3c. Register a CSRF token-protected form
-echo "3c. Registering a CSRF token-protected form..."
-curl -X POST "$BASE_URL/admin/routes" \
- -H "Content-Type: application/json" \
- -d '{
- "name": "secure-form",
- "contentType": "form",
- "hcaptchaProtected": false,
- "requireToken": true
- }'
+ROUTE_NTFY_JSON="$(cat <<'JSON'
+{
+ "name": "ntfy-webhook",
+ "contentType": "json",
+ "hcaptchaProtected": false,
+ "ntfy": {
+ "enabled": true,
+ "server": "https://ntfy.sh",
+ "topic": "posthook-demo-alerts"
+ }
+}
+JSON
+)"
+expect_json "register ntfy-webhook" POST "$BASE_URL/admin/routes" "application/json" "$ROUTE_NTFY_JSON" 200 '.ok.success == true'
echo
+
+echo "3c. Registering a CSRF token-protected form..."
+ROUTE_SECURE_FORM_JSON="$(cat <<'JSON'
+{
+ "name": "secure-form",
+ "contentType": "form",
+ "hcaptchaProtected": false,
+ "requireToken": true
+}
+JSON
+)"
+expect_json "register secure-form" POST "$BASE_URL/admin/routes" "application/json" "$ROUTE_SECURE_FORM_JSON" 200 '.ok.success == true'
echo
-# 4. List all routes
echo "4. Listing all routes..."
-curl -X GET "$BASE_URL/admin/routes"
-echo
+expect_json "list routes" GET "$BASE_URL/admin/routes" "" "" 200 \
+ '(.ok.routes | type == "array")
+ and ((.ok.routes | map(.name) | index("simple-webhook")) != null)
+ and ((.ok.routes | map(.name) | index("form-webhook")) != null)
+ and ((.ok.routes | map(.name) | index("protected-webhook")) != null)
+ and ((.ok.routes | map(.name) | index("ntfy-webhook")) != null)
+ and ((.ok.routes | map(.name) | index("secure-form")) != null)'
echo
-# 5. Send a test webhook to simple-webhook
echo "5. Sending test data to simple-webhook..."
-curl -X POST "$BASE_URL/hook/simple-webhook" \
- -H "Content-Type: application/json" \
- -d '{
- "event": "test",
- "data": {
- "foo": "bar",
- "timestamp": 1234567890
- }
- }'
-echo
+SIMPLE_WEBHOOK_BODY="$(cat <<'JSON'
+{
+ "event": "test",
+ "data": {
+ "foo": "bar",
+ "timestamp": 1234567890
+ }
+}
+JSON
+)"
+expect_json "post simple-webhook" POST "$BASE_URL/hook/simple-webhook" "application/json" "$SIMPLE_WEBHOOK_BODY" 200 '.ok.success == true and (.ok.stored | type == "string") and (.ok.stored | endswith("/request.json"))'
echo
-# 6. Send a form webhook
echo "6. Sending form data to form-webhook..."
-curl -X POST "$BASE_URL/hook/form-webhook" \
- -H "Content-Type: application/x-www-form-urlencoded" \
- -d "name=John&email=john@example.com&message=Hello+World"
-echo
+expect_json "post form-webhook" POST "$BASE_URL/hook/form-webhook" "application/x-www-form-urlencoded" \
+ "name=John&email=john@example.com&message=Hello+World" 200 '.ok.success == true and (.ok.stored | type == "string") and (.ok.stored | endswith("/request.json"))'
echo
-# 6b. Send a webhook to ntfy-enabled route (will trigger notification)
echo "6b. Sending webhook to ntfy-webhook (check https://ntfy.sh/posthook-demo-alerts)..."
-curl -X POST "$BASE_URL/hook/ntfy-webhook" \
- -H "Content-Type: application/json" \
- -d '{
- "event": "test-notification",
- "message": "This should trigger an ntfy alert"
- }'
-echo
+NTFY_WEBHOOK_BODY="$(cat <<'JSON'
+{
+ "event": "test-notification",
+ "message": "This should trigger an ntfy alert"
+}
+JSON
+)"
+expect_json "post ntfy-webhook" POST "$BASE_URL/hook/ntfy-webhook" "application/json" "$NTFY_WEBHOOK_BODY" 200 '.ok.success == true and (.ok.stored | type == "string") and (.ok.stored | endswith("/request.json"))'
echo
-# 6c. Send a form with redirect (should return 303 redirect)
echo "6c. Sending form with _redirect (should return 303 redirect)..."
-curl -v -X POST "$BASE_URL/hook/form-webhook" \
- -H "Content-Type: application/x-www-form-urlencoded" \
- -d "name=Jane&email=jane@example.com&message=Testing+redirect&_redirect=https://example.com/thank-you"
-echo
+expect_redirect "redirect form-webhook" "$BASE_URL/hook/form-webhook" "application/x-www-form-urlencoded" \
+ "name=Jane&email=jane@example.com&message=Testing+redirect&_redirect=https://example.com/thank-you" 303 \
+ "https://example.com/thank-you"
echo
-# 6d. Get CSRF token for secure-form
echo "6d. Getting CSRF token for secure-form..."
-TOKEN_RESPONSE=$(curl -s -X GET "$BASE_URL/hook/secure-form/token")
-TOKEN=$(echo $TOKEN_RESPONSE | jq -r '.ok.token')
+TOKEN_RESPONSE="$(expect_json "get secure-form token" GET "$BASE_URL/hook/secure-form/token" "" "" 200 '.ok.token | type == "string" and length > 0')"
+TOKEN="$(echo "$TOKEN_RESPONSE" | jq -r '.ok.token')"
echo "Token: $TOKEN"
echo
-echo
-# 6e. Send form with CSRF token
echo "6e. Sending form with CSRF token..."
-curl -X POST "$BASE_URL/hook/secure-form" \
- -H "Content-Type: application/x-www-form-urlencoded" \
- -d "name=Secure&email=secure@example.com&message=With+token&_token=$TOKEN"
-echo
+expect_json "post secure-form with token" POST "$BASE_URL/hook/secure-form" "application/x-www-form-urlencoded" \
+ "name=Secure&email=secure@example.com&message=With+token&_token=$TOKEN" 200 '.ok.success == true and (.ok.stored | type == "string") and (.ok.stored | endswith("/request.json"))'
echo
-# 6f. Try sending without token (should fail with 400)
echo "6f. Trying to send without token (should fail)..."
-curl -X POST "$BASE_URL/hook/secure-form" \
- -H "Content-Type: application/x-www-form-urlencoded" \
- -d "name=Insecure&email=insecure@example.com&message=No+token"
-echo
+expect_json "post secure-form without token" POST "$BASE_URL/hook/secure-form" "application/x-www-form-urlencoded" \
+ "name=Insecure&email=insecure@example.com&message=No+token" 400 '.error.message == "Missing CSRF token" and .error.status == 400'
echo
-# 7. Test 404 on non-existent route
echo "7. Testing 404 on non-existent route..."
-curl -X POST "$BASE_URL/hook/does-not-exist" \
- -H "Content-Type: application/json" \
- -d '{"test": true}'
-echo
+expect_json "post missing route" POST "$BASE_URL/hook/does-not-exist" "application/json" '{"test": true}' 404 \
+ '.error.message == "Route not found" and .error.status == 404'
echo
-# 8. Health check
echo "8. Health check..."
-curl -X GET "$BASE_URL/health"
-echo
+expect_json "health" GET "$BASE_URL/health" "" "" 200 '.ok == "ok"'
echo
echo "=== Examples complete ==="