diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..7dc088a --- /dev/null +++ b/.htaccess @@ -0,0 +1 @@ +FallbackResource "demo.sh" diff --git a/base.sh b/base.sh new file mode 100644 index 0000000..fe138e5 --- /dev/null +++ b/base.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +. utils.sh +. uri.sh +. router.sh diff --git a/demo.sh b/demo.sh new file mode 100755 index 0000000..cdf3c31 --- /dev/null +++ b/demo.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +. base.sh + +route GET / index +index() { + endHeaders + + echo "Hello World" +} + +route GET /foo foobar +foobar() { + status 417 + endHeaders + + echo "bar" +} + +route GET /debug debug +debug() { + endHeaders + + echo "$pathInfo" + set +} + +router diff --git a/router.sh b/router.sh new file mode 100644 index 0000000..978de0d --- /dev/null +++ b/router.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +_methods=() +_paths=() +_handlers=() +_routeNo=0 +_404="_default404" + +route() { + _methods+=("$1") + _paths+=("$2") + _handlers+=("$3") + _routeNo=$((_routeNo+1)) +} + +_default404() { + status 404 + endHeaders + echo "File not found" +} + +_matchPaths() { + actual="$1" + search="$2" + + # TODO: add wildcards + test "$actual" = "$search" + return +} + +router() { + for ((i=0; i<$_routeNo; i++ )); do + if test "${_methods[$i]}" != "$REQUEST_METHOD"; then + continue + fi + if _matchPaths "$pathInfo" "${_paths[$i]}"; then + "${_handlers[$i]}" # todo add arguments + return + fi + done + + "$_404" +} diff --git a/uri.sh b/uri.sh new file mode 100644 index 0000000..96591d7 --- /dev/null +++ b/uri.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +urldecode() { + : "${*//+/ }" + echo -e "${_//%/\\x}" +} + +_query() { + tr '&' '\n' | grep -e "^$1=" | cut -d= -f2 | while read d; do + urldecode "$d" + done +} + +query() { + echo "$QUERY_STRING" | _query "$1" +} + +_formData="" + +formData() { + if test -z "$_formData"; then + _formData="$(cat)" + fi + + echo "$_formData" | _query "$1" +} + +pathInfo=$(echo "$REQUEST_URI" | cut -d? -f1) diff --git a/utils.sh b/utils.sh new file mode 100644 index 0000000..23c2980 --- /dev/null +++ b/utils.sh @@ -0,0 +1,88 @@ +#!/bin/bash + +_hasStatus=0 + +status() { + _hasStatus=1 + status="$1" + echo -n "Status: $status " + case "$status" in + 100) echo "Continue" ;; + 101) echo "Switching Protocols" ;; + 102) echo "Processing" ;; + + 200) echo "OK" ;; + 201) echo "Created" ;; + 202) echo "Accepted" ;; + 203) echo "Non-Authoritative Information" ;; + 204) echo "No Content" ;; + 205) echo "Reset Content" ;; + 206) echo "Partial Content" ;; + 207) echo "Multi-Status" ;; + 208) echo "Already Reported" ;; + 226) echo "IM Used" ;; + + 300) echo "Multiple Choices" ;; + 301) echo "Moved Permanently" ;; + 302) echo "Found" ;; + 303) echo "See Other" ;; + 304) echo "Not Modified" ;; + 305) echo "Use Proxy" ;; + 306) echo "Switch Proxy" ;; + 307) echo "Temporary Redirect" ;; + 308) echo "Permanent Redirect" ;; + + 400) echo "Bad Request" ;; + 401) echo "Unauthorized" ;; + 402) echo "Payment Required" ;; + 403) echo "Forbidden" ;; + 404) echo "Not Found" ;; + 405) echo "Method Not Allowed" ;; + 406) echo "Not Acceptable" ;; + 407) echo "Proxy Authentication Required" ;; + 408) echo "Request Timeout" ;; + 409) echo "Conflict" ;; + 410) echo "Gone" ;; + 411) echo "Length Required" ;; + 412) echo "Precondition Failed" ;; + 413) echo "Payload Too Large" ;; + 414) echo "URI Too Long" ;; + 415) echo "Unsupported Media Type" ;; + 416) echo "Range Not Satisfiable" ;; + 417) echo "Expectation Failed" ;; + 418) echo "I\'m a teapot" ;; + 421) echo "Misdirected Request" ;; + 422) echo "Unprocessable Entity" ;; + 423) echo "Locked" ;; + 424) echo "Failed Dependency" ;; + 426) echo "Upgrade Required" ;; + 428) echo "Precondition Required" ;; + 429) echo "Too Many Requests" ;; + 431) echo "Request Header Fields Too Large" ;; + 451) echo "Unavailable For Legal Reasons" ;; + + 500) echo "Internal Server Error" ;; + 501) echo "Not Implemented" ;; + 502) echo "Bad Gateway" ;; + 503) echo "Service Unavailable" ;; + 504) echo "Gateway Timeout" ;; + 505) echo "HTTP Version Not Supported" ;; + 506) echo "Variant Also Negotiates" ;; + 507) echo "Insufficient Storage" ;; + 508) echo "Loop Detected" ;; + 510) echo "Not Extended" ;; + 511) echo "Network Authentication Required" ;; + *) echo "Unknown" + esac +} + +header() { + echo "$1: $2" +} + +endHeaders() { + if test "$_hasStatus" = 0; then + status 200 + fi + echo +}