Skip to content
Snippets Groups Projects
Select Git revision
  • 14d0bd5bdda6898bb242ac36f601ce2c095ec866
  • master default protected
  • 7771-harden-postgres-backup
  • pgsql-dump-with-snapshots
  • update-colors
  • update-docs-css
  • usb-repair-stick
  • desktop-notification
  • 7000-corrections
  • db-detector
10 results

localdump.sh

Blame
  • http.class.sh 29.76 KiB
    #!/bin/bash
    # ======================================================================
    #
    # REST API CLIENT USING CURL
    #
    # REQUIREMENTS
    # - Bash (Linux or MS Windows i.e with Cygwin)
    # - curl
    # - sha1sum (optional; for export functionality with AUTOFILE only)
    # ----------------------------------------------------------------------
    # License: GPL 3.0
    # Source: <https://git-repo.iml.unibe.ch/iml-open-source/bash-rest-api-client>
    # Docs: <https://os-docs.iml.unibe.ch/bash-rest-api-client/>
    # ----------------------------------------------------------------------
    # (1) source this script
    # (2) enter "http.help" to get a list of available commands
    # ----------------------------------------------------------------------
    # 2020-02-07  v0.2  axel.hahn@iml.unibe.ch  BETABETA
    # 2020-02-12  v0.4  axel.hahn@iml.unibe.ch  Caching
    # 2020-03-02  v0.5  axel.hahn@iml.unibe.ch  a few more response check functions
    # 2021-01-21  v0.6  axel.hahn@iml.unibe.ch  add Content-type in request header
    # 2022-01-11  v0.7  axel.hahn@iml.unibe.ch  fixes using shellcheck
    # 2024-10-09  v0.8  axel.hahn@unibe.ch      add setAuthorization; customize accept header, add custom request headers
    # 2024-10-10  v0.9  axel.hahn@unibe.ch      update docs
    # 2024-10-23  v0.10 axel.hahn@unibe.ch      update help
    # 2024-11-20  v0.11 axel.hahn@unibe.ch      no insecure requests by default; add setInsecure, setCA, addCurlparam
    # ======================================================================
    
      http_cfg__about="Bash REST API client v0.11"
      typeset -i http_cfg__debug=0
      typeset -i http_cfg__cacheTtl=0
      http_cfg__cacheDir=/var/tmp/http-cache
      http_cfg__UA="${http_cfg__about}"
      http_cfg__prjurl="https://git-repo.iml.unibe.ch/iml-open-source/bash-rest-api-client"
      http_cfg__docsurl="https://os-docs.iml.unibe.ch/bash-rest-api-client/"
    
    # --- curl meta infos to collect
    #     see variables in man curl --write-out param
      curlMeta="\
        http_code \
        http_connect \
        local_ip \
        local_port \
        num_connects \
        num_redirects \
        redirect_url \
        remote_ip \
        remote_port \
        size_download \
        size_header \
        size_request \
        size_upload \
        speed_download \
        speed_upload \
        ssl_verify_result \
        time_appconnect \
        time_connect \
        time_namelookup \
        time_pretransfer \
        time_redirect \
        time_starttransfer \
        time_total \
        url_effective \
    "
    
    
    # ----------------------------------------------------------------------
    #
    # functions
    #
    # ----------------------------------------------------------------------
    
      # ......................................................................
      #
      # Write a debug message to STDERR
      # Do no not change the prefix - is is read in inc_functions
      #
      # params  strings  output message
      #
      function http._wd(){
        if [ $http_cfg__debug -gt 0 ]; then
          echo -e "\e[33m# RESTAPI::DEBUG $*\e[0m" >&2
        fi
      }
    
      # ......................................................................
      #
      # Write an error message to STDERR
      # Do no not change the prefix - is is read in inc_functions
      #
      # params  strings  output message
      #
      function http._we(){
        echo -e "\e[31m# RESTAPI::ERROR $*\e[0m" >&2
      }
    
      function http(){
      cat <<EOH
    
    $http_cfg__about
    
    A REST API Client with curl
    
    Enter http.help to show all commands.
    
    EOH
        # $0 is not the current file if we source a script
        # grep "function http.[a-z]" $0 | sort
      }
    
      # ......................................................................
      #
      # Initialize the client
      #
      # Initialize the client for a new request. Call this before any other
      # function. It will reset all variables.
      #
      function http.init(){
        http._wd "${FUNCNAME[0]}()"
        which curl >/dev/null || http.quit
    
        # request vars
    
        http_req__auth=
        http_req__authorization=
        http_req__accept="application/json"
        http_req__headers=()
        http_req__curlparams=()
    
        http_req__body=
        http_req__method=GET
        http_req__url=
        http_req__fullurl=
        http_req__docs=
        http_req__cafile=
        http_req__insecure=
    
        http_req__dataprefix="RESTAPICLIENTMETADATA_$(date +%s)_$$"
        local writevar=
        for myvar in $curlMeta
        do
          writevar="${writevar}|${myvar}:%{${myvar}}"
        done
        http_curl__writeout="\\n${http_req__dataprefix}${writevar}\\n"
    
        # cache
        http_cfg__cacheTtl=0
        http_cfg__cacheFile=
    
        # response
        http_resp__all=
        http_resp__neutral=
        mkdir ${http_cfg__cacheDir} 2>/dev/null
        chmod 777 ${http_cfg__cacheDir} 2>/dev/null
      }
    
      # ......................................................................
      #
      # Execute the request
      #
      # param  string  optional: method; GET|POST|PUT|DELETE|...
      # param  string  optional: full url
      # param  string  optional: request body
      #
      # description:
      #
      #   This function does the following:
      #
      #     1. Check if to use a cache
      #     2. If not cached, make the request
      #     3. If cached, use the cached result
      #
      function http.makeRequest(){
        http._wd "${FUNCNAME[0]}()"
    
        # --- handle optional prams
        if [ $# -ne 0 ]; then
          if echo "$1" | grep -q "^[A-Z]*$"; then
            http.setMethod "$1"
            shift 1
          fi
          http.setUrl "$1"
          http.setBody "$2"
        fi
        # test -z "$1" || http.setFullUrl "$1"
    
        # --- detect caching
        local useCache=0
        local makeRequest=1
        if [ $http_cfg__cacheTtl -gt 0 ] && [ "${http_req__method}" = "GET" ]; then
          useCache=1
          test -z "${http_cfg__cacheFile}" && http_cfg__cacheFile=$(http._genOutfilename "${http_cfg__cacheDir}/AUTOFILE")
          if [ -f "${http_cfg__cacheFile}" ]; then
            http.responseImport "${http_cfg__cacheFile}"
            local iAge; typeset -i iAge
            iAge=$(http.getRequestAge)
            http._wd "INFO: Age of cache is $iAge sec  - vs TTL $http_cfg__cacheTtl sec - file $http_cfg__cacheFile"
            if [ $iAge -gt 0 ] && [ $iAge -lt $http_cfg__cacheTtl ]; then
              http._wd "INFO: Using cache"
              makeRequest=0
            else
              http._wd "INFO: Cache file will be updated after making the request"
              rm -f "${http_cfg__cacheFile}" 2>/dev/null
            fi
          fi
        fi
    
    
        # --- make the request
        if [ $makeRequest -eq 1 ]; then
    
          # build curl parameters
          local curl_params=(
            -s
            -i "${http_req__fullurl}"
            -X "${http_req__method}"
            -A "${http_cfg__UA}" 
          )
          test -n "$http_req__auth"          && curl_params+=( -u "$http_req__auth" )
          test -n "$http_req__authorization" && curl_params+=( -H "Authorization: $http_req__authorization" )
          test -n "$http_req__accept"        && curl_params+=( -H "Accept: $http_req__accept" )
          test -n "$http_req__body"          && curl_params+=( -d "${http_req__body}" )
          test -n "$http_req__insecure"      && curl_params+=( -k )
          test -n "$http_req__cafile"        && curl_params+=( --cacert "$http_req__cafile" )
          curl_params+=( "${http_req__headers[@]}" )
          curl_params+=( "${http_req__curlparams[@]}" )
    
          http._wd "${FUNCNAME[0]}($1) ${http_req__method} ${http_req__fullurl}"
          http._wd "${FUNCNAME[0]}($1) ${curl_params[@]}"
          curl_params+=( -w "${http_curl__writeout}" )
    
          http_resp__all=$( curl "${curl_params[@]}") || http.quit
    
          http._wd "OK - Curl finished the http request ... processing data"
          http_resp__neutral=$(http._fetchAllAndReformat)
          if [ $useCache -eq 1 ]; then
            http._wd "INFO: writing cache ..."
            http.responseExport "${http_cfg__cacheFile}"
          fi
        fi
        http._wd "Request function finished; Code $(http.getStatuscode)"
      }
    
      # ......................................................................
      #
      # Show error message with last return code and quit with this exitcode
      #
      # This function is used to quit the script with a meaningful error message
      # and the exit code of the last command.
      #
      # The message is printed to STDERR and contains the return code.
      # If a documentation URL is known, it is printed as a hint.
      #
      # The exit code is the one of the last command.
      # To prevent the script from exiting when this function is called from a
      # sourced file, the exit is commented out.
      #
      # no params
      #
      function http.quit(){
        rc=$?
        http._wd "${FUNCNAME[0]}()"
        echo >&2
        echo -e "\e[31m# ERROR: command FAILED with rc $rc. \e[0m" >&2
        if [ ! -z "${RestApiDocs}" ]; then
          echo "HINT: see ${RestApiDocs}" >&2
        fi
        # dont make exit in a sourced file
        # exit $rc
      }
    
    
      # ......................................................................
      #
      # Load a config file
      #
      # This function is marked as deprecated.
      # It will be removed in the future.
      #
      # param  string  config file name
      #
      # Sourcing that file will set the following vars
      # - RestApiUser
      # - RestApiPassword
      # - RestApiBaseUrl
      # - RestApiDocs
      #
      # The function will then set the "internal" vars
      # - http_req__auth
      # - http_req__fullurl
      # - http_req__docs
      #
      function http.loadcfg(){
        http._wd "${FUNCNAME[0]}($1) !!! DEPRECATED !!!"
        # reset expected vars from config
        RestApiUser=
        RestApiPassword=
        RestApiBaseUrl=
        RestApiDocs=
    
        # source config file
        . "${1}" || http.quit
    
        # set "internal" vars
        if [ -z "$RestApiPassword" ]; then
          http.setAuth "$RestApiUser:$RestApiPassword"
        else
          http.setAuth
        fi
        http.setBaseUrl "${RestApiBaseUrl}"
        http.setDocs "${RestApiDocs}"
      }
    
      # ======================================================================
      # GETTER
      # ======================================================================
    
      # ......................................................................
      #
      # Get the response header or response body
      #
      # param  string  what to return; one of header|body
      #
      # Return the response header or the response body. The output is the same
      # as that of http.getResponseHeader or http.getResponse. The difference is
      # the implementation
      #
      function http._fetchResponseHeaderOrBody(){
        http._wd "${FUNCNAME[0]}($1)"
        local isheader=true
    
        # keep leading spaces
        IFS=''
    
        echo "${http_resp__all}" | grep -v "${http_req__dataprefix}" | while read -r line; do
          if $isheader; then
            if [[ $line = $'\r' ]]; then
                isheader=false
            else
              test "$1" = "header" && echo $line
            fi
          else
            # body="$body"$'\n'"$line"
            test "$1" = "body" && echo $line
          fi
        done
      }
    
      # ......................................................................
      #
      # Get the response data
      #
      # Return the curl meta infos like http_code, http_connect, local_ip, ...
      # as key/ value pairs. Each line is a single key value pair.
      #
      # The data is extracted from the response header. The format is:
      # ${http_req__dataprefix}|key|value|key|value|...
      #
      function http._fetchResponseData(){
        http._wd "${FUNCNAME[0]}()"
        echo "${http_resp__all}" | sed "s#${http_req__dataprefix}#\n${http_req__dataprefix}#" | grep "${http_req__dataprefix}" | tail -1 | cut -f 2- -d "|" | sed "s#|#\n#g" | grep -v "${http_req__dataprefix}" | while read -r line; do
          echo "$line"
        done
      }
    
      # ......................................................................
      #
      # Generate the dump with request and response
      function http._fetchAllAndReformat(){
        http._wd "${FUNCNAME[0]}()"
        IFS=''
        line="#------------------------------------------------------------"
    
        echo "#_META_|about:$http_cfg__about"
        echo "#_META_|host:$(hostname -f)"
        echo $line
        echo "#_REQUEST_|fullurl:$http_req__fullurl"
        echo "#_REQUEST_|method:$http_req__method"
        echo "#_REQUEST_|time:$(date)"
        echo "#_REQUEST_|timestamp:$(date +%s)"
        echo "#_REQUEST_|auth:$(echo $http_req__auth | sed 's#:.*#:xxxxxxxx#')"
        echo "#_REQUEST_|body:$http_req__body"
        echo "#_REQUEST_|baseurl:$http_req__baseurl"
        echo "#_REQUEST_|url:$http_req__url"
        echo "#_REQUEST_|docs:$http_req__docs"
        echo $line
        http._fetchResponseHeaderOrBody header  | sed "s,^,#_HEADER_|,g"
        echo $line
        http._fetchResponseData                 | sed "s,^,#_DATA_|,g"
        echo $line
        http._fetchResponseHeaderOrBody body    | sed "s,^,#_BODY_|,g"
        echo $line END
      }
    
      # ......................................................................
      #
      # Get a section from dump data
      #
      # param  string  what to return; one of HEADER|DATA|BODY
      #
      # returns string  the requested part of the response
      #
      function http._getFilteredResponse(){
        http._wd "${FUNCNAME[0]}($1)"
        echo "${http_resp__neutral}" | grep "^#_${1}_|"  | cut -f 2- -d "|"
      }
    
      # ---------- PUBLIC REQUEST GETTER
    
      # ......................................................................
      #
      # Get timestamp of the response as a Unix timestamp.
      #
      # no param
      #
      # returns string  the timestamp of the response
      #
      function http.getRequestTs(){
        http._wd "${FUNCNAME[0]}()"
        http._getFilteredResponse REQUEST | grep "^timestamp" | cut -f 2 -d ":"
      }
    
      # ......................................................................
      #
      # Get age of the response in sec.
      # It is especially useful after responseImport
      #
      # no param
      #
      # returns integer  age of the response in sec
      #
      function http.getRequestAge(){
        http._wd "${FUNCNAME[0]}()"
        local iAge; typeset -i iAge
        local iTs; typeset -i iTs
        iTs=$( http.getRequestTs )
        iAge=$( date +%s )-${iTs}
        echo "$iAge"
      }
    
      # ---------- PUBLIC RESPONSE GETTER
    
      # ......................................................................
      #
      # Get response body
      #
      # no param
      #
      # returns string  the response body
      #
      function http.getResponse(){
        http._wd "${FUNCNAME[0]}()"
        http._getFilteredResponse BODY
      }
    
      # ......................................................................
      #
      # Get curl data of this request with status, transferred bytes, speed, ...
      #
      # no param
      #
      # returns string  the response data
      #
      function http.getResponseData(){
        http._wd "${FUNCNAME[0]}()"
        http._getFilteredResponse DATA
      }
    
      # ......................................................................
      #
      # Get response header
      #
      # no param
      #
      # returns string  the response header
      #
      function http.getResponseHeader(){
        http._wd "${FUNCNAME[0]}()"
        http._getFilteredResponse HEADER
      }
    
      # ......................................................................
      #
      # Get raw response (not available after import)
      #
      # no params
      #
      # no param
      #
      function http.getResponseRaw(){
        http._wd "${FUNCNAME[0]}()"
        echo "${http_resp__all}"
      }
    
      # ......................................................................
      #
      # Get Http status as string OK|Redirect|Error
      #
      # no params
      #
      function http.getStatus(){
        http._wd "${FUNCNAME[0]}($1)"
        http.isOk       >/dev/null && echo OK
        http.isRedirect >/dev/null && echo Redirect
        http.isError    >/dev/null && echo Error
      }
    
      # ......................................................................
      #
      # Get Http status code of the request as 3 digit number
      #
      # no params
      #
      function http.getStatuscode(){
        http._wd "${FUNCNAME[0]}()"
        http.getResponseData | grep "^http_code:" | cut -f 2 -d ":"
      }
    
      # ......................................................................
      #
      # Check: was response a 2xx status code?
      # output is a statuscode if it matches ... or empty
      # Additionally you can verify the return code
      #
      # $? -eq 0 means YES
      # $? -ne 0 means NO
      #
      # no params
      #
      function http.isOk(){
        http._wd "${FUNCNAME[0]}()"
        http.getStatuscode | grep '2[0-9][0-9]'
      }
    
      # ......................................................................
      #
      # Was the repsonse a redirect?
      #
      # no params
      #
      function http.isRedirect(){
        http._wd "${FUNCNAME[0]}()"
        http.getStatuscode | grep '3[0-9][0-9]'
      }
    
      # ......................................................................
      #
      # Was the repsonse a client error (4xx or 5xx)
      #
      # no params
      #
      function http.isError(){
        http._wd "${FUNCNAME[0]}()"
        http.getStatuscode | grep '[45][0-9][0-9]'
      }
    
      # ......................................................................
      #
      # Was the repsonse a client error (4xx)
      #
      # no params
      #
      function http.isClientError(){
        http._wd "${FUNCNAME[0]}()"
        http.getStatuscode | grep '4[0-9][0-9]'
      }
    
      # ......................................................................
      #
      # Was the repsonse a client error (5xx)
      #
      # no params
      #
      function http.isServerError(){
        http._wd "${FUNCNAME[0]}()"
        http.getStatuscode | grep '5[0-9][0-9]'
      }
    
      # ......................................................................
      #
      # Dump information about request and response
      #
      # no params
      #
      function http.dump(){
        http._wd "${FUNCNAME[0]}()"
        http.responseExport
      }
    
      # ======================================================================
      # Import/ Export
      # ======================================================================
    
      # ......................................................................
      #
      # Helper to replace "AUTOFILE" with something uniq using full url
      #
      # param  string  import or export filename
      #
      function http._genOutfilename(){
        http._wd "${FUNCNAME[0]}($1)"
        if echo "$1" | grep -q "AUTOFILE"; then
          echo "$1"
        else
          local sum
          sum=$(echo ${http_req__fullurl} | sha1sum )
          local autofile
          autofile=$(echo "${sum}__${http_req__fullurl}" | sed "s#[^a-z0-9]#_#g")
          echo "$1" | sed "s#AUTOFILE#${autofile}#"
        fi
      }
    
      # ......................................................................
      #
      # Export response to a file
      #
      # param  string  optional: custom filename
      #
      function http.responseExport(){
        http._wd "${FUNCNAME[0]}($1)"
        if [ -z "$1" ]; then
          echo "${http_resp__neutral}"
        else
          local outfile
          outfile=$(http._genOutfilename "$1")
          http._wd "${FUNCNAME[0]}($1) writing to outfile $outfile"
          echo "${http_resp__neutral}" >"$outfile"
        fi
      }
    
      # ......................................................................
      #
      # Import a former response from a file
      #
      # param  string  filename with stored response
      #
      function http.responseImport(){
        http._wd "${FUNCNAME[0]}($1)"
        local infile
        infile=$(http._genOutfilename "$1")
        if [ -r "${infile}" ]; then
          if grep -q "^#_META_|about:$http_cfg__about" "${infile}"; then
             http_resp__neutral=$(cat "${infile}")
          else
             echo "ERROR: Ooops [${infile}] does not seem to be an export dump."
             http.quit
          fi
        else
          echo "ERROR: Ooops the file [${infile}] is not readable."
          http.quit
        fi
      }
    
      # ......................................................................
      #
      # Delete an exported file; this is especially useful if you use
      # AUTOFILE functionality
      #
      # param  string  filename with stored response
      #
      function http.responseDelete(){
        http._wd "${FUNCNAME[0]}($1)"
        local infile
        infile=$(http._genOutfilename "$1")
        if [ -r "${infile}" ]; then
          if grep -q "^#_META_|about:$http_cfg__about" "${infile}"; then
            if rm -f "${infile}"; then
              http._wd "OK, ${infile} was deleted."
            else
              http._wd "ERROR: unable to delete existing ${infile}. Check permissions."
            fi
           else
            http._wd "SKIP: ${infile} is not an export file."
          fi
        else
          http._wd "SKIP: ${infile} is not readable."
        fi
      }
    
      # ======================================================================
      # SETTER
      # ======================================================================
    
      # ......................................................................
      #
      # Add a line to the request header
      #
      # param  string  line to add, eg "Connection: keep-alive"
      #
      function http.addHeader(){
        http._wd "${FUNCNAME[0]}($1)"
        http_req__headers+=( -H "$1")
      }
    
      # ......................................................................
      #
      # Add an additional curl parameter
      #
      # param  string  line to add, eg "Connection: keep-alive"
      #
      function http.addCurlparam(){
        http._wd "${FUNCNAME[0]}($1)"
        http_req__curlparams+=( "$1")
      }
    
      # ......................................................................
      #
      # set Accept request header and override default
      #
      # param  string  accept header value, eg text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
      #
      function http.setAccept(){
        http._wd "${FUNCNAME[0]}($1)"
        if [ -z "$1" ]; then
          http_req__accept=
        else
          http_req__accept="$1"
        fi
      }
    
      # ......................................................................
      #
      # Set basic authentication
      # Without given parameter, authentication is removed
      #
      # param  string  optional: USER:PASSWORD
      #
      function http.setAuth(){
        http._wd "${FUNCNAME[0]}($1)"
        if [ -z "$1" ]; then
          http_req__auth=
        else
          http_req__auth="$1"
        fi
      }
    
      # ......................................................................
      #
      # Set authentication via Athorization header
      # Without given parameter, authorization is removed
      #
      # param  string  optional: type, eg. Basic|Bearer|Negotiate
      # param  string  optional: token or encoded user + password
      #
      function http.setAuthorization(){
        http._wd "${FUNCNAME[0]}($1 $2)"
        if [ -z "$1" ]; then
          http_req__authorization=
        else
          http_req__authorization="${1} ${2}"
        fi
      }
    
      # ......................................................................
      #
      # Set body to send for PUTs and POSTs
      #
      # param  string  body
      #
      function http.setBody(){
        http._wd "${FUNCNAME[0]}($1)"
        http_req__body=$1
      }
    
      # ......................................................................
      #
      # Set a base url of an API
      # Remark: Then use http.setUrl to complet the url to request
      #
      # param  string  url
      #
      function http.setBaseUrl(){
        http._wd "${FUNCNAME[0]}($1)"
        http_req__baseurl=$1
        http.setFullUrl ""
      }
    
      # ......................................................................
      #
      # set and unset CA cert file to use
      #
      # param  string  optional: filename to use; no value to disable cafile
      #
      function http.setCA(){
        http._wd "${FUNCNAME[0]}($1)"
        http_req__cafile="$1"
      }
    
      # ......................................................................
      #
      # Enable or disable debug mode
      #
      # param  integer  0|1
      #
      function http.setDebug(){
        http._wd "${FUNCNAME[0]}($1)"
        http_cfg__debug=$1
      }
    
    
      function http.setDocs(){
        http._wd "${FUNCNAME[0]}($1)"
        http_req__docs=$1
      }
      # ......................................................................
      #
      # Allow and disallow insecure connections
      #
      # param  string  optional: 1 to enable insecure flag; no value to disable insecure flag
      #
      function http.setInsecure(){
        http._wd "${FUNCNAME[0]}($1)"
        http_req__insecure="$1"
      }
    
      # ......................................................................
      #
      # Set the method to use; GET|POST|PUT|DELETE|...
      #
      # param  string  name of method
      #
      function http.setMethod(){
        http._wd "${FUNCNAME[0]}($1)"
        http_req__method=$1
      }
    
      # ......................................................................
      #
      # Set a full url to request
      #
      # param  string  optional: url
      #
      function http.setFullUrl(){
        http._wd "${FUNCNAME[0]}($1)"
        if [ -z "$1" ]; then
          http_req__fullurl=${http_req__baseurl}${http_req__url}
        else
          http_req__fullurl=$1
        fi
      }
    
      # ......................................................................
      #
      # Complete the base url
      #
      # param  string  url part behind base url
      #
      function http.setUrl(){
        http._wd "${FUNCNAME[0]}($1)"
        http_req__url=$1
        http.setFullUrl
      }
    
      # ----- caching
    
      # ......................................................................
      #
      # Set cache ttl in seconds
      #
      # param  integer  ttl in seconds
      #
      function http.setCacheTtl(){
        http._wd "${FUNCNAME[0]}($1)"
        http_cfg__cacheTtl=$1
      }
    
      # ......................................................................
      #
      # Set cache file
      #
      # param  string  filename
      #
      function http.setCacheFile(){
        http._wd "${FUNCNAME[0]}($1)"
        http_cfg__cacheFile="$1"
      }
    
      # ......................................................................
      #
      # Flush the cache  
      #
      # no params
      #
      function http.flushCache(){
        http._wd "${FUNCNAME[0]}($1)"
        rm -f ${http_cfg__cacheDir}/*
      }
    
      # ......................................................................
      #
      # show a help text
      #
      # no params
      #
      function http.help(){
        cat <<EOH
    
    $http_cfg__about
    
    This is a bash solution to script REST API calls.
    
    Source: <$http_cfg__prjurl>
    Docs: <$http_cfg__docsurl>
    License: GNU GPL 3
    
    
    INSTRUCTION:
    
    - Source the file once
    - Then you can run functions starting with "http."
    
        http.init
          Start a new request. It resets internal vars of the last request
          (if there was one).
    
        http.setDebug 0|1
          Enable or disable debugging infos during processing. It is written
          to STDERR.
    
    - initialize a request
    
        setAccept "<ACCEPTHEADER>"
          Set authentication with user and password for basic auth
          Default: $http_req__accept
    
        setAuth "<USER>:<PASSWORD>"
          Set authentication with user and password for basic auth
          Without given parameter, authentication is removed
    
        setAuthorization "<TYPE>" "<TOKEN|HASH>"
          Set authentication with Authorization header. 
          As TYPE you can use Basic|Bearer|Negotiate|...
          2nd param is the token or hashed user+password
          Without given parameter, authorization is removed
    
        http.setBody "<DATA>"
          set a body for POST/ PUT requests.
    
        http.setBaseUrl "<URL>"
          Set a base url to an api.
          renmark:
          Use http.setUrl to built a complete url.
    
        http.setCA "<FILE>"
          Set CA file to verify the server certificate. 
          Default: [empty] = use system defaults
          Without parameter the cafile is removed
    
        http.setDocs "<URL>"
          Set a docs url. If set it will be shown as additional hint when a 
          request fails.
    
        http.setInsecure 1
          Set insecure flag by giving any non empty value. 
          Default: [empty] = secure requests
          Without parameter the insecure flag is removed
    
        http.setMethod "<METHOD>"
          Set a http method. Use an uppercase string for GET|POST|PUT|DELETE|...
    
        http.setFullUrl "<URL>"
          Set a complete url for a request.
    
        http.setUrl "<REQUEST?QUERY>"
          Set a relative url for a request.
          This requires to use http.setBaseUrl before.
    
        http.addHeader "<HEADER_LINE>"
          Add a header line to the request.
          This command can be repeated multiple times to add multiple headers.
    
        http.addCurlparam "<CURL_PARAMETER>"
          Add any missing parameter for curl requestst.
          This command can be repeated multiple times to add multiple prameters.
          You also can add multiple parameters with one command.
    
    - caching functions
    
        http.setCacheTtl <SECONDS>
          Enable caching with values > 0
          Remark: only GET requests will be cached.
          Default: 0 (no caching)
    
        http.setCacheFile "<FILENAME>"
          Set a file where to read/ store a request
          Default: empty; autogenerated file below $http_cfg__cacheDir
    
        http.flushCache
          Delete all files in $http_cfg__cacheDir
    
    - make the request
    
        http.makeRequest [[<METHOD>] ["<URL>"] ["<BODY>"]]
          The parameters are optional. Without parameter the request will be
          started with given data in http.set* functions described above.
          If minimum one param is given then they are handled:
            METHOD  optional: set a method (must be uppercase) - see http.setMethod
            URL     set a relative url - see http.setUrl
            BODY    optional: set a body - see http.setBody
    
          The request will be skipped and uses a cached content if ...
            - METHOD is GET
            - http.setCacheTtl set a value > 0
            - the cache file exists and is younger than the given TTL
    
    - handle response
    
          http.getResponse
            Get the Response Body
    
          http.getResponseData
            Get Meta infos from curl
    
          http.getResponseHeader
            Get The http reponse header
    
    - check http status code
    
          http.getStatus
            Get the http status as string Ok|Redirect|Error
    
          http.getStatuscode
            Get the http status code of a request as 3 digit integer
    
          http.isOk
            Check if the http response code is a 2xx
    
          http.isRedirect
            Check if the http response code is a 3xx
    
          http.isError
            Check if the http response code is a 4xx or 5xx
    
          http.isClientError
            Check if the http response code is a 4xx
    
          http.isServerError
            Check if the http response code is a 5xx
    
          http.getRequestAge
            Get the age of the request in seconds.
            Remark: This function is useful after an import
            see http.responseImport.
    
          http.getRequestTs
            Get the Unix timestamp of the request
    
    - import/ export
    
          http.responseExport ["<FILE>"]
            dump the response data
            Without parameter it is written on STDOUT.
            You can set a filename to write it to a file.
            The filename can contain "AUTOFILE" this string
            will be replaced with a uniq string.
            (requires sha1sum and a set url)
            Example:
            http.makeRequest "https://example.com/api/"
            http.responseExport /tmp/something_AUTOFILE_.txt
    
          http.responseImport "<FILE>"
            Import an export file.
            To use the AUTOFILE mechanism from export set
            the url first.
            Example:
            http.setFullUrl "https://example.com/api/"
            http.responseImport /tmp/something_AUTOFILE_.txt
    
          http.responseDelete "<FILE>"
            Delete a file after http.responseExport.
            It is useful if you use the AUTOFILE mechanism.
    
    EOH
      }
    
    # ----------------------------------------------------------------------
    #
    # main
    #
    # ----------------------------------------------------------------------
    
      http.init
    
    # ----------------------------------------------------------------------