Skip to content

Commit 6af3384

Browse files
committed
core updates
1 parent bb731c5 commit 6af3384

File tree

2 files changed

+71
-13
lines changed

2 files changed

+71
-13
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ not sure
2222
- [x] SSE with pubsub
2323
- [x] form data parsing
2424
- [x] cookie parsing
25-
- [ ] url search param parsing
25+
- [x] url search param parsing
2626
- [ ] database abstraction
2727
- [ ] higher level SSE abstraction
2828
- [ ] bootstrap tool (`create-bs-app`)

core.sh

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env bash
22

33
declare -A HTTP_HEADERS
4+
declare -A QUERY_PARAMS
45
declare -A FORM_DATA
56
declare -A COOKIES
67

@@ -33,20 +34,25 @@ urldecode() {
3334
}
3435

3536
function htmx_page() {
36-
[[ ${HTTP_HEADERS["HX-Request"]} == "true" ]] || cat << EOF
37+
if [[ -z "$NO_STYLES" ]]; then
38+
STYLE_TEXT='<link rel="stylesheet" href="/static/style.css">'
39+
fi
40+
[[ ${HTTP_HEADERS["HX-Request"]} == "true" ]] || [[ "$INTERNAL_REQUEST" == "true" ]] || cat << EOF
3741
<!doctype html>
3842
<html>
3943
<head>
40-
<link rel="stylesheet" href="/static/style.css">
41-
<script src="https://unpkg.com/htmx.org@1.8.6" integrity="sha384-Bj8qm/6B+71E6FQSySofJOUjA/gq330vEqjFx9LakWybUySyI1IQHwPtbTU7bNwx" crossorigin="anonymous"></script>
44+
<meta name="viewport" content="width=device-width, initial-scale=1" />
45+
${STYLE_TEXT}
46+
<script src="https://unpkg.com/htmx.org@1.9.3" integrity="sha384-lVb3Rd/Ca0AxaoZg5sACe8FJKF0tnUgR2Kd7ehUOG5GCcROv5uBIZsOqovBAcWua" crossorigin="anonymous"></script>
4247
<script src="https://unpkg.com/hyperscript.org@0.9.8"></script>
48+
<script src="https://unpkg.com/htmx.org/dist/ext/sse.js"></script>
4349
</head>
4450
<body>
4551
EOF
4652

4753
cat # meow
4854

49-
[[ ${HTTP_HEADERS["HX-Request"]} == "true" ]] || cat << EOF
55+
[[ "$INTERNAL_REQUEST" == "true" ]] || [[ ${HTTP_HEADERS["HX-Request"]} == "true" ]] || [[ ! -z "$HIDE_LOGO" ]] || cat << EOF
5056
<div id="signature">
5157
<a href="https://github.com/cgsdev0/bash-stack" target="_blank">
5258
<svg xmlns="http://www.w3.org/2000/svg" width="224" height="256" viewBox="0 0 224 256"><path fill="#FFF" d="M207.953 52.162L127.317 4.287a30.372 30.372 0 0 0-31.114 0L15.55 52.162A32.165 32.165 0 0 0 0 79.869v95.734a32.165 32.165 0 0 0 15.55 27.691l80.636 47.859a30.388 30.388 0 0 0 31.115 0l80.636-47.859a32.165 32.165 0 0 0 15.566-27.707V79.869a32.165 32.165 0 0 0-15.55-27.707Z"/><path fill="#2F3A3E" d="m208.412 52.277l-80.814-47.98a30.439 30.439 0 0 0-31.184 0l-80.83 47.98A32.236 32.236 0 0 0 0 80.045v95.945a32.236 32.236 0 0 0 15.584 27.752l80.814 47.964a30.455 30.455 0 0 0 31.183 0l80.814-47.964a32.236 32.236 0 0 0 15.6-27.769V80.045a32.236 32.236 0 0 0-15.583-27.768ZM99.23 246.803l-80.814-47.964A26.604 26.604 0 0 1 5.6 175.989V80.046a26.588 26.588 0 0 1 12.816-22.849L99.23 9.216a24.92 24.92 0 0 1 25.536 0l80.749 47.98a26.426 26.426 0 0 1 12.412 18.48c-2.687-5.712-8.723-7.282-15.762-3.236l-76.396 47.316c-9.531 5.551-16.554 11.814-16.57 23.303v94.213c0 6.877 2.767 11.327 7.039 12.638a24.759 24.759 0 0 1-4.24.405a25.034 25.034 0 0 1-12.768-3.512Z"/><path fill="#3AB14A" d="m187.007 185.06l-20.086 12.013a1.47 1.47 0 0 0-.92 1.308v5.28c0 .646.435.904.968.597l20.394-12.4a1.616 1.616 0 0 0 .613-1.615v-4.634c-.016-.598-.484-.856-.969-.55Z"/><path fill="#FFF" d="M144.263 140.832c.646-.323 1.179 0 1.195.92l.064 7.008a12.917 12.917 0 0 1 7.718-.937c.501.13.71.808.517 1.615l-1.534 6.152a2.648 2.648 0 0 1-.694 1.227a1.615 1.615 0 0 1-.404.29a.92.92 0 0 1-.597.098a10.237 10.237 0 0 0-7.444 1.194a9.349 9.349 0 0 0-5.506 8.284c0 3.229 1.615 4.117 7.25 4.214c7.444.13 10.673 3.375 10.754 10.883a26.69 26.69 0 0 1-9.882 20.135l.13 6.878a2.519 2.519 0 0 1-1.18 2.1l-4.068 2.34c-.646.323-1.18 0-1.195-.904v-6.765c-3.488 1.453-7.024 1.792-9.285.888c-.42-.162-.613-.791-.436-1.518l1.47-6.216a2.6 2.6 0 0 1 .726-1.292c.115-.11.246-.203.388-.275a.807.807 0 0 1 .662 0c2.878.78 5.948.392 8.541-1.081a11.173 11.173 0 0 0 6.314-9.688c0-3.488-1.922-4.941-6.459-4.974c-5.861 0-11.303-1.13-11.416-9.688a25.027 25.027 0 0 1 9.462-19.15l-.29-7.04a2.503 2.503 0 0 1 1.178-2.13l4.021-2.568Z"/></svg>
@@ -99,19 +105,60 @@ function publish() {
99105
done
100106
}
101107

108+
# encode result
109+
# can encode the following status codes as unix return codes:
110+
# 200-263
111+
# 300-363
112+
# 400-463
113+
# 500-563
114+
function status_code() {
115+
A=${1:0:1}
116+
B=${1:1:2}
117+
echo $(( ((A - 2) << 6) + B ))
118+
}
119+
120+
function decode_result() {
121+
ENCODED=${1}
122+
printf "%d%02d" $(((ENCODED >> 6) + 2)) $(( ENCODED & 63 ))
123+
}
124+
125+
function component() {
126+
local REQUEST_PATH
127+
REQUEST_PATH="$1"
128+
route_script=`matchRoute "$REQUEST_PATH"`
129+
INTERNAL_REQUEST=true
130+
result=$(source "pages/${route_script}")
131+
echo "$result"
132+
}
133+
134+
export -f status_code
135+
export -f component
102136
export -f debug
103137
export -f subscribe
104138
export -f unsubscribe
105139
export -f publish
106140
export -f htmx_page
107141

142+
readonly URI_REGEX='(/[^?#]*)(\?([^#]*))?'
143+
108144
parseHttpRequest() {
109145
local line
110146

111147
# Read request line
112-
read -r REQUEST_METHOD REQUEST_PATH HTTP_VERSION
148+
read -r REQUEST_METHOD REQUEST_PATH_WITH_PARAMS HTTP_VERSION
113149
HTTP_VERSION="${HTTP_VERSION%%$'\r'}"
114-
debug "$REQUEST_METHOD $REQUEST_PATH $HTTP_VERSION"
150+
debug "$REQUEST_METHOD $REQUEST_PATH_WITH_PARAMS $HTTP_VERSION"
151+
REQUEST_PATH=$([[ "$REQUEST_PATH_WITH_PARAMS" =~ $URI_REGEX ]] && echo "${BASH_REMATCH[1]}")
152+
REQUEST_QUERY=$([[ "$REQUEST_PATH_WITH_PARAMS" =~ $URI_REGEX ]] && echo "${BASH_REMATCH[3]}")
153+
154+
# Parse query parameters
155+
if [[ ! -z "$REQUEST_QUERY" ]]; then
156+
while read -r -d '&' line; do
157+
QUERY_PARAMS["${line%%=*}"]=$(urldecode "${line#*=}")
158+
done << EOF
159+
${REQUEST_QUERY}&
160+
EOF
161+
fi
115162

116163
# Read headers
117164
while IFS= read -r line; do
@@ -124,7 +171,7 @@ parseHttpRequest() {
124171
# Read body
125172
CLEN=${HTTP_HEADERS["Content-Length"]}
126173
[[ "$CLEN" =~ ^[0-9]+$ ]] && \
127-
test $CLEN -gt 0 && read -N $CLEN REQUEST_BODY;
174+
test $CLEN -gt 0 && read -rN $CLEN REQUEST_BODY;
128175
# Parse Form Data
129176
if [[ ! -z "$REQUEST_BODY" ]] && \
130177
[[ ${HTTP_HEADERS["Content-Type"]} == "application/x-www-form-urlencoded" ]]; then
@@ -150,10 +197,12 @@ writeHttpResponse() {
150197

151198
if [[ ! -f "$FILE_PATH" ]]; then
152199
printf "%s\r\n" "HTTP/1.1 404 Not Found"
200+
printf "%s\r\n" "Server: bash lol"
153201
printf "%s\r\n" ""
154202
return
155203
fi
156204
printf "%s\r\n" "HTTP/1.1 200 OK"
205+
printf "%s\r\n" "Server: bash lol"
157206
if [[ "$REQUEST_PATH" == *".css" ]]; then
158207
printf "%s\r\n" "Content-Type: text/css"
159208
else
@@ -167,13 +216,15 @@ writeHttpResponse() {
167216
if [[ -z "$route_script" ]]; then
168217
debug "404 no match found"
169218
printf "%s\r\n" "HTTP/1.1 404 Not Found"
219+
printf "%s\r\n" "Server: bash lol"
170220
printf "%s\r\n" ""
171221
return
172222
fi
173223

174224
if directive_test=$(head -1 "pages/${route_script}"); then
175225
if [[ "$directive_test" == "# sse" ]]; then
176226
printf "%s\r\n" "HTTP/1.1 200 OK"
227+
printf "%s\r\n" "Server: bash lol"
177228
printf "%s\r\n" "Content-Type: text/event-stream"
178229
printf "%s\r\n" ""
179230
source "pages/${route_script}"
@@ -183,18 +234,22 @@ writeHttpResponse() {
183234
fi
184235
fi
185236
result=$(source "pages/${route_script}")
186-
if [[ $? == 0 ]]; then
237+
CODE=$?
238+
if [[ "$CODE" -lt 64 ]]; then
187239
# for i in "${!HTTP_HEADERS[@]}"; do
188240
# debug "%s=%s" "$i" "${HTTP_HEADERS[$i]}"
189241
# done
190242
printf "%s\r\n" "HTTP/1.1 200 OK"
191-
printf "%s\r\n" "Content-Type: text/html"
243+
printf "%s\r\n" "Server: bash lol"
244+
[[ -z $CUSTOM_HEADERS ]] && printf "%s\r\n" "Content-Type: text/html"
192245

193246
[[ -z $CUSTOM_HEADERS ]] && printf "%s\r\n" ""
194247
printf "%s" "$result"
195248
else
196-
printf "%s\r\n" "HTTP/1.1 404 Not Found"
249+
printf "%s\r\n" "HTTP/1.1 $(decode_result $CODE)"
250+
printf "%s\r\n" "Server: bash lol"
197251
printf "%s\r\n" ""
252+
printf "%s" "$result"
198253
fi
199254
}
200255

@@ -235,9 +290,7 @@ matchRoute() {
235290
done
236291
findDynamicRoutes | while IFS= read -r route; do
237292
routeRegex="/${route%.sh}"
238-
# routeRegex="${routeRegex//\//\\/}"
239293
routeRegex="^$(echo "$routeRegex" | sed 's@\[[^]]*\]@[^\/]+@g')$"
240-
# debug "THE REGEX IS '$routeRegex'"
241294
[[ "$sanitized" =~ $routeRegex ]] && echo "$route" && return
242295
done
243296
findCatchAllRoutes | while IFS= read -r route; do
@@ -250,5 +303,10 @@ matchRoute() {
250303
done
251304
}
252305

306+
export -f findPredefinedRoutes
307+
export -f findDynamicRoutes
308+
export -f findCatchAllRoutes
309+
export -f matchRoute
310+
253311
parseHttpRequest
254312
writeHttpResponse

0 commit comments

Comments
 (0)