#!/bin/bash # shellcheck disable=SC2034 # false flags nameref params # ============= # Route Methods # ============= # $1: path function get() { [ "$REQUEST_METHOD" != "GET" ] && return 1; all "$1"; } # $1: path function post() { [ "$REQUEST_METHOD" != "POST" ] && return 1; all "$1"; } # $1: path function put() { [ "$REQUEST_METHOD" != "PUT" ] && return 1; all "$1"; } # $1: path function delete() { [ "$REQUEST_METHOD" != "DELETE" ] && return 1; all "$1"; } # $1: path function all() { [ "$routeHandled" -eq 1 ] && return 1; # Reset params params=(); pathMatch "$1" params || return 1; # # if path ooesn't match PATH_INFO: return 1 routeHandled=1; return 0; } function next() { routeHandled=0; } # ================= # Request Functions # ================= # $1: param name function param() { printf '%s\n' "${params[$1]}"; } # $1: param name function hasParam() { [[ -v "params[$1]" ]]; } # ========= # Internals # ========= # $1: path # $2: (nameref) array function pathToArray() { readarray -t "$2" < <(printf '%s\n' "$1" | tr '/' '\n' | grep .); } # $1: route # $2: (nameref) associative array for params function pathMatch() { [ -z ${PATH_INFO+x} ] && return 1; [ -z ${1+x} ] && return 1; local path="$PATH_INFO"; local route="$1"; local pathArr; pathToArray "$path" pathArr; local routeArr; pathToArray "$route" routeArr; # Params associative array local -n routeParams="$2"; # Not a match if pathArr and routeArr have different length [ "${#pathArr[@]}" -ne "${#routeArr[@]}" ] && return 1; for ((i=0; i<${#routeArr[@]}; i++)); do local routeComponent="${routeArr[$i]}"; local pathComponent="${pathArr[$i]}"; # If route component starts with ":" if [[ "$routeComponent" == :* ]]; then routeParams["${routeComponent:1}"]="$pathComponent"; else # Confirm paths match [ "$routeComponent" != "$pathComponent" ] && return 1; fi; done; return 0; } # ======= # Globals # ======= routeHandled=0; declare -A params;