# http-cmd
Run a command over HTTP
## ⚠️ Warning ⚠️
**Don't expose `http-cmd` to the internet, especially with programs that execute code (e.g. `python`) or commands (e.g. `bash`).
Otherwise, execution of arbitrary code and programs is possible (aka. you get hacked)!**
## Motivation
The motivation for building this tool is that static site generators like [Zola](https://www.getzola.org/) don't allow executing external commands for security reasons.
You don't want arbitrary programs to be executed while you try to build a static website!
Imagine being hacked by a third-party theme 😱
However, such static site generators support fetching remote data.
This leads to the hack of how `http-cmd` works:
- 💻️ Run a local HTTP server waiting for POST requests and using their body as standard input or command arguments for the external command
- ⬆️ Let the static site generator send a POST request to run the external command
- ⬇️ Embed the response body as the output of the external command
- 🎉 Profit!
You can find examples of using `http-cmd` with Zola in the [`zola_examples`](zola_examples) directory.
## Use cases
Here are some possible use cases:
- ➗ Converting LaTeX math to HTML
- 💻️ Demonstration of CLIs
- 🖨️ [Embedding the output of code blocks for multiple languages](zola_examples/embedding_code_evaluation)
- 📊 Embedding a diagram generated from text
- 😃 Replacing emoji shortcodes with Unicode emojis
- ⚙️ In general, extending the capabilities of static site generators
- 💭 Your idea
## Installation
You can install `http-cmd` using Cargo by running
```bash
cargo install http-cmd
```
You can update it using [`cargo-update`](https://github.com/nabijaczleweli/cargo-update).
If you don't want to install Cargo with the Rust toolchain, open an issue and I will publish a container image that you can run with Docker or Podman.
## Config
`http-cmd` expects the config file `http-cmd.toml` in the directory where it is executed.
But you can also provide a path to the a config file using the `-c` command line option.
| `ip` | The IPv4/IPv6 address to bind to | "127.0.0.1" |
| `port` | The port to listen on | 8080 |
| `max_request_body_size` | The maximum request body size in bytes | 1048576 (1 MiB) |
| `commands` | A list of command configs | |
| `commands.name` | A name for the command. It is used for executing the command under `http://IP:PORT/NAME`. Only the characters `a` to `z` (lowercase), `0` to `9` and `-` are allowed. | |
| `commands.stdin` | See the [Modes](#modes) section below | |
| `commands.program` | The program to execute when `http://IP:PORT/NAME` is called. It can be an absolute or relative path to the executable. Otherwise, the executable will be searched for equivalently to running the Unix `which` command | |
| `commands.args` | A list of the program's arguments | |
### Modes
`http-cmd` has two modes for running a program.
The mode is chosen using the boolean configuration value `stdin`:
- For **`stdin = true`**, the request body is piped to the standard input of the command.
- For **`stdin = false`**, the request body is split to arguments which are provided after the configured `args`. See the example below with the `ls` command.
## Demo
Here is an example config file:
```toml
# The default
ip = "127.0.0.1"
# The default
port = 8080
# 2 KiB instead of the default of 1MiB
max_request_body_size = 2048
[[commands]]
name = "rev"
stdin = true
program = "rev"
args = []
[[commands]]
name = "ls"
stdin = false
program = "/usr/bin/ls"
args = ["-l"]
```
If you save this configuration to the file `http-cmd.toml` and run `http-cmd`, a server is started listening on `http://127.0.0.1:8080/rev` and `http://127.0.0.1:8080/ls`.
Now, run
```bash
curl http://127.0.0.1:8080/rev -d "Hello World!"
```
This command sends a POST request with the body "Hello World!".
The output should be the reversed text: "!dlroW olleH" 🎉
The equivalent of what `http-cmd` does here with `stdin` set to `true` is the following pipe:
```bash
To test the second command, run
```bash
curl http://127.0.0.1:8080/ls -d "src zola_examples"
```
The output depends on the content of the two directories.
This command also sends a POST request, but since `stdin` is set to `false` for the `ls` command, the second [mode](#modes) is applied.
This means that `http-cmd` executes the command `ls -l src zola_examples`.
The arguments `src` and `zola_examples` are placed after the program `ls` and its configured arguments (here only `-l`).