#!/bin/bash
#< Excercise a webserver by repetitively calling a URL

BASENAME="/bin/basename"
CAT="/bin/cat"
CURL="/usr/bin/curl"
ECHO="/bin/echo"
EGREP="/bin/egrep"
PRINTF="/usr/bin/printf"
RM="/bin/rm"
SED="/bin/sed"
SLEEP="/bin/sleep"
TIME="/usr/bin/time"

THISPROG=$( ${BASENAME} $0 )

VERBOSE=0

function print_error {
   ${ECHO} "Error: $@" >&2
}

function printv {
   (( VERBOSE )) && {
      ${ECHO} "--> $@"
   }
}

function print_usage {
   {
      ${ECHO} "Usage: ${THISPROG} [-hv] -H <host> -I <server> -u <uri> -p <port> -n <num> -d <delay> -t <timeout>"
      ${ECHO} "       -d   Delay (seconds)"
      ${ECHO} "       -h   Display this usage message"
      ${ECHO} "       -n   Number of iterations"
      ${ECHO} "       -p   Port"
      ${ECHO} "       -t   Timeout"
      ${ECHO} "       -u   URI to excercise"
      ${ECHO} "       -v   Verbose mode"
                ${ECHO} "       -H   Hostname to pass as Host header"
                ${ECHO} "       -I   Server to excercise"
   } >&2
}

function check_args {
                ERROR_COUNT=0
                if [ -z "${DELAY}" ]; then 
                        print_error "-d option mandatory"
                        (( ERROR_COUNT = ERROR_COUNT + 1 ))
                fi
                if [ -z "${NUM_ITER}" ]; then 
                        print_error "-n option mandatory"
                        (( ERROR_COUNT = ERROR_COUNT + 1 ))
                fi
                if [ -z "${PORT}" ]; then 
                        print_error "-p option mandatory"
                        (( ERROR_COUNT = ERROR_COUNT + 1 ))
                fi
                if [ -z "${TIMEOUT}" ]; then 
                        print_error "-t option mandatory"
                        (( ERROR_COUNT = ERROR_COUNT + 1 ))
                fi
                if [ -z "${URI}" ]; then 
                        print_error "-u option mandatory"
                        (( ERROR_COUNT = ERROR_COUNT + 1 ))
                fi
                if [ -z "${HTTP_HOST}" ]; then 
                        print_error "-H option mandatory"
                        (( ERROR_COUNT = ERROR_COUNT + 1 ))
                fi
                if [ -z "${SERVER}" ]; then 
                        print_error "-I option mandatory"
                        (( ERROR_COUNT = ERROR_COUNT + 1 ))
                fi
                # Some basic sanity checking
                ${ECHO} "${PORT}" | ${EGREP} -qs '^[0-9]+$'
                if [ "$?" -ne "0" ]; then
                        print_error "Invalid Port Number"
                        (( ERROR_COUNT = ERROR_COUNT + 1 ))
                elif [ "${PORT}" -lt "1" -o "${PORT}" -gt "65535" ]; then
                        print_error "Invalid Port Number"
                        (( ERROR_COUNT = ERROR_COUNT + 1 ))
                fi
                ${ECHO} "${DELAY}" | ${EGREP} -qs '^[0-9]+$'
                if [ "$?" -ne "0" ]; then
                        print_error "Delay out of bounds"
                        (( ERROR_COUNT = ERROR_COUNT + 1 ))
                fi
                ${ECHO} "${NUM_ITER}" | ${EGREP} -qs '^[0-9]+$'
                if [ "$?" -ne "0" ]; then
                        print_error "Iterations out of bounds"
                        (( ERROR_COUNT = ERROR_COUNT + 1 ))
                fi
                ${ECHO} "${TIMEOUT}" | ${EGREP} -qs '^[0-9]+$'
                if [ "$?" -ne "0" ]; then
                        print_error "Timeout out of bounds"
                        (( ERROR_COUNT = ERROR_COUNT + 1 ))
                fi
                if [ "${ERROR_COUNT}" -gt "0" ]; then
                        exit 1
                fi
}

function do_check {
        COUNTER=0
        while [ "${NUM_ITER}" -gt "0" ]; do
                (( COUNTER = COUNTER + 1 ))
                ${TIME} ${CURL} -o /dev/null -w %{http_code} -m ${TIMEOUT} -s -H "Host: ${HTTP_HOST}" http://${SERVER}:${PORT}/${URI} >/tmp/http_code 2>/tmp/time_output
                ELAPSED=$( ${SED} -n 's/^.* \([0-9:.]*\)elapsed.*$/\1/p' /tmp/time_output )
                RETURN=$( ${CAT} /tmp/http_code )
                ${PRINTF} "%5d%20s\t%20s\t%s\n" "${COUNTER}" "${RETURN}" "${ELAPSED}" "${URI}"
                ${RM} /tmp/http_code /tmp/time_output
                ${SLEEP} ${DELAY}
                (( NUM_ITER = NUM_ITER - 1 ))
        done
}

#
# main()
#
while getopts ":d:hn:p:t:u:vH:I:" OPTION; do
        case ${OPTION} in
                "d")  DELAY="${OPTARG}"                 ;;
        "h")  print_usage && exit 0   ;;
                "n")  NUM_ITER="${OPTARG}"              ;;
                "p")  PORT="${OPTARG}"                  ;;
                "t")  TIMEOUT="${OPTARG}"               ;;
                "u")  URI="${OPTARG}"                   ;;
        "v")  VERBOSE=1               ;;
                "H")  HTTP_HOST="${OPTARG}"     ;;
                "I")  SERVER="${OPTARG}"                ;;
        *  )  print_usage && exit 1   ;;
        esac
done

shift $(( ${OPTIND} - 1 ))

if [ "$#" -ne "0" ]; then
   print_usage && exit 1
fi

check_args
do_check

exit 0