Skip to content
Snippets Groups Projects
check_http 7.42 KiB
#!/bin/bash
# ================================================================================
#
# CHECK HTTP
#
# Check http request to an url with given method.
# The response header and 
#
# -------------------------------------------------------------------------------
# 2023-09-06  v1.0  <axel.hahn@unibe.ch>
# ================================================================================

. $( dirname $0 )/inc_pluginfunctions

export self_APPVERSION=1.0

# ----------------------------------------------------------------------
# FUNCTIONS
# ----------------------------------------------------------------------

# show help text
function showHelp(){
    local _self; _self=$(basename $0)
cat <<EOF
$( ph.showImlHelpHeader )

Makes an http request with a given method.
Additionally you can verify the response by
- http status code
- content in http response header
- content in http response body
- content that is NOT in http response body

SYNTAX:
  $_self [-h]
  $_self [-m METHOD] -u URL [-c PARAMS]\\
      [-j FILTER] \\ 
      [-s STATUSCODE] \\
      [-b REGEX] [-n REGEX] [-r REGEX] \\
      [-l LABEL]

OPTIONS:

  -h               this help

PARAMETERS:

  Define request:
  -u URL           Set url to fetch; eg. https://www.example.com/
  -m METHOD        Set a method, eg. HEAD; default: GET
  -c PARAMS        additional curl params; curl will be executed 
                   with '[PARAMS] -si -X [METHOD] --connect-timeout 10 [URL]'

  Filtering:
  -j JQ-FILTER     for JSON Response: filter response body by jq

  What to check:
  -s STATUSCODE    exact Statuscode to check; 3 digits; by default critical
                   is a statuscode greater equal 400
  -r REGEX         Regex must match in http response header
  -b REGEX         Regex must match in response body
  -n REGEX         Regex must NOT match in response body

  Output:
  -l LABEL         set a custom label; default: METHOD + URL eg.
                   "GET https://example.com/status (200)"

EXAMPLES:

  $_self -u https://www.example.com/
                   Check if GET request to url responds with 200..3xx status. 

  $_self -m HEAD -u https://www.example.com/
                   Check if HEAD request to url responds with 200..3xx status

  $_self -u [URL] -s 403
                   Check if the GET request to url has a wanted status code.
                   You can verify if a protected url is not accessible.

  $_self -u [URL] -b "contact"
                   Check if the GET request to url responds with 200..3xx 
                   status and the response body contains "contact".

  $_self -u [URL] -n "error occured"
                   Check if the GET request to url responds with 200..3xx 
                   status and the response body NOT contains "error occured".

  $_self -u [URL] -s 200 -b -b "contact" -n "error occured"
                   Combine code, a matching search and a non matching one.

EOF
}

# ----------------------------------------------------------------------
# MAIN
# ----------------------------------------------------------------------

ph.hasParamoption "h" "$@"; bOptHelp=$?

if [ $bOptHelp -eq 0 -o $# -eq 0 ]; then
    showHelp
    exit 0
fi

ph.require "curl"

sUrl=$(          ph.getValueWithParam ''    u "$@")
sMethod=$(       ph.getValueWithParam 'GET' m "$@" | tr [:lower:] [:upper:])
curlParams=$(    ph.getValueWithParam ''    c "$@")

iStatus=$(       ph.getValueWithParam ''    s "$@")
sHeader=$(       ph.getValueWithParam ''    r "$@")
sBody=$(         ph.getValueWithParam ''    b "$@")
sNotInBody=$(    ph.getValueWithParam ''    n "$@")
sJq=$(           ph.getValueWithParam ''    j "$@")
sLabel=$(        ph.getValueWithParam ""    l "$@")

curlParams+=" -si -X $sMethod --connect-timeout 10"
sProblems=
sInfos=
sOK=

if [ -z "$sUrl" ]; then
    ph.setStatus unknown
    ph.status "Wrong parameters - no url was given."
    ph.exit
fi

out=$( curl $curlParams "$sUrl" )
if [ -z "$out" ]; then
    ph.setStatus critical
    sProblems+="- Url [${sUrl}] not reachable - response is empty;\n"
    iHttpStatus='???'
else
    iHeaderEnd=$( echo "$out" | grep -n ^$'\r' | cut -f 1 -d ':' | head -1 )

    _header=$(echo "$out" | sed -n "1,${iHeaderEnd}p")
    _body=$(  echo "$out" | sed -n "${iHeaderEnd},\$p")

    # --- jq filter
    if [ -n "$sJq" ]; then
        _body=$( jq "$sJq" <<< "$_body" 2>/dev/null )
        if [ -z "$_body" ]; then
            ph.setStatus critical
            sProblems+="- jq filter [$sJq] was applied and resulted in an empty result. The reponse from url was no JSON.\n"
        else
            if [ "$_body" = "null" ]; then
                ph.setStatus critical
                sProblems+="- jq filter [$sJq] does not match on responded JSON\n"
            else
                sOK+="- jq filter [$sJq] matches\n"
                sInfos+="Content after jq filter: ${_body}"
            fi
        fi
    fi

    # --- test status
    typeset -i iHttpStatus
    iHttpStatus=$( grep -i "^HTTP/[0-9\.]* " <<< "${_header}" | awk '{ print $2 }')

    if [ -n "$iStatus" ]; then
        # if ! grep -i "^HTTP/[0-9\.]* ${iStatus}" <<< "${_header}" >/dev/null; then
        if [ "$iHttpStatus" != "$iStatus" ]; then
            ph.setStatus critical
            sProblems+="- Http status is not [${iStatus}] but [${iHttpStatus}]\n"
        else
            sOK+="- Http status is [${iStatus}]\n"
        fi
    else
        if [ $iHttpStatus -ge 400 ]; then
            ph.setStatus critical
            sProblems+="- Http status is an http error [${iHttpStatus}]\n"
        elif [ $iHttpStatus -ge 300 ]; then
            sOK+="- Http status is a 3xx redirect [${iHttpStatus}]\n"
        else
            sOK+="- Http status is a 2xx OK [${iHttpStatus}]\n"
        fi
    fi

    # --- search in http response header
    if [ -n "$sHeader" ]; then
        if ! grep -iE "$sHeader" <<< "${_header}" >/dev/null; then
            ph.setStatus critical
            sProblems+="- Header does not contain [${sHeader}]\n"
        else
            sOK+="- [${sHeader}] was found in header\n"
        fi    
    fi
    # --- search in http response header
    if [ -n "$sNotInHeader" ]; then
        if grep -iE "$sNotInHeader" <<< "${_header}" >/dev/null; then
            ph.setStatus critical
            sProblems+="- Header does contain unwanted [${sNotInHeader}]\n"
        else
            sOK+="- [${sNotInHeader}] was not found in header\n"
        fi
    fi

    # --- search in http response body
    if [ -n "$sBody" ]; then
        if ! grep -iE "$sBody" <<< "${_body}" >/dev/null; then
            ph.setStatus critical
            sProblems+="- Body does not contain [${sBody}]\n"
        else
            sOK+="- [${sBody}] was found in body\n"
        fi
        
    fi
    if [ -n "$sNotInBody" ]; then
        if grep -iE "$sNotInBody" <<< "${_body}" >/dev/null; then
            ph.setStatus critical
            sProblems+="- Body contains unwanted [${sNotInBody}]\n"
        else
            sOK+="- [${sNotInBody}] was not found in body\n"
        fi
        
    fi

fi

# --- output
test -n "$sProblems" && sProblems="Problems:\n$sProblems\n"
test -n "$sOK"       && sOK="Found:\n$sOK"
test -n "$sInfos"    && sInfos="\nHints:\n$sInfos"

test -n "$sLabel" && ( 
    ph.status "$sLabel" 
    echo "$sMethod $sUrl ($iHttpStatus)"
)
test -n "$sLabel" || ph.status "$sMethod $sUrl ($iHttpStatus)"

echo
echo -e "${sProblems}${sOK}${sInfos}"

test -n "${sProblems}" && (echo "RESPONSE HEADER:"; echo; echo "$_header")

ph.exit

# ----------------------------------------------------------------------