An Express-like HTTP router for Bash compatible with CGI 1.1
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
2.0 KiB

#!/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;
routeHandled=1;
return 0;
}
function use() {
[ "$routeHandled" -eq 1 ] && 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;