Fanta is a web framework that aims for developers to be productive and consistent across projects and teams. Its goals are to be: - Opinionated - Fast - Intuitive
Based heavily off of the work here: https://github.com/tokio-rs/tokio-minihttp
This is a work in progress
Initial tests of plain-text requests yeilds the following resuts:
Framework: Cowboy
Requests/sec: 10982.93
Transfer/sec: 1.36MB
Framework: Node (Koa)
Requests/sec: 9592.82
Transfer/sec: 1.39MB
Framework: Node (Express)
Requests/sec: 5926.87
Transfer/sec: 1.22MB
Framework: Phoenix/Elixir (prod mode)
Requests/sec: 538.02
Transfer/sec: 132.93KB
Framework: Rocket (dev mode)
Requests/sec: 5537.87
Transfer/sec: 789.58KB
Framework: Rocket (prod mode)
Requests/sec: 18555.74
Transfer/sec: 2.58MB
Framework: Fanta (dev mode)
Requests/sec: 7362.82
Transfer/sec: 726.22KB
Framework: Fanta (prod mode)
Requests/sec: 39865.62
Transfer/sec: 3.84MB
Left to the developer to decide at this point!
To get started, check out the example app:
``` extern crate envlogger; extern crate futures; extern crate fanta; extern crate tokioproto; extern crate tokio_service; extern crate time;
extern crate lazy_static;
use fanta::{App, Context, MiddlewareChain, Request, Response};
/** * Here we make a custom context. Contexts are the way that * Fanta passes data between middleware functions. Typically * this is where you'd add fields such as the currently * signed in user, or tracking sessions, etc. */
struct CustomContext { pub body: String, pub method: String, pub path: String }
impl CustomContext { fn new(context: CustomContext) -> CustomContext { CustomContext { body: context.body, method: context.method, path: context.path } } }
/** * The only important part about Contexts is that they * implement the Context trait. The Context trait only * requires a single method, getresponse. * * getresponse should create a Response object from * the current context. This is where you would hydrate * headers, body, and anything else custom that belongs * on the response. */
impl Context for CustomContext { fn get_response(&self) -> Response { let mut response = Response::new(); response.body(&self.body); response.header("Content-Type", "text/plain");
response
}
fn set_body(&mut self, body: String) { self.body = body; } }
/** * The generate_context function is pretty self explanatory. * It's the function that's passed in to the app that gets * called every time a new request into the app is made. It * takes the request and transforms it into Context. */
fn generatecontext(request: &Request) -> CustomContext { CustomContext { body: "".toowned(), method: request.method().toowned(), path: request.path().toowned() } }
/** * The app object must have a static lifetime. This is * just a way to generate static lifetime apps. */
lazystatic! {
static ref APP: App
/**
* We have a single route with the root (/) path. It
* then takes a vector of middleware to be run whenever
* a request is made to that path.
*/
_app.get("/", vec![index]);
_app
}; }
/**
* From above, this is the single function that's executed
* when the /
path is hit. Middleware functions take a
* a Context, a MiddlewareChain (explained below,) and return
* a Context.
*
* A MiddlewareChain is Fanta's way of representing the call
* stack of middleware functions. It has a single method,
* next
which calls the next function in the middleawre
* chain, which returns a new context.
*
* If chain.next() is not called, the chain simply does not
* continue any further and the call stack returns back up.
*/
fn index(context: CustomContext, _chain: &MiddlewareChain
context.body = "Hello world".to_owned();
context }
/** * Start the app! */
fn main() { println!("Starting server...");
drop(envlogger::init()); App::start(&APP, "0.0.0.0".tostring(), "8080".to_string()); } ```