A lightweight web framework built on hyper, implemented in Rust language.

Related tags

Web Servers sapper
Overview

Sapper

Sapper, a lightweight web framework, written in Rust.

Sapper focuses on ergonomic usage and rapid development. It can work with stable Rust.

Sapper now is based on hyper 0.10.13.

Tutorial

Look into json demo, you can learn how to parse http parameters, and return json;

Look into mvc diesel demo, you can learn how to use database, how to render template, and how to redirect.

English Tutorial

中文教程

Import

In Cargo.toml,

[dependencies]
sapper = "0.1"

Basic Example

Now, you can boot the example server with:

cd examples/basic/
cargo build
cargo run

and open the browser, visit

http://localhost:1337/

or

http://localhost:1337/test

or any other url to test it.

Other Examples

  1. tiny

  2. init_global

  3. query params

  4. body params

  5. session

  6. template rendering

  7. simple logger

  8. response json

  9. mvc diesel demo

  10. more continued...

Basic Benchmark

mike@mike-Vostro-3653:~/works2/wrk$ uname -a
Linux mike-Vostro-3653 4.10.0-21-generic #23-Ubuntu SMP Fri Apr 28 16:14:22 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux


mike@mike-Vostro-3653:~/works2/wrk$ cat /proc/cpuinfo 
processor	: 0
vendor_id	: GenuineIntel
cpu family	: 6
model		: 94
model name	: Intel(R) Core(TM) i3-6100 CPU @ 3.70GHz
cpu MHz		: 832.183
cache size	: 3072 KB
bogomips	: 7392.00
...


mike@mike-Vostro-3653:~/works2/sapper/examples/tiny$ cargo run --release
    Finished release [optimized] target(s) in 36.27 secs
     Running `target/release/tiny`
Listening on http://127.0.0.1:1337

output: hello, world!


mike@mike-Vostro-3653:~/works2/wrk$ ./wrk -t2 -c100 -d30s http://127.0.0.1:1337
Running 30s test @ http://127.0.0.1:1337
  2 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    21.73us  139.92us  16.02ms   99.87%
    Req/Sec   235.94k    26.75k  259.73k    76.33%
  7045973 requests in 30.04s, 598.04MB read
Requests/sec: 234536.10
Transfer/sec:     19.91MB

Features

  • Sapper supplies only basic framework;
  • Three level granularity (global, module, function handler) middleware controller and unified middleware presentation;
  • Typesafe abstraction, keep the same spirit with hyper;
  • For easy using, will supply some convenient macros to help write business logics;
  • Global object cross requests;

Philosophy

Typed, hierarchical control, and middlewares.

Typed

In Sapper, nearly every important thing is a Type. They are:

  • Each module is a type, different modules are different types;
  • Every middleware supplies some (0 to n) types for handler getting values;
  • Inherited from hyper's typed spirit, all headers, mime and so on should use types for manipulation.

Hierarchical Control

  • Sapper forces you to put router in each module (in main.rs, you can not write it, no space left for you to write);
  • Sapper forces you to seperate the router binding and the handler realization;
  • Sapper's plugin processor can be used in app level wrapper, module level wrapper, and each handler. These three level hierarchical controls make it flexible to construct your business.

Middlewares

Sapper's core contains only router system, request and response definitions, middleware system, and some other basic facilities. Nearly all practical features, such as query parameter, body parameter, cookie, session, json, xml, orm..., are supplied by the corresponding middlewares.

Sapper's middleware is very easy to write. One rust module realized a function on the prototype of

fn (&mut Request) -> Result<()>;  // before plugin
fn (&Request, &mut Response) -> Result<()>; // after plugin

can be thought as Sapper's middleware. Sample middleware: sapper_query.

TODO

  1. QueryParams (x-www-form-urlencoded);
  2. BodyParams (x-www-form-urlencoded);
  3. BodyJsonParams;
  4. Basic static file serving for dev;
  5. Global object shared cross requests;
  6. Macros;
  7. Multipart;

Middlewares

  • sapper_query parsing query string for req;
  • sapper_body parsing body parameters for req, including url form encoded, json type, json to struct macro;
  • sapper_logger record request and caculate its time;
  • sapper_session a cookie plugin, and else supply a helper set_cookie function;
  • sapper_tmpl use tera to render template;

Related Projects

Thanks to these projects below:

  • hyper Sapper is based on hyper mio branch;
  • iron Sapper learns many designs from iron;
  • router Sapper steals router about code from it;
  • recognizer Sapper uses this route recognizer;

License

MIT

Comments
  • Use diesel instead of sporm?

    Use diesel instead of sporm?

    To Quote:

    Diesel is the most productive way to interact with databases in Rust because of its safe and composable abstractions over queries.

    Did you take a look at the code? It also has a code generator and it seems to be pretty useable. Maybe those projects can be merged and sapper can benefit from it?

    opened by Anachron 6
  • cargo build failed

    cargo build failed

    ubuntu X64 and centos X64 on win10 vmware rustc 1.10.0-nightly (8492b6aa4 2016-05-14) error:failed to run custom build command for openssl-sys-extras v0.7.11 details : Process didn't exit successfully: /usr/gitplace/sapper/examples/basic/target/debug/build/openssl-sys-extras-581243db77f2742c/build-script-build (exit code: 101) --- stdout TARGET = Some("x86_64-unknown-linux-gnu") OPT_LEVEL = Some("0") PROFILE = Some("debug") TARGET = Some("x86_64-unknown-linux-gnu") debug=true opt-level=0 HOST = Some("x86_64-unknown-linux-gnu") TARGET = Some("x86_64-unknown-linux-gnu") TARGET = Some("x86_64-unknown-linux-gnu") HOST = Some("x86_64-unknown-linux-gnu") CC_x86_64-unknown-linux-gnu = None CC_x86_64_unknown_linux_gnu = None HOST_CC = None CC = None HOST = Some("x86_64-unknown-linux-gnu") TARGET = Some("x86_64-unknown-linux-gnu") HOST = Some("x86_64-unknown-linux-gnu") CFLAGS_x86_64-unknown-linux-gnu = None CFLAGS_x86_64_unknown_linux_gnu = None HOST_CFLAGS = None CFLAGS = None running: "cc" "-O0" "-ffunction-sections" "-fdata-sections" "-g" "-m64" "-fPIC" "-o" "/usr/gitplace/sapper/examples/basic/target/debug/build/openssl-sys-extras-581243db77f2742c/out/src/openssl_shim.o" "-c" "src/openssl_shim.c" ExitStatus(ExitStatus(256))

    command did not execute successfully, got: exit code: 1

    --- stderr src/openssl_shim.c:1:26: fatal error: openssl/hmac.h: No such file or directory #include <openssl/hmac.h> ^ compilation terminated. thread '

    ' panicked at 'explicit panic', /root/.cargo/registry/src/github.com-1ecc6299db9ec823/gcc-0.3.28/src/lib.rs:840 note: Run with RUST_BACKTRACE=1 for a backtrace.

    opened by qixuxiang 3
  • Build failed.

    Build failed.

    hyper#67436

    https://github.com/hyperium/hyper/commit/67436c5bf615cf5a55a71e32b788afef5985570e#diff-e3386610f32c404d2944bf396a387ba4R48 Request 多了泛型参数。

    opened by sablib 2
  • unused import & unused variables

    unused import & unused variables

    Just cloned the repository and run cargo build, get bellow errors on terminal(mac/Rust Nightly)

    src/main.rs:7:60: 7:67 warning: unused import, #[warn(unused_imports)] on by default src/main.rs:7 use sapper::{SApp, SAppWrapper, Request, Response, Result, SModule}; ^~~~~~~ src/biz.rs:15:14: 15:17 warning: unused variable:req, #[warn(unused_variables)] on by default src/biz.rs:15 fn index(req: &mut Request) -> Result<Response> { ^~~ src/biz.rs:23:13: 23:16 warning: unused variable:req, #[warn(unused_variables)] on by default src/biz.rs:23 fn test(req: &mut Request) -> Result<Response> { ^~~ src/biz.rs:47:22: 47:25 warning: unused variable:req, #[warn(unused_variables)] on by default src/biz.rs:47 fn before(&self, req: &mut Request) -> Result<()> { ^~~ src/biz.rs:52:21: 52:24 warning: unused variable:req, #[warn(unused_variables)] on by default src/biz.rs:52 fn after(&self, req: &Request, res: &mut Response) -> Result<()> { ^~~ src/biz.rs:52:36: 52:39 warning: unused variable:res, #[warn(unused_variables)] on by default src/biz.rs:52 fn after(&self, req: &Request, res: &mut Response) -> Result<()> { ^~~ src/foo.rs:13:14: 13:17 warning: unused variable:req, #[warn(unused_variables)] on by default src/foo.rs:13 fn index(req: &mut Request) -> Result<Response> { ^~~ src/foo.rs:21:13: 21:16 warning: unused variable:req, #[warn(unused_variables)] on by default src/foo.rs:21 fn test(req: &mut Request) -> Result<Response> { ^~~ src/foo.rs:44:22: 44:25 warning: unused variable:req, #[warn(unused_variables)] on by default src/foo.rs:44 fn before(&self, req: &mut Request) -> Result<()> { ^~~ src/foo.rs:49:21: 49:24 warning: unused variable:req, #[warn(unused_variables)] on by default src/foo.rs:49 fn after(&self, req: &Request, res: &mut Response) -> Result<()> { ^~~ src/foo.rs:49:36: 49:39 warning: unused variable:res, #[warn(unused_variables)] on by default src/foo.rs:49 fn after(&self, req: &Request, res: &mut Response) -> Result<()> { ^~~ src/main.rs:21:22: 21:25 warning: unused variable:req, #[warn(unused_variables)] on by default src/main.rs:21 fn before(&self, req: &mut Request) -> Result<()> { ^~~ src/main.rs:27:21: 27:24 warning: unused variable:req, #[warn(unused_variables)] on by default src/main.rs:27 fn after(&self, req: &Request, res: &mut Response) -> Result<()> { ^~~ src/main.rs:27:36: 27:39 warning: unused variable:res, #[warn(unused_variables)] on by default src/main.rs:27 fn after(&self, req: &Request, res: &mut Response) -> Result<()> { ^~~

    opened by dumindu 2
  • add CustomResponse for Error

    add CustomResponse for Error

    there something like

    fn do_something() -> Option<Info> {
        // some code may return None
    }
    
    fn custom_response() -> Response {
        // some code build custom response
    }
    

    with this commit, you could write code like

    fn with_custom_response_error(req: &mut Request, res: Response) -> SapperResult<Response> {
        let info = do_something().ok_or(SapperError::CustomResponse(custom_response()))?; // success or return custom response immediately
        // some code
        Ok(res)
    }
    

    without this commit, you have to write code like

    fn without_custom_response_error(req: &mut Request, res: Response) -> SapperResult<Response> {
        if let Some(info) = do_something() {
            // some code
            Ok(res)
        } else {
            Ok(custom_response())
        }
    }
    
    opened by DCjanus 1
  • Remove reflect_marker

    Remove reflect_marker

    Because "we approve deprecation" from https://github.com/rust-lang/rust/issues/27749 and I did not see any usage in code.

    PS after small fix sapper is working very well on stable rustc 1.12.0, Requests per second: 27632.17

    opened by stalkerg 1
  • export Params for user

    export Params for user

    Sometime users want to save or pass params, but the Params is private, that means, I can't write code such as

    fn save_params(params: sapper::sapper::recognizer::Params) {
        // some code
    }
    

    I have to write it like

    fn save_params(req:sapper::Request) {
        let params=get_params!(req);
        // some code
    }
    
    opened by DCjanus 0
  • use may_http as the lower layer http implementation

    use may_http as the lower layer http implementation

    the may_http version with 2 io threads

    $ wrk http://127.0.0.1:1337/foo/ -d 30 -t 2 -c 200
    Running 30s test @ http://127.0.0.1:1337/foo/
      2 threads and 200 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     1.86ms    1.59ms  36.35ms   97.31%
        Req/Sec    58.39k     4.12k   90.16k    82.17%
      3489710 requests in 30.09s, 336.13MB read
    Requests/sec: 115974.88
    Transfer/sec:     11.17MB
    wrk http://127.0.0.1:1337/foo/ -d 30 -t 2 -c 200  12.30s user 31.38s system 145% cpu 30.095 total
    

    the hyper master branch

    $ wrk http://127.0.0.1:1337/foo/ -d 30 -t 2 -c 200
    Running 30s test @ http://127.0.0.1:1337/foo/
      2 threads and 200 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency    72.68us   58.95us  13.76ms   99.20%
        Req/Sec    50.24k     6.26k   72.91k    88.00%
      1499423 requests in 30.09s, 124.41MB read
    Requests/sec:  49824.83
    Transfer/sec:      4.13MB
    wrk http://127.0.0.1:1337/foo/ -d 30 -t 2 -c 200  3.29s user 15.76s system 63% cpu 30.101 total 
    
    opened by Xudong-Huang 0
  • Consider adding a TechEmpower comparison for Sapper

    Consider adding a TechEmpower comparison for Sapper

    Hi!

    I noticed that Sapper is missing from https://github.com/TechEmpower/FrameworkBenchmarks/ - are you interested in adding a benchmark there? Alternatively, I can add one if you're not against it :)

    opened by whitfin 1
Owner
Daogang Tang
Rustacean, Motobike, Life.
Daogang Tang
A synchronous HTTP server built on hyper.

Astra Astra is a synchronous HTTP server built on top of hyper. use astra::{Body, Response, Server}; fn main() { Server::bind("localhost:3000")

Ibraheem Ahmed 23 Nov 27, 2022
Node.js http server framework powered by Hyper native binding.

hnsjs POC project. Install this test package yarn add @hnsjs/core Support matrix node10 node12 node14 node15 Windows x64 ✓ ✓ ✓ ✓ Windows x32 ✓ ✓ ✓ ✓

LongYinan 18 Nov 23, 2022
Static Web Server - a very small and fast production-ready web server suitable to serve static web files or assets

Static Web Server (or SWS abbreviated) is a very small and fast production-ready web server suitable to serve static web files or assets.

Jose Quintana 496 Jan 2, 2023
Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust.

Actix Web Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust Features Supports HTTP/1.x and HTTP/2 Streaming and pipelining

Actix 16.3k Jan 8, 2023
An Extensible, Concurrent Web Framework for Rust

Iron Extensible, Concurrency Focused Web Development in Rust. Response Timer Example Note: This example works with the current iron code in this repos

null 6.1k Dec 27, 2022
An expressjs inspired web framework for Rust

nickel.rs nickel.rs is a simple and lightweight foundation for web applications written in Rust. Its API is inspired by the popular express framework

null 3k Jan 3, 2023
A web framework for Rust.

Rocket Rocket is an async web framework for Rust with a focus on usability, security, extensibility, and speed. #[macro_use] extern crate rocket; #[g

Sergio Benitez 19.5k Jan 8, 2023
Web framework in Rust

Rouille, a Rust web micro-framework Rouille is a micro-web-framework library. It creates a listening socket and parses incoming HTTP requests from cli

Pierre Krieger 840 Jan 1, 2023
A fast, boilerplate free, web framework for Rust

Tower Web A web framework for Rust with a focus on removing boilerplate. API Documentation Tower Web is: Fast: Fully asynchronous, built on Tokio and

Carl Lerche 969 Dec 22, 2022
Salvo is a powerful and simplest web server framework in Rust world

Salvo is an extremely simple and powerful Rust web backend framework. Only basic Rust knowledge is required to develop backend services.

Salvo 1.2k Jan 5, 2023
The light web framework for Rust.

Rusty Web Rusty web is a simple to use, fully customizable lightweight web framework for rust developers. Learn rusty web Installation [dependencies]

Tej Magar 5 Feb 27, 2024
A flexible web framework that promotes stability, safety, security and speed.

A flexible web framework that promotes stability, safety, security and speed. Features Stability focused. All releases target stable Rust. This will n

Gotham 2.1k Jan 3, 2023
Handlebars middleware for Iron web framework

handlebars-iron Handlebars middleware for the Iron web framework. This library, together with handlebars, iron and hyper, works on both stable and nig

Ning Sun 118 Jun 28, 2022
A toy web framework inspired by gin-gonic/gin and expressjs/express.

Rum Framework A toy web framework inspired by gin-gonic/gin and expressjs/express. Installation Just add rum_framework to the dependencies of Cargo.to

Hidetomo Kou(YingZhi 2 Dec 20, 2022
web browser as a language server

web-browser-lsp A toy program that implements a text-based web browser as a language server. Motivation My favorite progrmming tools are neovim, tmux

octaltree 17 Nov 24, 2022
high (er) level language and compiler targeting the mindustry logic language

Copper Copper is a high level language and compiler that compiles to mindustry logic. The syntax is similar to rust, with some differences. (these wil

Rowan 2 Jun 27, 2022
JSON Web Token implementation in Rust.

Frank JWT Implementation of JSON Web Tokens in Rust. Algorithms and features supported HS256 HS384 HS512 RS256 RS384 RS512 ES256 ES384 ES512 Sign Veri

Alex Maslakov 246 Dec 27, 2022
Source Code for 'Practical Rust Web Projects' by Shing Lyu

Apress Source Code This repository accompanies Practical Rust Web Projects by Shing Lyu (Apress, 2021). Download the files as a zip using the green bu

Apress 44 Nov 17, 2022
A web application completely written in Rust. 🌍

WebApp.rs A web application completely written in Rust Target of this project is to write a complete web application including backend and frontend wi

Sascha Grunert 2.1k Dec 30, 2022