#!/usr/bin/env bash set -euo pipefail ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" cd "$ROOT" umask 077 if [[ -f .env ]]; then # This is a local shell configuration file. Do not use untrusted .env files. set -a # shellcheck disable=SC1091 source .env set +a fi if ! command -v cargo >/dev/null 2>&1 && [[ -x "$HOME/.cargo/bin/cargo" ]]; then export PATH="$HOME/.cargo/bin:$PATH" fi RUSTPROXY_VERSION="$(python3 scripts/version.py)" mode="${1:-run}" if [[ $# -gt 0 ]]; then shift; fi case "$mode" in help|-h|--help) cat <&2; exit 2 ;; esac if [[ "$mode" == "backup" ]]; then exec python3 tools/legacy/backup.py --data-dir "${RUST_PROXY_DATA_DIR:-$ROOT/data}" "$@" fi if ! command -v python3 >/dev/null 2>&1; then printf 'Python 3.10+ is required for source preflight and upgrade safety checks.\n' >&2 exit 127 fi python3 -c 'import sys; sys.exit(0 if sys.version_info >= (3, 10) else "Python 3.10+ is required.")' if [[ "$mode" == "doctor" ]]; then python3 tools/checks/preflight.py printf 'Source layout: OK\n' for tool in cargo rustc cc python3; do printf '%s: ' "$tool" command -v "$tool" || printf 'NOT FOUND\n' done exit 0 fi if [[ "$mode" == "acme" ]]; then exec python3 scripts/runtime/acme_provider.py "$@"; fi if [[ "$mode" == "mock-auth" ]]; then exec python3 tools/dev/mock_auth.py "$@"; fi if [[ "$mode" == "mock" ]]; then exec python3 tools/dev/mock_server.py "$@"; fi python3 tools/checks/preflight.py --repair-known if [[ "$mode" == "repair" ]]; then printf 'Source preflight: OK\n'; exit 0; fi if [[ "$mode" == "test" ]]; then python3 tools/checks/rust_module_contracts.py python3 tools/checks/h3_navigation_0316.py python3 tools/checks/release_0317.py python3 tools/checks/release_0318.py python3 tools/checks/certificate_api_0319.py python3 tools/checks/source_pruning_0317.py python3 tools/checks/system_info_no_subprocess_contracts.py python3 tools/checks/source_module_contracts.py python3 tools/checks/version_contracts.py python3 tools/checks/check_source.py python3 tools/checks/release_smoke.py python3 tools/checks/memory_contracts.py python3 tools/checks/high_traffic_memory_model.py python3 tools/checks/web_server_contracts.py python3 tools/checks/security_contracts.py python3 tools/checks/admin_surface_audit_0310.py python3 tools/checks/security_dependency_contracts.py python3 tools/checks/dependency_upgrade_0312.py if command -v node >/dev/null 2>&1; then node tools/checks/web_service_ui_test.mjs node tools/checks/backend_cache_0297_ui_test.mjs node tools/checks/backend_health_0300_ui_test.mjs node tools/checks/system_info_0301_ui_test.mjs node tools/checks/refresh_0310_ui_test.mjs node tools/checks/dashboard_startup_0310_ui_test.mjs node tools/checks/dashboard_boot_0311_ui_test.mjs node tools/checks/origin_resume_0313_ui_test.mjs node tools/checks/admin_public_origin_0314_sim.mjs node tools/checks/admin_public_origin_0314_config_sim.mjs node tools/checks/admin_panel_config_0314_ui_test.mjs node tools/checks/security_logs_0315_ui_test.mjs node tools/checks/release_0317_ui_test.mjs node tools/checks/release_0318_ui_test.mjs node tools/checks/docker_startup_0318_ui_test.mjs node tools/checks/certificate_api_0319_ui_test.mjs node tools/checks/h3_cache_mobile_0315_test.mjs node tools/checks/panel_cache_http_0310_ui_test.mjs node tools/checks/vhost_origin_errors_0297_ui_test.mjs node tools/checks/www_redirect_ui_test.mjs node tools/checks/vhost_www_ui_test.mjs else printf 'Node.js not found; skipping Web Service UI behavior test.\n' >&2 fi python3 tools/checks/docs_check.py python3 tools/checks/langs_check.py fi if ! command -v cargo >/dev/null 2>&1; then cat >&2 <<'MISSING' Rust/Cargo is not installed or not in PATH. Install the stable Rust toolchain using https://rustup.rs, then open a new terminal. Linux also needs a C compiler/linker (for example: build-essential or gcc). macOS: install the Xcode command line tools. Windows: use WSL2 + Bash. This script does not install system software or run sudo automatically. MISSING exit 127 fi export RUST_PROXY_DATA_DIR="${RUST_PROXY_DATA_DIR:-$ROOT/data}" export RUST_PROXY_PROXY_LISTEN="${RUST_PROXY_PROXY_LISTEN:-127.0.0.1:8080}" export RUST_PROXY_ADMIN_LISTEN="${RUST_PROXY_ADMIN_LISTEN:-127.0.0.1:9090}" if [[ "${RUST_PROXY_TLS:-1}" == "1" ]]; then export RUST_PROXY_TLS_LISTEN="${RUST_PROXY_TLS_LISTEN:-127.0.0.1:8443}" else unset RUST_PROXY_TLS_LISTEN fi export RUST_PROXY_DEMO_LISTEN="${RUST_PROXY_DEMO_LISTEN:-127.0.0.1:9000}" export RUST_LOG="${RUST_LOG:-rust_proxy=info,warn}" export CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$ROOT/target}" if [[ "$CARGO_TARGET_DIR" != /* ]]; then export CARGO_TARGET_DIR="$ROOT/$CARGO_TARGET_DIR"; fi if [[ "$mode" == "fmt" ]]; then exec cargo fmt --all "$@"; fi if [[ ! -f Cargo.lock ]]; then printf 'Resolving dependencies once; creating Cargo.lock (keep it for future builds).\n' >&2 cargo generate-lockfile fi case "$mode" in check) exec cargo check --locked --all-targets "$@" ;; release) exec cargo build --locked --release "$@" ;; esac if [[ "$mode" == "test" ]]; then printf 'Checking all Rust targets before tests...\n' >&2 cargo check --locked --all-targets fi printf "Building RustProxy %s...\n" "$RUSTPROXY_VERSION" >&2 cargo build --locked BIN="$CARGO_TARGET_DIR/debug/rust-proxy" case "$mode" in build) printf 'Binary: %s\n' "$BIN" ;; token) exec "$BIN" token "$@" ;; admin) exec "$BIN" admin "$@" ;; config) exec "$BIN" config "$@" ;; tls) exec "$BIN" tls "$@" ;; test) cargo test --locked --all-targets ;; run) args=(serve) if [[ "${RUST_PROXY_DEMO:-0}" == "1" ]]; then args+=(--demo); fi exec "$BIN" "${args[@]}" "$@" ;; esac