nickel.rs – Web application framework for rust

nickel.rs – Web application framework for rust

Getting Started

Getting started with nickel.rs is extremely easy. This guide will walk you through the steps necessary to write your first nickel app.

 1. Get a recent version of Rust and Cargo

In order to write a nickel app, you first need to make sure to have a recent version of Rust and Cargo. In case you are wondering Cargo is the package manager for Rust. It makes dependency and builds management a breeze. The easiest way to install both is just a simple one-liner on your shell.

$ curl -s https://static.rust-lang.org/rustup.sh | sudo sh

 2. Let Cargo generate a new project directory and cd into it

$ cargo new nickel-demo --bin && cd nickel-demo

By feeding --bin to the cargo new we command cargo to choose the project folder layout for programs instead of libraries. This will also make sure that we can later just use cargo run to start the program.

 3. Edit the generated Cargo.toml file

The Cargo.toml file is the manifest that describes all dependencies of your app and also tells Cargo how to build the project. Just append the following to the file to make Cargo aware of the nickel.rs dependency.


[dependencies]
nickel = "*"

By now your Cargo.toml file should look like this:


[package]

name = "my-demo"
version = "0.0.1"
authors = ["Your Name <your.name@somewhere.com>"]


[dependencies]
nickel = "*"

 4. Edit the generated main.rs file

Cargo generated a main.rs in the src directory of your project. It comes predefined with a hello world implementation. This is where we will put the code for your first nickel app. Delete the content and overwrite it with this:


#[macro_use] extern crate nickel;

use nickel::Nickel;

fn main() {
    let mut server = Nickel::new();

    server.utilize(router! {
        get "**" => |_req, _res| {
            "Hello world!"
        }
    });

    server.listen("127.0.0.1:6767");
}

 5. Run your app

Congrats! You created your first nickel app. Just type cargo run on your console and visit http://localhost:6767 in your browser. It should print out hello world.

Your first nickel app

#[macro_use] extern crate nickel;

use nickel::Nickel;

fn main() {
    let mut server = Nickel::new();

    server.utilize(router! {
        get "**" => |_req, _res| {
            "Hello world!"
        }
    });

    server.listen("127.0.0.1:6767");
}

 Flexible routing

Routes can be as simple as /foo, use parameters, wildcards or even double wildcards.

#[macro_use] extern crate nickel;

use nickel::{Nickel, HttpRouter};

fn main() {
    let mut server = Nickel::new();

    server.get("/bar", middleware!("This is the /bar handler"));
    server.get("/user/:userid", middleware! { |request|
        format!("This is user: {:?}", request.param("userid"))
    });
    server.get("/a/*/d", middleware!("matches /a/b/d but not /a/b/c/d"));
    server.get("/a/**/d", middleware!("This matches /a/b/d and also /a/b/c/d"));

    server.listen("127.0.0.1:6767");
}

 Middleware

Middleware are the extensibility points of nickel. Batteries included! A bunch of existing Middleware comes right with nickel.

#[macro_use] extern crate nickel;

use nickel::{Nickel, StaticFilesHandler};

fn main() {
    let mut server = Nickel::new();

    server.utilize(StaticFilesHandler::new("examples/assets/"));

    server.listen("127.0.0.1:6767");
}

 JSON handling

nickel makes it easy to map JSON data right onto your struct.

This example requires adding the rustc-serialize dependency to your Cargo.toml

extern crate rustc_serialize;
#[macro_use] extern crate nickel;

use nickel::{Nickel, HttpRouter, JsonBody};

#[derive(RustcDecodable, RustcEncodable)]
struct Person {
    firstname: String,
    lastname:  String,
}

fn main() {
    let mut server = Nickel::new();

    server.post("/a/post/request", middleware! { |request, response|
        let person = request.json_as::<Person>().unwrap();
        format!("Hello {} {}", person.firstname, person.lastname)
    });

    server.listen("127.0.0.1:6767");
}

 Custom error handler

By default nickel catches all errors with its default ErrorHandler and tries to take reasonable actions. In cases where one wants to provide an own ErrorHandler (e.g. for custom 404 pages), it’s trivial to write one.

#[macro_use] extern crate nickel;

use std::io::Write;
use nickel::status::StatusCode::NotFound;
use nickel::{Nickel, NickelError, Action, Continue, Halt, Request};

fn main() {
    let mut server = Nickel::new();

    //this is how to overwrite the default error handler to handle 404 cases with a custom view
    fn custom_404<'a>(err: &mut; NickelError, _req: &mut; Request) -> Action {
        if let Some(ref mut res) = err.stream {
            if res.status() == NotFound {
                let _ = res.write_all(b"<h1>Call the police!</h1>");
                return Halt(())
            }
        }

        Continue(())
    }


    // issue #20178
    let custom_handler: fn(&mut; NickelError, &mut; Request) -> Action = custom_404;

    server.handle_error(custom_handler);

    server.listen("127.0.0.1:6767");

}

 Easy Templating

Nickel supports defining templates with mustache.rs. All you need is to create the template…

<html>
    <body>
        <h1>
            Hello {{ name }}!
        </h1>
    </body>
</html>

…and pass it to response.render(template, data).

#[macro_use] extern crate nickel;

use std::collections::HashMap;
use nickel::{Nickel, HttpRouter};

fn main() {
    let mut server = Nickel::new();

    server.get("/", middleware! { |_, response|
        let mut data = HashMap::new();
        data.insert("name", "user");
        return response.render("examples/assets/template.tpl", &data;);
    });

    server.listen("127.0.0.1:6767");
}