flyer 0.1.0

HTTP framework for rust
Documentation

Flyer - Web Framework

Getting Started

Prerequisites

Http key features:

  • Router
  • View
  • Assets
  • Middleware
  • Session
  • Cookie
  • WebSocket

Getting with Flyer

First create a new project using command:

cargo new example

After running the command add flyer to you project using command:

cargo add flyer

Running HTTP server

In order to run a basic server copy and paste below code snippet.

use flyer::server;

fn main() {
    let mut server = server("127.0.0.1", 9999);
    
    server.router().get("/", async |_req, res| {
        return res.html("<h1>Hello World!!!</h1>")
    });

    print!("\r\n\r\nRunning server: {}\r\n\r\n", server.address());

    server.listen();
}

Now we are ready to run the server using command.

cargo run

if you want to run secure server you can use function server_tls here is example below.

use flyer::server_tls;

fn main() {
    let mut server = server_tls("127.0.0.1", 9999, ":HOST_KEY_PATH:", ":HOST_CERT_PATH:");
    
    server.router().get("/", async |req, res| {
        return res.html("<h1>Hello World Secure Connection!!!</h1>")
    });

    print!("\r\n\r\nRunning server: {}\r\n\r\n", server.address());

    server.listen();
}

Router

use flyer::{server, request::Request, response::Response};

pub async fn index<'a>(_req: &'a mut Request, res: &'a mut Response) -> &'a mut Response {
    return res.html("<h1>Users List</h1>");
}

pub async fn store<'a>(_req: &'a mut Request, res: &'a mut Response) -> &'a mut Response {
    return res.redirect("users/1");
}

pub async fn view<'a>(req: &'a mut Request, res: &'a mut Response) -> &'a mut Response {
    return res.html(format!("<h1>User {}</h1>", req.parameter("user")).as_str());
}

pub async fn update<'a>(req: &'a mut Request, res: &'a mut Response) -> &'a mut Response {
    return res.redirect(format!("users/{}", req.parameter("user")).as_str());
}

pub async fn destroy<'a>(_req: &'a mut Request, res: &'a mut Response) -> &'a mut Response {
    return res.redirect("users")
}

fn main() {
    let mut server = server("127.0.0.1", 9999);
    
    server.router().group("/", |router| {
        router.group("users", |router| {
            router.get("/", index);
            router.post("/", store);
            router.group("{user}", |router| {
                router.get("/", view);
                router.patch("/", update);
                router.delete("/", destroy);
            });
        });
    });

    print!("\r\n\r\nRunning server: {}\r\n\r\n", server.address());

    server.listen();
}

View

Create file called index.html in folder called views and copy the content below in the file.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello {{ user.first_name }}</title>
</head>
<body>
    <h1>Hi, {{ user.first_name }} {{ user.last_name }} how are you?</h1>
</body>
</html>

The next step to insert code below in main.rs.

use flyer::{server, view::view_data};
use serde::Serialize;

#[derive(Serialize)]
pub struct User<'a> {
    first_name: &'a str,
    last_name: &'a str,
}

fn main() {
    let mut server = server("127.0.0.1", 8888)
        .view("views");

    server.router().get("/", async |_req, res| {
        let mut data = view_data();

        data.insert("user", &User{
            first_name: "Jeo",
            last_name: "Deo"
        });

        return res.view("index.html", Some(data));
    });

    println!("Running Server: {}", server.address());

    server.listen();
}

For more information about view functionality view Tera.

Assets

Create file called style.css in folder called assets and copy the content below in the file.

body {
    background-color: black;
}

h1 {
    color: white;
}

And also create file called index.html in folder called views and copy the content below in the file.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <base href="http://127.0.0.1:9999/">
  <title>Assets Test</title>
  <link href="/style.css" rel="stylesheet">
</head>
<body>
  <h1>Hello World</h1>
</body>
</html>

The next step to insert code below in main.rs.

use flyer::{server, view::view_data};

fn main() {
    let mut server = server("127.0.0.1", 8888)
        .view("views");

    server.router().get("/", async |_req, res| {
        return res.view("index.html", Some(view_data()));
    });

    println!("Running Server: {}", server.address());

    server.listen();
}

You should see background color of black and Hello World with white color if you visit 127.0.0.0.1:9999

Middleware

use flyer::{server, request::Request, response::Response, router::Next};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
pub struct User {
    id: u64,
    email:  String
}

#[derive(Serialize, Deserialize)]
pub struct JsonMessage {
    message: String
}

pub async fn auth<'a>(req: &'a mut Request, res: &'a mut Response, next: &mut Next) -> &'a mut Response {
    if req.header("authorization") != "ey.jwt.token" {
        return res.status_code(401).json(&JsonMessage{
            message: "Unauthorized Access".to_owned()
        })
    }
    
    return next.handle(res);
}

fn main() {
    let mut server = server("127.0.0.1", 9999);
    
    server.router().get("api/users/{user}", async |req, res| {
        return res.json(&User{
            id: req.parameter("user").parse().unwrap(),
            email: "joe@deo.com".to_owned()
        })
    }).middleware(auth);

    print!("\r\n\r\nRunning server: {}\r\n\r\n", server.address());

    server.listen();
}

Session

use std::time::Duration;

use flyer::{
    request::Request,
    response::Response,
    router::next::Next,
    server,
    session::cookie::new_session_manager
};

/// Controller
pub async fn home_view<'a>(req: &'a mut Request, res: &'a mut Response) -> &'a mut Response {
    return res.html(format!("<h1>Welcome to protected home page user {}</h1>", req.session().get("user_id")).as_str());
}

pub async fn login<'a>(req: &'a mut Request, res: &'a mut Response) -> &'a mut Response {
    req.session().set("user_id", format!("{}", 1).as_str());

    return res.redirect("login");
}

pub async fn register<'a>(_req: &'a mut Request, res: &'a mut Response) -> &'a mut Response {
    return res.html("<h1>Please visit the login page to login</h1>");
}

pub async fn logout<'a>(req: &'a mut Request, res: &'a mut Response) -> &'a mut Response {
    req.session().remove("user_id");

    return res.redirect("register");
}

pub async fn page_not_found<'a>(_req: &'a mut Request, res: &'a mut Response) -> &'a mut Response {
    return res.html("<h1>404 Page Not Found</h1>");
}

/// Middleware
pub async fn auth<'a>(req: &'a mut Request, res: &'a mut Response, next: &'a mut Next) -> &'a mut Response {
    if req.session().get("user_id") == "" {
        return res.redirect("register");
    }

    return next.handle(res);
}

pub async fn guest<'a>(req: &'a mut Request, res: &'a mut Response, next: &'a mut Next) -> &'a mut Response {
    if req.session().get("user_id") != "" {
        return res.redirect("/");
    }

    return next.handle(res);
}

fn main() {
    let mut server = server("127.0.0.1", 9999)
        .session(new_session_manager(Duration::from_hours(2), "session_cookie_key_name", "encryption"));

    server.router().group("/", |router| {
        router.get("/", home_view).middleware(auth);
        router.get("register", register).middleware(guest);
        router.get("login", login).middleware(guest);
        router.get("logout", logout).middleware(auth);
    });

    server.router().not_found(page_not_found);

    print!("\r\n\r\nRunning server: {}\r\n\r\n", server.address());

    server.listen();
}

Cookie

use std::time::Duration;

use flyer::{
    request::Request,
    response::Response,
    server,
};

pub async fn home_view<'a>(req: &'a mut Request, res: &'a mut Response) -> &'a mut Response {
    req.cookies()
        .set("user_id", "1")
        .set_expires(Duration::from_hours(2));

    return res.html("<h1>Cookie has been set visit route /cookie</h1>");
}

pub async fn cookie<'a>(req: &'a mut Request, res: &'a mut Response) -> &'a mut Response {
    return res.html(format!("<h1>User ID cookie is {}</h1>", req.cookies().get("user_id")).as_str());
}

fn main() {
    let mut server = server("127.0.0.1", 9999);

    server.router().group("/", |router| {
        router.get("/", home_view);
        router.get("cookie", cookie);
    });

    print!("\r\n\r\nRunning server: {}\r\n\r\n", server.address());

    server.listen();
}

Websocket

use std::time::Duration;

use flyer::{
    request::Request,
    response::Response,
    server,
};

pub async fn home_view<'a>(req: &'a mut Request, res: &'a mut Response) -> &'a mut Response {
    req.cookies()
        .set("user_id", "1")
        .set_expires(Duration::from_hours(2));

    return res.html("<h1>Cookie has been set visit route /cookie</h1>");
}

pub async fn cookie<'a>(req: &'a mut Request, res: &'a mut Response) -> &'a mut Response {
    return res.html(format!("<h1>User ID cookie is {}</h1>", req.cookies().get("user_id")).as_str());
}

fn main() {
    let mut server = server("127.0.0.1", 9999);

    server.router().group("/", |router| {
        router.get("/", home_view);
        router.get("cookie", cookie);
    });

    print!("\r\n\r\nRunning server: {}\r\n\r\n", server.address());

    server.listen();
}