210 lines
6.0 KiB
Bash
Executable File
210 lines
6.0 KiB
Bash
Executable File
#!/bin/bash
|
|
# HTTP Request Action - Core Pack
|
|
# Make HTTP requests to external APIs using curl
|
|
|
|
set -e
|
|
set -o pipefail
|
|
|
|
# Read JSON parameters from stdin
|
|
INPUT=$(cat)
|
|
|
|
# Parse required parameters
|
|
URL=$(echo "$INPUT" | jq -r '.url // ""')
|
|
|
|
if [ -z "$URL" ] || [ "$URL" = "null" ]; then
|
|
echo "ERROR: 'url' parameter is required" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Parse optional parameters
|
|
METHOD=$(echo "$INPUT" | jq -r '.method // "GET"' | tr '[:lower:]' '[:upper:]')
|
|
HEADERS=$(echo "$INPUT" | jq -r '.headers // {}')
|
|
BODY=$(echo "$INPUT" | jq -r '.body // ""')
|
|
JSON_BODY=$(echo "$INPUT" | jq -c '.json_body // null')
|
|
QUERY_PARAMS=$(echo "$INPUT" | jq -r '.query_params // {}')
|
|
TIMEOUT=$(echo "$INPUT" | jq -r '.timeout // 30')
|
|
VERIFY_SSL=$(echo "$INPUT" | jq -r '.verify_ssl // true')
|
|
AUTH_TYPE=$(echo "$INPUT" | jq -r '.auth_type // "none"')
|
|
FOLLOW_REDIRECTS=$(echo "$INPUT" | jq -r '.follow_redirects // true')
|
|
MAX_REDIRECTS=$(echo "$INPUT" | jq -r '.max_redirects // 10')
|
|
|
|
# Build URL with query parameters
|
|
FINAL_URL="$URL"
|
|
if [ "$QUERY_PARAMS" != "{}" ] && [ "$QUERY_PARAMS" != "null" ]; then
|
|
QUERY_STRING=$(echo "$QUERY_PARAMS" | jq -r 'to_entries | map("\(.key)=\(.value | @uri)") | join("&")')
|
|
if [[ "$FINAL_URL" == *"?"* ]]; then
|
|
FINAL_URL="${FINAL_URL}&${QUERY_STRING}"
|
|
else
|
|
FINAL_URL="${FINAL_URL}?${QUERY_STRING}"
|
|
fi
|
|
fi
|
|
|
|
# Build curl arguments array
|
|
CURL_ARGS=(
|
|
-X "$METHOD"
|
|
-s # Silent mode
|
|
-w "\n%{http_code}\n%{time_total}\n%{url_effective}\n" # Write out metadata
|
|
--max-time "$TIMEOUT"
|
|
--connect-timeout 10
|
|
)
|
|
|
|
# Handle SSL verification
|
|
if [ "$VERIFY_SSL" = "false" ]; then
|
|
CURL_ARGS+=(-k)
|
|
fi
|
|
|
|
# Handle redirects
|
|
if [ "$FOLLOW_REDIRECTS" = "true" ]; then
|
|
CURL_ARGS+=(-L --max-redirs "$MAX_REDIRECTS")
|
|
fi
|
|
|
|
# Add headers
|
|
if [ "$HEADERS" != "{}" ] && [ "$HEADERS" != "null" ]; then
|
|
while IFS= read -r header; do
|
|
if [ -n "$header" ]; then
|
|
CURL_ARGS+=(-H "$header")
|
|
fi
|
|
done < <(echo "$HEADERS" | jq -r 'to_entries | map("\(.key): \(.value)") | .[]')
|
|
fi
|
|
|
|
# Handle authentication
|
|
case "$AUTH_TYPE" in
|
|
basic)
|
|
AUTH_USERNAME=$(echo "$INPUT" | jq -r '.auth_username // ""')
|
|
AUTH_PASSWORD=$(echo "$INPUT" | jq -r '.auth_password // ""')
|
|
if [ -n "$AUTH_USERNAME" ] && [ "$AUTH_USERNAME" != "null" ]; then
|
|
CURL_ARGS+=(-u "${AUTH_USERNAME}:${AUTH_PASSWORD}")
|
|
fi
|
|
;;
|
|
bearer)
|
|
AUTH_TOKEN=$(echo "$INPUT" | jq -r '.auth_token // ""')
|
|
if [ -n "$AUTH_TOKEN" ] && [ "$AUTH_TOKEN" != "null" ]; then
|
|
CURL_ARGS+=(-H "Authorization: Bearer ${AUTH_TOKEN}")
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
# Handle request body
|
|
if [ "$JSON_BODY" != "null" ] && [ "$JSON_BODY" != "" ]; then
|
|
CURL_ARGS+=(-H "Content-Type: application/json")
|
|
CURL_ARGS+=(-d "$JSON_BODY")
|
|
elif [ -n "$BODY" ] && [ "$BODY" != "null" ]; then
|
|
CURL_ARGS+=(-d "$BODY")
|
|
fi
|
|
|
|
# Capture start time
|
|
START_TIME=$(date +%s%3N)
|
|
|
|
# Make the request and capture response headers
|
|
TEMP_HEADERS=$(mktemp)
|
|
CURL_ARGS+=(--dump-header "$TEMP_HEADERS")
|
|
|
|
# Execute curl and capture output
|
|
set +e
|
|
RESPONSE=$(curl "${CURL_ARGS[@]}" "$FINAL_URL" 2>&1)
|
|
CURL_EXIT_CODE=$?
|
|
set -e
|
|
|
|
# Calculate elapsed time
|
|
END_TIME=$(date +%s%3N)
|
|
ELAPSED_MS=$((END_TIME - START_TIME))
|
|
|
|
# Parse curl output (last 3 lines are: http_code, time_total, url_effective)
|
|
BODY_OUTPUT=$(echo "$RESPONSE" | head -n -3)
|
|
HTTP_CODE=$(echo "$RESPONSE" | tail -n 3 | head -n 1 | tr -d '\r\n')
|
|
CURL_TIME=$(echo "$RESPONSE" | tail -n 2 | head -n 1 | tr -d '\r\n')
|
|
EFFECTIVE_URL=$(echo "$RESPONSE" | tail -n 1 | tr -d '\r\n')
|
|
|
|
# Ensure HTTP_CODE is numeric, default to 0 if not
|
|
if ! [[ "$HTTP_CODE" =~ ^[0-9]+$ ]]; then
|
|
HTTP_CODE=0
|
|
fi
|
|
|
|
# If curl failed, handle error
|
|
if [ "$CURL_EXIT_CODE" -ne 0 ]; then
|
|
ERROR_MSG="curl failed with exit code $CURL_EXIT_CODE"
|
|
|
|
# Determine specific error
|
|
case $CURL_EXIT_CODE in
|
|
6) ERROR_MSG="Could not resolve host" ;;
|
|
7) ERROR_MSG="Failed to connect to host" ;;
|
|
28) ERROR_MSG="Request timeout" ;;
|
|
35) ERROR_MSG="SSL/TLS connection error" ;;
|
|
52) ERROR_MSG="Empty reply from server" ;;
|
|
56) ERROR_MSG="Failure receiving network data" ;;
|
|
*) ERROR_MSG="curl error code $CURL_EXIT_CODE" ;;
|
|
esac
|
|
|
|
# Output error result as JSON
|
|
jq -n \
|
|
--arg error "$ERROR_MSG" \
|
|
--argjson elapsed "$ELAPSED_MS" \
|
|
--arg url "$FINAL_URL" \
|
|
'{
|
|
status_code: 0,
|
|
headers: {},
|
|
body: "",
|
|
json: null,
|
|
elapsed_ms: $elapsed,
|
|
url: $url,
|
|
success: false,
|
|
error: $error
|
|
}'
|
|
|
|
rm -f "$TEMP_HEADERS"
|
|
exit 1
|
|
fi
|
|
|
|
# Parse response headers into JSON
|
|
HEADERS_JSON="{}"
|
|
if [ -f "$TEMP_HEADERS" ]; then
|
|
# Skip the status line and parse headers
|
|
HEADERS_JSON=$(grep -v "^HTTP/" "$TEMP_HEADERS" | grep ":" | sed 's/\r$//' | jq -R -s -c '
|
|
split("\n") |
|
|
map(select(length > 0)) |
|
|
map(split(": "; "") | select(length > 1) | {key: .[0], value: (.[1:] | join(": "))}) |
|
|
map({(.key): .value}) |
|
|
add // {}
|
|
' || echo '{}')
|
|
rm -f "$TEMP_HEADERS"
|
|
fi
|
|
|
|
# Ensure HEADERS_JSON is valid JSON
|
|
if ! echo "$HEADERS_JSON" | jq empty 2>/dev/null; then
|
|
HEADERS_JSON="{}"
|
|
fi
|
|
|
|
# Determine if successful (2xx status code)
|
|
SUCCESS=false
|
|
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
|
|
SUCCESS=true
|
|
fi
|
|
|
|
# Try to parse body as JSON
|
|
JSON_PARSED="null"
|
|
if [ -n "$BODY_OUTPUT" ] && echo "$BODY_OUTPUT" | jq empty 2>/dev/null; then
|
|
JSON_PARSED=$(echo "$BODY_OUTPUT" | jq -c '.' || echo 'null')
|
|
fi
|
|
|
|
# Output result as JSON
|
|
jq -n \
|
|
--argjson status_code "$HTTP_CODE" \
|
|
--argjson headers "$HEADERS_JSON" \
|
|
--arg body "$BODY_OUTPUT" \
|
|
--argjson json "$JSON_PARSED" \
|
|
--argjson elapsed "$ELAPSED_MS" \
|
|
--arg url "$EFFECTIVE_URL" \
|
|
--argjson success "$SUCCESS" \
|
|
'{
|
|
status_code: $status_code,
|
|
headers: $headers,
|
|
body: $body,
|
|
json: $json,
|
|
elapsed_ms: $elapsed,
|
|
url: $url,
|
|
success: $success
|
|
}'
|
|
|
|
# Exit with success
|
|
exit 0
|