aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xrest-run259
1 files changed, 259 insertions, 0 deletions
diff --git a/rest-run b/rest-run
new file mode 100755
index 0000000..2a682ca
--- /dev/null
+++ b/rest-run
@@ -0,0 +1,259 @@
+#!/bin/bash
+
+# me=$(basename $0)
+me=rest-run
+
+# [ Helper functions
+
+print-help () {
+ echo "$me - call REST APIs like a goat of the pest, JJ's style"
+ echo
+ cat <<HELP
+Usage:
+ cat /tmp/body.json | $me http://localhost:8080/api/path --body stdin
+ $me PUT http://localhost:8080/api/resource
+
+Positional arguments:
+ You must provide the API URL. An HTTP verb preceding it is accepted if present.
+
+Options:
+ -b|--body Request body source, must be one of the following options:
+ default - create a request body using the default editor
+ last - use the last request
+ history - pick from the request history
+ stdin - reads from piped input
+ -r|--response Request response handling, must be one of the following options:
+ default - store the request on cache
+ last - read last request, skip request
+ history - pick from the response history, skip request
+ -ne|--no-edit Skip request editting. Ignored when --body is set to default
+ -h|--header Header string. Ex: "Authorization: Bearer 123"
+ -p|--paginate Paginate request response
+
+rest-run parses your request body with a simple template engine called esh.
+You can embed shell scripts/commands in your request file surrouning it
+with <% my-command %>
+
+Example:
+ echo '{
+ "created_at": "<% date +"%FT%T.000Z" %>"
+ }'
+HELP
+}
+
+fail () {
+ echo "$1
+" >&2
+ print-help
+ exit 1
+}
+
+opt-fail () {
+ fail "Argument for $1 is missing"
+}
+
+opt-validation-fail () {
+ fail "Value for option $1 is invalid"
+}
+
+extract-url-domain () {
+ echo "$1" | sed 's/[a-z]*:\/\///g' | sed 's/\/.*//g' | sed 's/\?.*//g'
+}
+
+remove-newlines-from-templates () {
+ sed 's/%>/ | xargs echo -n %>/g'
+}
+
+# ] <- end helper functions
+
+# [ Check installed dependencies
+
+if ! command -v http > /dev/null; then
+ fail "You need HTTPie Client installed."
+fi
+
+if ! command -v ranger > /dev/null; then
+ fail "You need Ranger File Manager installed."
+fi
+
+if ! command -v sha1sum > /dev/null; then
+ fail "You need sha1sum command installed"
+fi
+
+if ! command -v esh > /dev/null; then
+ fail "You need esh template engine installed."
+fi
+
+# ]
+
+# [ Variable and script parameter definition
+
+CACHE_DIR="$HOME/.cache/rest-run/"
+CACHE_DIR_CONTEXT="$CACHE_DIR"
+
+PARAMS=""
+
+rest_request_file=""
+rest_response_file=""
+rest_url=""
+rest_method="POST"
+rest_body="default"
+rest_body_options=("default" "last" "stdin" "history")
+rest_response="default"
+rest_response_options=("default" "history" "last")
+last_request_file=""
+last_request_file_checksum=""
+is_new_request=true
+edit_rest_request=true
+paginate_response=false
+ignore_body=false
+declare -a rest_headers=()
+
+# ] <- end variable definition
+
+# [ Arg parsing
+
+while (( "$#" )); do
+ case "$1" in
+ -ne|--no-edit) edit_rest_request=false && shift;;
+ -p|--paginate) paginate_response=true && shift;;
+ --help) print-help && exit;;
+ -b|--body) [[ -n "$2" && ${2:0:1} != "-" ]] && rest_body=$2 && shift 2 || opt-fail $1 ;;
+ -r|--response) [[ -n "$2" && ${2:0:1} != "-" ]] && rest_response=$2 && shift 2 || opt-fail $1 ;;
+ -h|--header) [[ -n "$2" && ${2:0:1} != "-" ]] && rest_headers+=("$2") && shift 2 || opt-fail $1 ;;
+ -*|--*=) fail "Unkown option $1" ;;
+ *) PARAMS="$PARAMS $1" && shift ;;
+ esac
+done
+
+eval set -- "$PARAMS"
+
+IFS=' ' read -r -a ARGS <<< "$PARAMS"
+
+# ] <- end arg parsing
+
+# [ Arg validation
+
+! [[ " ${rest_body_options[*]} " =~ "$rest_body" ]] && opt-validation-fail "-b|--body"
+! [[ " ${rest_response_options[*]} " =~ "$rest_response" ]] && opt-validation-fail "-r|--response"
+
+if [[ ${#ARGS[@]} -gt 1 ]]; then
+ rest_method="${ARGS[0]}"
+ case "$rest_method" in
+ POST|post);;
+ GET|get);;
+ PUT|put);;
+ PATCH|patch);;
+ DELETE|delete);;
+ *) fail "Invalid HTTP Verb $rest_method" ;;
+ esac
+ unset 'ARGS[0]'
+fi
+
+[[ -z "$PARAMS" || "${#PARAMS}" = "1" ]] && fail "Not enough params"
+
+rest_url="${ARGS[*]}"
+CACHE_DIR_CONTEXT="${CACHE_DIR_CONTEXT}$(extract-url-domain "$rest_url")"
+CACHE_DIR_CONTEXT_RESPONSE="${CACHE_DIR_CONTEXT}/response"
+CACHE_DIR_CONTEXT_REQUEST="${CACHE_DIR_CONTEXT}/request"
+
+mkdir -p "$CACHE_DIR_CONTEXT_RESPONSE" > /dev/null
+mkdir -p "$CACHE_DIR_CONTEXT_REQUEST" > /dev/null
+
+rest_timestamp="$(date +"%s")"
+rest_request_file="$CACHE_DIR_CONTEXT_REQUEST/request-$rest_timestamp.json"
+last_request_file="$(find "$CACHE_DIR_CONTEXT_REQUEST" -type f | sort -n | tail -1)"
+rest_response_file="$CACHE_DIR_CONTEXT_RESPONSE/response-$rest_timestamp.log"
+
+if ! [[ -z "$last_request_file" || "${#last_request_file}" = "0" ]]; then
+ last_request_file_checksum="$(cat "$last_request_file" | sha1sum | awk '{print $1}')"
+fi
+
+if [[ "$rest_method" = "GET" || "$rest_method" = "get" ]]; then
+ ignore_body=true
+fi
+
+# ] <- end arg validation
+
+# [ rest-run!
+
+case "$rest_response" in
+ last)
+ [ $paginate_response = true ] \
+ && find "$CACHE_DIR_CONTEXT_RESPONSE" | sort -n | tail -1 | xargs less -r -f \
+ || find "$CACHE_DIR_CONTEXT_RESPONSE" | sort -n | tail -1 | xargs cat
+ exit
+ ;;
+ history)
+ tmp_file="/tmp/choose-file-$$"
+ ranger --choosefile "$tmp_file" "$CACHE_DIR_CONTEXT_RESPONSE"
+ [[ "$(cat "$tmp_file" 2> /dev/null)" = "" ]] && fail "No file selected"
+ [ $paginate_response = true ] \
+ && cat "$(cat "$tmp_file")" | less -r -f \
+ || cat "$(cat "$tmp_file")"
+ rm "$tmp_file"
+ exit
+ ;;
+esac
+
+if [ $ignore_body = false ]; then
+ case "$rest_body" in
+ last)
+ [[ -z "$last_request_file" || "${#last_request_file}" = "0" ]] && fail "No requests previously made"
+ cp "$(find "$CACHE_DIR_CONTEXT_REQUEST" | sort -n | tail -1)" "$rest_request_file"
+ ;;
+ history)
+ [[ -z "$last_request_file" || "${#last_request_file}" = "0" ]] && fail "No requests previously made"
+ tmp_file="/tmp/choose-file-$$"
+ ranger --choosefile "$tmp_file" "$CACHE_DIR_CONTEXT_REQUEST"
+ [[ "$(cat "$tmp_file" 2> /dev/null)" = "" ]] && fail "No file selected"
+ cp "$(cat "$tmp_file")" "$rest_request_file"
+ rm "$tmp_file"
+ ;;
+ stdin)
+ cat - > "$rest_request_file"
+ ;;
+ esac
+
+ if [[ $edit_rest_request = true || "$rest_body" = "default" ]]; then
+ $EDITOR "$rest_request_file"
+ fi
+
+fi
+
+if [ $ignore_body = false ]; then # Send request body
+
+ if [ $paginate_response = true ]; then
+ cat "$rest_request_file" \
+ | remove-newlines-from-templates \
+ | esh - \
+ | eval -- http --pretty=all -p HBhbm \
+ "$rest_method" \"$rest_url\" $(for h in "${rest_headers[@]}"; do echo \"$h\"; done) > "$rest_response_file"
+ less -r -f "$rest_response_file"
+ else
+ cat "$rest_request_file" \
+ | remove-newlines-from-templates \
+ | esh - \
+ | eval -- http -p HBhbm \
+ "$rest_method" \"$rest_url\" $(for h in "${rest_headers[@]}"; do echo \"$h\"; done)
+ fi
+
+ current_request_checksum="$(cat "$rest_request_file" | sha1sum | awk '{print $1}')"
+ if [[ "${#current_request_checksum}" != "0" && "${#current_request_checksum}" != "1" ]]; then
+ if [[ "$current_request_checksum" = "$last_request_file_checksum" ]]; then
+ rm "$rest_request_file"
+ fi
+ fi
+
+else # Send request without body
+
+ if [ $paginate_response = true ]; then
+ eval -- http --pretty=all -p HBhbm "$rest_method" \"$rest_url\" $(for h in "${rest_headers[@]}"; do echo \"$h\"; done) > "$rest_response_file"
+ less -r -f "$rest_response_file"
+ else
+ eval -- http -p HBhbm "$rest_method" \"$rest_url\" $(for h in "${rest_headers[@]}"; do echo \"$h\"; done) > "$rest_response_file"
+ fi
+
+fi
+
+# ] <- script end