[][src]Crate vial

~ vial: a micro micro-framework ~

Vial is a small web "framework" for making small web sites.

It only includes a few basics:

  • routes!: Macro for mapping URLs to handlers.
  • Request: Information about the current request, such as form data or URL path segments.
  • Response: Response to deliver to the client.
  • Responder: Trait to convert your types or a few built-ins like String into a Response.
  • asset: Serving of static files and support for bundling into the release binary.

Everything else... well, that's up to you.

The goal is an as-few-as-possible-dependencies web library you can use to test out an idea quickly or get a personal project rolling. Single file, server side apps? You bet! Fast compilation? Yes please! À la carte dependencies? Now you're talkin'!

It's sort of like a picnic where the playlist is all 90s music and you have to bring your own beverages. And food.


Status: Vial is currently in early development. It is being developed alongside [deadwiki], but that is strictly for personal use. Proceed with caution.


To get started, just add vial to your Cargo.toml:

[dependencies]
vial = "*"

There are a handful of --features that you can enable, most of which add additional dependencies that need to be included:

[dependencies]
vial = { version = "*", features = ["state", "cookies"] }

This list is a work in progress:

  • [x] state: Global state: handlers take State<T>
  • [x] horror: Small & fast macro-based HTML builder, via [horrowshow].
  • [ ] cookies: Cookie monster!
  • [ ] sessions: Session support
  • [ ] multipart: Multipart form data (file uploads)
  • [ ] log: Access logging
  • [ ] json: to_json and from_json powers, via Serde.

~ hello world ~

As is tradition:

vial::routes! {
    GET "/" => |_| "Hello, world!";
}

fn main() {
    vial::run!().unwrap();
}

For a bit more sanity, you can route to functions directly:

use vial::prelude::*;

routes! {
    GET "/echo" => echo;
    POST "/echo" => post;
}

fn echo(_: Request) -> &'static str {
    "<form method='POST'>
        <input type='text' name='echo'/>
        <input type='submit'/>
    </form>"
}

fn post(req: Request) -> String {
    format!(
        "<h1>{}</h1>",
        req.form("echo").unwrap_or("You didn't say anything!")
    )
}

fn main() {
    vial::run!().unwrap();
}

To really break the mold, you can split your site into different modules:

use vial;

mod wiki;
mod blog;

mod index {
    use vial::prelude::*;
    routes! {
        GET "/" => |_| Response::from_file("index.html")
    }
}

fn main() {
    // The order matters here - if `wiki` and `blog` both define "/",
    // the `mod index` version will match first and get run.
    vial::run!(index, wiki, blog);
}

But hey, who wants to putz around with HTML when you can be writing Rust? Enable the horror feature and you're on your way:

use vial::prelude::*;

routes! {
    GET "/" => |_| html! {
        p {
            : "You're looking for this: ";
            a(href="/echo") { : "echo" }
        }
    };
    GET "/echo" => echo;
    POST "/echo" => post;
}

fn echo(_: Request) -> impl Responder {
    html! {
        form(method="POST") {
            p {
            : "Type something: ";
                input(type="text", name="echo");
                input(type="submit");
            }
        }
    }
}

fn post(req: Request) -> impl Responder {
    owned_html! {
        h1: req.form("echo")
            .unwrap_or("You didn't say anything!");
    }
}

fn main() {
    vial::run!().unwrap();
}

~ hot reloading ~

Install [cargo-watch]:

$ cargo install cargo-watch
$ cargo watch -x 'run --example hello_world'

~ performance ~

We want to keep Vial snappy, but this is not a production web server that's competing in any shootouts. Our bigger priority is keeping the base dependency count and compilation time low.

~ when to use ~

Probably never, or only ever to quickly test an idea. Certainly not for personal wikis or small hobby projects, unless you insisted.

Modules

asset

Assets

features
prelude

The prelude pulls in all the main types, traits, and macros:

Macros

asset_dir
bundle_assets
include_assets
routes
run
setup

Structs

Request

  • [x] set_arg(&str, &str)
  • [x] set_form(&str, &str)
  • [ ] set_query(&str, &str)
  • [x] set_path(&str, &str)
  • [ ] set_method(&str, &str)
  • [ ] set_body(&str, &str) Request contains all the info about a client's request. It's handed to your actions and filters, and is dropped after responding to the client.
  • Response
    Router
    TypeCache

    The TypeCache is heavily inspired by the state crate and the way the Rocket framework handles global and local state. You could say we've immutably borrowed some ideas. Rim-shot!

    Enums

    Method

    Method is just an enum representing the HTTP methods Vial supports. Which is not all of them.

    Constants

    BUILD_DATE

    Date and time this program was compiled.

    Statics

    ASSET_DIR

    Directory where assets are stored, if any.

    BUNDLED_ASSETS

    Assets bundled into the binary in release mode.

    Traits

    Responder

    The Responder trait converts your custom types or a few basic Rust types into a Response that gets hand delivered to the HTTP client in a timley fashion, barring any weather delays.

    Functions

    bundle_assets

    Prepares everything in dir to be bundled into a binary. Sets ASSET_DIR and cfg(bundle_assets) for the user's program, which uses them to find the assets.

    run

    Type Definitions

    Result

    Convenience Result that, for now, returns io::Error. TODO: replace with vial::Error.