RetroDECK/developer_toolbox/api_test_client.sh
2025-04-04 12:08:35 -04:00

165 lines
4 KiB
Bash

#!/bin/bash
# Set up paths for named pipes (same as in the server)
rd_api_dir="$HOME/.var/app/net.retrodeck.retrodeck/config/retrodeck/api"
REQUEST_PIPE="$rd_api_dir/retrodeck_api_pipe"
# Function to send a request and get a response
send_request() {
local request="$1"
local timeout="${2:-5}"
# Check if pipes exist
if [[ ! -p "$REQUEST_PIPE" ]]; then
echo "Error: Request pipe does not exist at $REQUEST_PIPE" >&2
echo "Make sure the API server is running." >&2
return 1
fi
# Create a unique request ID
local request_id="client_$(date +%s)_$$"
local response_pipe="$rd_api_dir/response_${request_id}"
# Create response pipe
mkfifo "$response_pipe"
chmod 600 "$response_pipe"
# Add request_id to the JSON if it doesn't have one already
# First, validate JSON and then add the request_id
if ! echo "$request" | jq -e . >/dev/null 2>&1; then
echo "Error: Invalid JSON request: $request" >&2
return 1
fi
if ! echo "$request" | jq -e '.request_id' >/dev/null 2>&1; then
# We need to properly quote the request_id for jq
request=$(echo "$request" | jq --arg rid "$request_id" '. + {request_id: $rid}')
else
request_id=$(echo "$request" | jq -r '.request_id')
fi
# Start reading the response pipe in the background with a timeout
# Use 'cat' instead of 'read' to capture multiline responses
local response
# Write to pipe first, then read from response pipe
echo "$request" > "$REQUEST_PIPE"
response=$(timeout "$timeout" cat "$response_pipe")
# Clean up response pipe
rm -f "$response_pipe"
# Check if we got a response
if [[ -z "$response" ]]; then
echo "Error: No response received within $timeout seconds" >&2
return 1
fi
# Return the response
echo "$response"
}
# Function to display help
show_help() {
echo "Bash API Client"
echo "Usage: $0 [options] [JSON request]"
echo ""
echo "Options:"
echo " -h, --help Show this help message"
echo " -a, --action ACTION API action to perform"
echo " -d, --data DATA Data for the request"
echo " -t, --timeout TIMEOUT Manually-defined timeout for the request (in seconds)"
echo ""
echo "Examples:"
echo " $0 '{\"action\":\"process_data\",\"data\":\"test\"}'"
echo " $0 --action process_data --data \"test data\""
}
# If no arguments, show help
if [[ $# -eq 0 ]]; then
show_help
exit 0
fi
# Parse arguments
ACTION=""
TIMEOUT=5
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
show_help
exit 0
;;
-a|--action)
ACTION="$2"
shift 2
;;
-d|--data)
DATA="$2"
shift 2
;;
-t|--timeout)
TIMEOUT="$2"
shift 2
;;
*)
# Assume it's a JSON string if it starts with {
if [[ "$1" == {* ]]; then
JSON_REQUEST="$1"
else
echo "Unknown option: $1"
show_help
exit 1
fi
shift
;;
esac
done
# If we have a JSON request, use it directly
if [[ -n "$JSON_REQUEST" ]]; then
# Validate JSON
if ! echo "$JSON_REQUEST" | jq . >/dev/null 2>&1; then
echo "Error: Invalid JSON request" >&2
exit 1
fi
# Send the request
echo "sending request: $JSON_REQUEST"
response=$(send_request "$JSON_REQUEST" "$TIMEOUT")
exit_code=$?
# Pretty-print the response
if [[ $exit_code -eq 0 ]]; then
echo "$response" | jq .
fi
exit $exit_code
fi
# Otherwise, build a JSON request from the arguments
if [[ -n "$ACTION" ]]; then
# Create JSON object with proper quoting
JSON_REQUEST=$(jq -n --arg action "$ACTION" '{action: $action}')
# Add data if provided
if [[ -n "$DATA" ]]; then
JSON_REQUEST=$(echo "$JSON_REQUEST" | jq --arg data "$DATA" '. + {data: $data}')
fi
# Send the request
response=$(send_request "$JSON_REQUEST" "$TIMEOUT")
exit_code=$?
# Pretty-print the response
if [[ $exit_code -eq 0 ]]; then
echo "$response" | jq .
fi
exit $exit_code
else
echo "Error: No action specified and no JSON request provided" >&2
show_help
exit 1
fi