operator 0.0.2

A web server for static and dynamic content
Documentation
# Operator

Operator is an experimental web server for static and dynamic content. You give
it [a directory](samples/realistic-basic) and it makes a website.

It serves static files the way you'd expect, but it can also serve [dynamic
content](samples/realistic-advanced) that is generated by handlebars templates
or executables at request time.

**⚠️ Operator is extremely alpha!** Please don't use it for anything important
until there's a 1.0 release.

## Installation

Operator is a single self-contained binary. At the moment, the best way to get
a binary for your platform is to build one yourself. First [install
Rust](https://doc.rust-lang.org/book/ch01-01-installation.html), then:

```sh
git clone https://github.com/mkantor/operator.git
cd operator
cargo build --release # This will take a while.
echo '{{#if true}}Hello, Operator!{{/if}}' \
  | ./target/release/operator eval --content-directory=/dev/null
```

## Usage

The CLI has three subcommands:

1. `eval` evaluates a handlebars template from STDIN.
1. `get` renders content from a content directory.
1. `serve` starts an HTTP server.

`serve` is where the real action is, but the other two come in handy at times.

These commands all require a "content directory", which is just the folder
where your website lives. There are a bunch of example content directories in
[`samples/`](samples).

To learn more, run `operator --help` or `operator <SUBCOMMAND> --help`.

### Example

Let's start a server for [one of the samples](samples/realistic-advanced):

```sh
operator -vv serve \
  --content-directory=samples/realistic-advanced \
  --index-route=home \
  --error-handler-route=error-handler \
  --bind-to=127.0.0.1:8080
```

Open [http://localhost:8080](http://localhost:8080) in your browser of choice
to see the website!

### Content

When Operator starts up, it crawls through your content directory to build a
representation of your website. The site's routes and configuration are derived
from this directory.

There are three different kinds of content files:
1. **Static files** are served directly. For example, you can drop a photo into
   your content directory and it'll be served as-is.
1. **Executables** are executed at request time, with standard output piped out
   as the response body. Any program that your operating system can run will
   work (think scripting languages, compiled binaries, etc). The executable is
   invoked with no CLI arguments, no special environment, and with its working
   directory set to its own parent folder. Operator requires execute
   permissions on these files, and scripts typically need a
   [shebang]https://en.wikipedia.org/wiki/Shebang_(Unix) so your operating
   system knows how to interpret them.
1. **Handlebars templates** are compiled during server startup and evaluated at
   request time. The heavy lifting is done by [the `handlebars` Rust
   library](https://crates.io/crates/handlebars) which is largely compatible
   with [the original JavaScript implementation]https://handlebarsjs.com.
   Operator provides some render data and a custom `get` helper to make your
   content composable.

Operator needs to know what [media type](https://tools.ietf.org/html/rfc6838)
will be emitted by each content file. This is specified via file extensions.
The rules are pretty simple:

- The _first_ extension always indicates the media type of the file's output
  (`.html` is `text/html`, `.js` is `text/javascript`, `.png` is `image/png`,
  and [so on]https://crates.io/crates/mime_guess).
- **Static files** only need one extension (`foo.html`, `bar.mp4`, etc).
- **Executables** have _two_ extensions (`baz.html.py`, `quux.css.sh`,
  `garply.jpg.exe`, etc). Operator actually does not care what the second
  extension is, but you can use it to indicate the file type (so
  `baz.html.py` would be a Python script that outputs HTML—for executables the
  _file type_ is usually not the same as its _output type_, although if you're
  feeling feisty then things like `wat.js.js` are certainly possible). As
  mentioned previously, make sure you set the executable bit on these files.
- **Handlebars templates** also have two extensions, but _the second one must
  be `.hbs`_ (`plugh.html.hbs`, `xyzzy.json.hbs`, etc).

Hidden files and directories (whose name begins with `.`) are always completely
ignored by Operator.

## Disclaimer

Operator is very young and has not been battle-hardened. There are known flaws
and obvious missing features that need to be addressed. The major ones are
filed as [issues](https://github.com/mkantor/operator/issues). All feedback is
greatly appreciated.

This is my first nontrivial Rust project and I'm sure there are places where
things are unidiomatic or non-optimal. The main reason I created Operator was
to get more experience using the language, so if you notice anything that could
be improved (no matter how small), please [open an
issue](https://github.com/mkantor/operator/issues/new) to help me learn! ❤️

---

![An old-timey switchboard operator](operator.jpg)