Added body/query parser, status and redirect

This commit is contained in:
Ben Ashton 2022-10-13 20:31:24 -06:00
parent 49c111a867
commit 45b7186e0c

View File

@ -59,7 +59,7 @@ function all() {
# Reset params # Reset params
_exprashParams=(); _exprashParams=();
pathMatch "$1" _exprashParams || return 1; _pathMatch "$1" _exprashParams || return 1;
_exprashRouteHandled=1; _exprashRouteHandled=1;
return 0; return 0;
@ -109,7 +109,7 @@ function allError() {
# Reset params # Reset params
_exprashParams=(); _exprashParams=();
pathMatch "$1" _exprashParams || return 1; _pathMatch "$1" _exprashParams || return 1;
_exprashRouteHandled=1; _exprashRouteHandled=1;
return 0; return 0;
@ -158,6 +158,41 @@ function hasParam() {
[[ -v "_exprashParams[$1]" ]]; [[ -v "_exprashParams[$1]" ]];
} }
# $1: key
# $2: (optional) index for accessing array parameters
function queryGet() {
_multiGet _exprashQuery "$1" "$2"
}
# $1: key
function queryHas() {
_multiHas _exprashQuery "$1"
}
# $1: key
function queryLen() {
_multiLen _exprashQuery "$1"
}
# $1: key
# $2: (optional) index for accessing array parameters
function bodyGet() {
_multiGet _exprashBody "$1" "$2"
}
# $1: key
function bodyHas() {
_multiHas _exprashBody "$1"
}
# $1: key
function bodyLen() {
_multiLen _exprashBody "$1"
}
# Call this function to parse URLencoded request bodies
function bodyParser() {
if [[ "${HTTP_CONTENT_TYPE,,}" == "application/x-www-form-urlencoded" ]]; then
_parseUrlEncoded _exprashBody
fi
}
# ================== # ==================
# Response Functions # Response Functions
# ================== # ==================
@ -168,29 +203,46 @@ function send() {
_exprashHeadersSent=1 _exprashHeadersSent=1
fi fi
sendRaw _sendRaw
}
# $1: Path
function redirect() {
local path="$1"
if [ "$path" == 'back' ]; then
path="${HTTP_REFERER:-/}"
fi
status '302'
setHeader 'Location' "$path"
printf 'Redirecting to: %s' "$path" | send
}
# $1: satus code
function status() {
setHeader "Status" "$1"
} }
# $1: Header Name # $1: Header Name
# $2: Header Value # $2: Header Value
function setHeader() { function setHeader() {
_exprashHeaders["$1"]="$2"; _exprashHeaders["$1"]="$2"
} }
function sendHeaders() { function sendHeaders() {
printf '%s\n' "Content-Type: ${_exprashHeaders['Content-Type']}" | sendRaw printf '%s\n' "Content-Type: ${_exprashHeaders['Content-Type']}" | _sendRaw
for key in "${!_exprashHeaders[@]}"; do for key in "${!_exprashHeaders[@]}"; do
[ "$key" == 'Content-Type' ] && continue [ "$key" == 'Content-Type' ] && continue
printf '%s\n' "${key}: ${_exprashHeaders[$key]}" | sendRaw printf '%s\n' "${key}: ${_exprashHeaders[$key]}" | _sendRaw
done; done;
printf '\n' | sendRaw printf '\n' | _sendRaw
} }
# ========= # =========
# Internals # Internals
# ========= # =========
function sendRaw() { function _sendRaw() {
[ -n "$_exprashRedirectStdout" ] && exec >&5; [ -n "$_exprashRedirectStdout" ] && exec >&5;
cat; cat;
[ -n "$_exprashRedirectStdout" ] && exec 1>>"$_exprashRedirectStdout"; [ -n "$_exprashRedirectStdout" ] && exec 1>>"$_exprashRedirectStdout";
@ -198,13 +250,13 @@ function sendRaw() {
# $1: path # $1: path
# $2: (nameref) array # $2: (nameref) array
function pathToArray() { function _pathToArray() {
readarray -t "$2" < <(printf '%s\n' "$1" | tr '/' '\n' | grep .); readarray -t "$2" < <(printf '%s\n' "$1" | tr '/' '\n' | grep .);
} }
# $1: route # $1: route
# $2: (nameref) associative array for params # $2: (nameref) associative array for params
function pathMatch() { function _pathMatch() {
[ -z ${PATH_INFO+x} ] && return 1; [ -z ${PATH_INFO+x} ] && return 1;
[ -z ${1+x} ] && return 1; [ -z ${1+x} ] && return 1;
@ -215,10 +267,10 @@ function pathMatch() {
local -n routeParams="$2"; local -n routeParams="$2";
local pathArr; local pathArr;
pathToArray "$path" pathArr; _pathToArray "$path" pathArr;
local routeArr; local routeArr;
pathToArray "$route" routeArr; _pathToArray "$route" routeArr;
# Get max path length # Get max path length
local routeLen=${#routeArr[@]}; local routeLen=${#routeArr[@]};
@ -245,21 +297,117 @@ function pathMatch() {
return 0; return 0;
} }
# ==================================
# Multi-dimensional Parameter Arrays
# ==================================
# $1: (nameref) associative array
# $2: key
# $3: value
function _multiAdd() {
local -n multiArr="$1"
local key="$2"
local value="$3"
local i=0
while [[ -v "multiArr[$i,$key]" ]]; do
let i++
done
multiArr["$i,$key"]="$value"
}
# $1: (nameref) associative array
# $2: key
function _multiLen() {
local -n multiArr="$1"
local key="$2"
local value="$3"
local i=0
while [[ -v "multiArr[$i,$key]" ]]; do
let i++
done
printf '%s' "$i"
}
# $1: (nameref) associative array
# $2: key
function _multiHas() {
local -n multiArr="$1"
local key="$2"
[[ -v "multiArr[0,$key]" ]]
}
# $1: (nameref) associative array
# $2: key
# $3: index
function _multiGet() {
local -n multiArr="$1"
local key="$2"
local i="${3:-0}";
printf '%s' "${multiArr[$i,$key]}"
}
# ==================
# URL Encoded Parser
# ==================
# $1: urlencoded string
decodeUri () {
local i="${*//+/ }";
echo -e "${i//%/\\x}";
}
# $1: multi associative array
function _parseUrlEncoded() {
local -n parsedArr="$1"
while IFS= read -d '&' -r pair || [ "$pair" ]; do
name=$(decodeUri "${pair%%=*}")
value=$(decodeUri "${pair#*=}")
if [ -n "$name" ]; then
_multiAdd parsedArr "$name" "$value"
fi;
done
}
# ======= # =======
# Globals # Globals
# ======= # =======
# Route globals
function _exprashResetRouteGlobals() {
_exprashRouteHandled=0
_exprashErrorMessage=''
declare -gA _exprashParams
_exprashHeadersSent=0
declare -gA _exprashHeaders
_exprashHeaders['Content-Type']='text/html'
}
_exprashResetRouteGlobals
# Setup globals # Setup globals
_exprashRedirectStdout='' _exprashRedirectStdout=''
# Route Parameters
declare -gA _exprashParams
# Body Parameters
declare -gA _exprashBody
# Query Parameters
declare -gA _exprashQuery
# Headers
declare -gA _exprashHeaders
function _exprashResetRouteGlobals() {
_exprashParams=()
_exprashBody=()
_exprashQuery=()
_exprashHeaders=()
_exprashRouteHandled=0
_exprashErrorMessage=''
_exprashHeadersSent=0
_exprashHeaders['Content-Type']='text/html'
}
# Set up route globals
_exprashResetRouteGlobals
# ==============
# Initialization
# ==============
# Parse query string
_parseUrlEncoded _exprashQuery < <(echo "$QUERY_STRING")