# Sherut The tool you didn't know you wanted. A slow breath of fresh air in the world of ever faster API frameworks. Sherut (שירות - Hebrew for "service") is a lightweight tool that exposes shell commands as HTTP endpoints. It automatically detects your shell, passes request data to your scripts, and even auto-detects content types. > [!WARNING] > Please keep in mind `sherut` meant as an elaborate joke more than anything else. Production use is very much discouraged. ## Installation ```bash cargo build --release ``` The binary will be at `target/release/sherut`. ## Quick Start ```bash # Simple echo endpoint (matches any HTTP method) sherut --route "/hello/:name" 'echo "Hello, :name!"' # Specify HTTP methods sherut --route "GET /api/users/:id" './scripts/get_user.sh :id' # Multiple routes with different methods sherut \ --route "GET /users" 'sqlite3 data.db -json "SELECT * FROM users"' \ --route "GET /users/:id" 'sqlite3 data.db -json "SELECT * FROM users WHERE id=:id" | jq ".[0]"' \ --route "POST /users" './scripts/create_user.sh' ``` ## Features ### HTTP Methods Specify the HTTP method before the path. Supported methods: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`, or `ANY` (default): ```bash # Only handles GET requests sherut --route "GET /users" 'sqlite3 data.db -json "SELECT * FROM users"' # Only handles POST requests sherut --route "POST /users" 'echo "@status: 201"; echo "{\"created\": true}"' # Handles any HTTP method (default when method not specified) sherut --route "/health" 'echo "OK"' sherut --route "ANY /health" 'echo "OK"' # equivalent ``` ### Route Parameters Use `:param` syntax in routes. The same `:param` placeholders can be used in commands: ```bash sherut --route "/users/:id/posts/:postId" 'echo "User :id, Post :postId"' ``` ### Query String Parameters Access query parameters via the `QUERY` associative array (bash/zsh) or `QUERY_JSON` environment variable: ```bash # GET /search?q=hello&limit=10 # Bash/Zsh (assoc array) sherut --route "/search" 'echo "Query: ${QUERY[q]}, Limit: ${QUERY[limit]}"' # Any shell (JSON) sherut --query-format json --route "/search" 'echo $QUERY_JSON | jq -r .q' ``` ### HTTP Headers Access request headers via the `HEADERS` associative array or `HEADERS_JSON` environment variable: ```bash # Bash/Zsh sherut --route "/auth" 'echo "Token: ${HEADERS[authorization]}"' # JSON format sherut --header-format json --route "/auth" 'echo $HEADERS_JSON | jq -r .authorization' ``` ### Request Body The request body is passed to your command via **stdin**, following Unix conventions: ```bash # Echo the raw body back sherut --route "POST /echo" 'cat' # Parse JSON body with jq sherut --route "POST /users" 'jq -r .name | xargs -I{} echo "Hello, {}!"' # Process and store sherut --route "POST /data" 'cat > /tmp/received.json && echo "Saved!"' # Validate JSON and extract fields sherut --route "POST /api/items" ' name=$(jq -r .name) price=$(jq -r .price) sqlite3 data.db "INSERT INTO items (name, price) VALUES (\"$name\", $price)" echo "{\"created\": true}" ' ``` ### Response Control Control HTTP responses using magic prefixes in your script output: ```bash #!/bin/bash # Set custom status code echo "@status: 201" # Set custom headers echo "@header: X-Custom-Header: my-value" echo "@header: Cache-Control: no-cache" # Response body echo '{"created": true}' ``` ### Auto Content-Type Detection Sherut automatically detects and sets the `Content-Type` header: - **JSON**: `application/json` (when output is valid JSON starting with `{` or `[`) - **XML**: `application/xml` (when output starts with `