Rustgram
A lightweight, fast and easy to use http routing and middleware framework build on top of hyper
Features
- build routes and middleware like Tower services
- uses yaml files to define routes
Install in Cargo.toml
[]
# hyper when using Statuscode
= { = "0.14", = ["full"] }
# tokio for the async main fn
= { = "1", = ["full"] }
# rustgram
= "0.1"
Documentation
Getting started
- Create the router with a not found handler service (e.g. a function)
- adding routes, for every http method there is a router function: get, post, put, delete, head, ...
- use the r function to pass the handler to the router
- use the method function to define on what method this route should be matched to the given path
- set an url path
- enter the socket address to listen for connection
use ;
use SocketAddr;
async
pub async
async
Middleware
- A middleware is a service.
- The middleware calls the next service (which is obtained by the middleware transformation).
- A transform is used to return a new middleware with a next service
- The transform function is called everytime when a middleware is applied to a route
The middleware stack is build like a service call stack.
The Order of the middleware stack is reverse to the applied order.
use ;
use ;
//define a middleware service
//define a middleware transform
;
//or define a middleware transform with a function
async
pub async
//Apply a middleware to a route after the r function
async
Middleware with async handling
If work must be done before the req handling or after the response, a Box Future is needed
When calling async actions before the response, here Arc is needed to avoid lifetime issues:
- use a Pin Box feature
- use inner service as an arc pointer
- clone the arc pointer before calling the async block
- do the async action in the async block
use Future;
use Pin;
use Arc;
use ;
use ;
Only after response async action:
use ;
use ;
Handler return and error handling
The router only uses Service traits. For normal functions and closure, this is already implemented.
The functions don't need to return a Hyper Response, but their return gets converted into hyper response.
Supported returns are:
- Hyper Response
- String
- &'static str
- Result<String, GramStdHttpErr>
- Result<String, E>
The GramStdHttpErr gets converted into a hyper response.
The E where E impl GramHttpErr, will convert via the GramHttpErr trait.
use StatusCode;
use ;
//example usage:
pub async
Route builder and groups
- groups can only be build by the route builder
- the builder parses a yml file and create a new route file. this file contains a function which returns a router (to use it later).
- all routes in a route shares the same middleware and the same prefix
- nested groups are also possible
- Create a 2nd bin crate for the route builder.
- This crate calls the builder function
- Set the input and the output path (both relative to the current working directory)
- Build and execute the route builder everytime the routes are changed
- use the route function, from the new file, to get the router
# in a workspace just create a new crate
cargo new route_builder
Open the main function in src/main.rs
use route_parser;
Create the route file.
# define the namespace where the route handlers live
# or leave it emtpy and use the full path to the handler
base_handler: test_handler
# define the namespace for the middleware
base_mw: test_mw
# the 404 handler. is called when no routes matched the given path
handler_404: crate::not_found_handler
# prefix for all routes
prefix: "/"
# the routes and groups. use the method followed by the path (p) and the handler (s)
routes:
- get:
p: ""
# must match the base_handler namespace
s: test_handler::test_handler
# a put route with middleware
- put:
p: ""
s: test_handler::test_handler
mw:
- mw1_transform
- mw_transform
# a group of routes.
# a prefix (p) for all routes and middleware (mw) like routes
- group:
p: admin
mw:
- mw1_transform
- mw_transform
# the routes to this group
gr:
- get:
p: ""
s: test_handler_db::test_handler_db_to_json
- get:
p: "/user/:id"
s: test_handler::test_handler
# for this route, mw is called first, then mw1, mw2 and mw3
- put:
p: "/many_mw"
s: test_handler::test_handler
mw:
- mw3_transform
- mw2_transform
- group:
p: nested
mw:
- mw1_transform
- mw_transform
gr:
# define a new group inside the group routes
- group:
p: "/management"
mw:
- mw1_transform
- mw_transform
gr:
- put:
p: "/put"
s: test_handler::test_handler
mw:
- mw5_transform
- mw4_transform
This file is parsed to this:
/**
# Generated route files by rustgram route builder.
Please do not modify this file. Any changes will be overridden by the next route build.
Use the returned router instead
*/
use ;
use crate*;
use crate*;
pub