#!/bin/bash # Example usage of posthook API # # If your Posthook instance is behind oauth2-proxy, provide the cookie value: # OAUTH2_PROXY_COOKIE="" ./examples.sh # ./examples.sh --cookie "" # # 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 ] [--cookie ] Options: --base-url Posthook base URL (or set BASE_URL) --cookie 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..." 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 echo "2. Registering a form webhook..." 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 echo "3. Registering an hCaptcha-protected webhook..." 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 echo "3b. Registering a webhook with ntfy notifications..." 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 echo "4. Listing all routes..." 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 echo "5. Sending test data to simple-webhook..." 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 echo "6. Sending form data to form-webhook..." 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 echo "6b. Sending webhook to ntfy-webhook (check https://ntfy.sh/posthook-demo-alerts)..." 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 echo "6c. Sending form with _redirect (should return 303 redirect)..." 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 echo "6d. Getting CSRF token for secure-form..." 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. Sending form with CSRF token..." 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 echo "6f. Trying to send without token (should fail)..." 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 echo "7. Testing 404 on non-existent route..." 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 echo "8. Health check..." expect_json "health" GET "$BASE_URL/health" "" "" 200 '.ok == "ok"' echo echo "=== Examples complete ==="