Skip to content

Commit 3b5b001

Browse files
committed
fix: address review feedback in gateway demo script
- Replace eval in run_step with inlined call sites for steps 3 and 4, eliminating the risk of command injection from variable expansion - Allow MODEL_CLI_BIN env var to override the binary path - Add early prerequisite checks for the model-cli binary and python3, exiting with a clear error message if either is missing
1 parent 33c2c7b commit 3b5b001

1 file changed

Lines changed: 34 additions & 25 deletions

File tree

demos/gateway/demo.sh

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ set -euo pipefail
1818

1919
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
2020
REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
21-
BIN="${REPO_ROOT}/model-cli/target/release/model-cli"
21+
BIN="${MODEL_CLI_BIN:-${REPO_ROOT}/model-cli/target/release/model-cli}"
2222
GATEWAY_PORT=4000
2323
GATEWAY_URL="http://localhost:${GATEWAY_PORT}"
2424
API_KEY="demo-secret"
@@ -35,6 +35,20 @@ cyan='\033[0;36m'
3535
red='\033[0;31m'
3636
white='\033[0;37m'
3737

38+
# ── prerequisite checks ───────────────────────────────────────────────────────
39+
40+
if [[ ! -x "${BIN}" ]]; then
41+
printf '%sError:%s model-cli binary not found at %s\n' "${red}" "${reset}" "${BIN}" >&2
42+
printf 'Build it with: cargo build --release (in model-cli/)\n' >&2
43+
printf 'Or set MODEL_CLI_BIN=/path/to/model-cli to override.\n' >&2
44+
exit 1
45+
fi
46+
47+
if ! command -v python3 >/dev/null 2>&1; then
48+
printf '%sError:%s python3 is required but not found in PATH.\n' "${red}" "${reset}" >&2
49+
exit 1
50+
fi
51+
3852
# ── helpers ───────────────────────────────────────────────────────────────────
3953

4054
# Simulate typing a command character by character
@@ -49,25 +63,7 @@ typewrite() {
4963
done
5064
}
5165

52-
# Print a fake prompt then type-animate the command, then wait for Enter
53-
# After Enter is pressed the command is actually run.
54-
run_step() {
55-
local description="$1"
56-
local command="$2"
57-
58-
echo
59-
printf '%s# %s%s\n' "${dim}" "$description" "${reset}"
60-
printf '%s%s$%s ' "${bold}" "${green}" "${reset}"
61-
typewrite "$command" 0.035
62-
printf '%s ▌%s' "${dim}" "${reset}" # blinking-cursor illusion
63-
64-
# Wait for Enter
65-
read -r -s _
66-
printf "\r${bold}${green}\$${reset} ${white}%s${reset}\n" "$command"
6766

68-
# Actually run it
69-
eval "$command"
70-
}
7167

7268
# A pause with a brief explanatory comment — no command executed
7369
pause_comment() {
@@ -207,19 +203,32 @@ ok "Gateway listening on http://localhost:${GATEWAY_PORT}"
207203

208204
section "Step 3 — Health check"
209205

210-
run_step \
211-
"The gateway exposes /health — no auth required" \
212-
"curl -s http://localhost:${GATEWAY_PORT}/health | python3 -m json.tool"
206+
echo
207+
printf '%s# The gateway exposes /health — no auth required%s\n' "${dim}" "${reset}"
208+
printf '%s%s$%s ' "${bold}" "${green}" "${reset}"
209+
typewrite "curl -s http://localhost:${GATEWAY_PORT}/health | python3 -m json.tool" 0.035
210+
printf '%s ▌%s' "${dim}" "${reset}"
211+
read -r -s _
212+
printf '\r%s%s$%s %scurl -s http://localhost:%s/health | python3 -m json.tool%s\n' \
213+
"${bold}" "${green}" "${reset}" "${white}" "${GATEWAY_PORT}" "${reset}"
214+
curl -s "http://localhost:${GATEWAY_PORT}/health" | python3 -m json.tool
213215

214216
# ─────────────────────────────────────────────────────────────────────────────
215217
# STEP 4 — list models
216218
# ─────────────────────────────────────────────────────────────────────────────
217219

218220
section "Step 4 — List models (/v1/models)"
219221

220-
run_step \
221-
"OpenAI-compatible model list — clients see gateway aliases, not backend details" \
222-
"curl -s http://localhost:${GATEWAY_PORT}/v1/models -H 'Authorization: Bearer ${API_KEY}' | python3 -m json.tool"
222+
echo
223+
printf '%s# OpenAI-compatible model list — clients see gateway aliases, not backend details%s\n' "${dim}" "${reset}"
224+
printf '%s%s$%s ' "${bold}" "${green}" "${reset}"
225+
typewrite "curl -s http://localhost:${GATEWAY_PORT}/v1/models -H 'Authorization: Bearer ${API_KEY}' | python3 -m json.tool" 0.035
226+
printf '%s ▌%s' "${dim}" "${reset}"
227+
read -r -s _
228+
printf '\r%s%s$%s %scurl -s http://localhost:%s/v1/models -H '\''Authorization: Bearer %s'\'' | python3 -m json.tool%s\n' \
229+
"${bold}" "${green}" "${reset}" "${white}" "${GATEWAY_PORT}" "${API_KEY}" "${reset}"
230+
curl -s "http://localhost:${GATEWAY_PORT}/v1/models" \
231+
-H "Authorization: Bearer ${API_KEY}" | python3 -m json.tool
223232

224233
# ─────────────────────────────────────────────────────────────────────────────
225234
# STEP 5 — auth rejection

0 commit comments

Comments
 (0)