diff options
| author | Elizabeth Hunt <me@liz.coffee> | 2025-12-14 22:43:24 -0800 |
|---|---|---|
| committer | Elizabeth Hunt <me@liz.coffee> | 2025-12-14 22:43:24 -0800 |
| commit | cdb1a57614068fcfefa145bc6df45c9def7ccc6a (patch) | |
| tree | 92cadbecda8658c143b7625d5925e3411976a892 /examples.sh | |
| parent | 6d318665a08c0d4564d8de23cc39425d2c0bac49 (diff) | |
| download | posthook-cdb1a57614068fcfefa145bc6df45c9def7ccc6a.tar.gz posthook-cdb1a57614068fcfefa145bc6df45c9def7ccc6a.zip | |
Updates
Diffstat (limited to 'examples.sh')
| -rwxr-xr-x | examples.sh | 356 |
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 ===" |
