Salvo is a web server framework written in Rust.
🎯 Features
- Base on hyper, tokio and async supported;
- Websocket supported;
- Middleware is handler and support executed before or after handle;
- Easy to use routing system, routers can be nested, and you can add middleware in routers;
- multipart form supported, handle files upload is very simple;
- Serve a static virtual directory from many physical directories;
⚡️ Quick start
You can view samples here or read docs here.
Create a new rust project:
Add this to Cargo.toml
[]
= "0.10"
= { = "1", = ["full"] }
Create a simple function handler in the main.rs file, we call it hello_world, this function just render plain text "Hello World".
use *;
async
There are many ways to write function handler.
-
You can omit function arguments if they do not used, like
_req,_depotin this example:async -
Any type can be function handler's return value if it implements
Writer. For example &str implementsWriterand it will render string as plain text:async -
The more common situation is we want to return a
Result<T, E>to implify error handling. IfTandEimplementsWriter,Result<T, E>can be function handler's return type:async
In the main function, we need to create a root Router first, and then create a server and call it's bind function:
use *;
async
async
Middleware
There is no difference between Handler and Middleware, Middleware is just Handler.
Tree-like routing system
Normally we write routing like this:
new.path.get.post;
new
.path
.get
.patch
.delete;
Often viewing articles and article lists does not require user login, but creating, editing, deleting articles, etc. require user login authentication permissions. The tree-like routing system in Salvo can meet this demand. We can write routers without user login together:
new
.path
.get
.push;
Then write the routers that require the user to login together, and use the corresponding middleware to verify whether the user is logged in:
new
.path
.before
.post
.push;
Although these two routes have the same path("articles"), they can still be added to the same parent route at the same time, so the final route looks like this:
new
.push
.push;
<id> matches a fragment in the path, under normal circumstances, the article id is just a number, which we can use regular expressions to restrict id matching rules, r"<id:/\d+/>".
For numeric characters there is an easier way to use <id:num>, the specific writing is:
<id:num>, matches any number of numeric characters;<id:num[10]>, only matches a certain number of numeric characters, where 10 means that the match only matches 10 numeric characters;<id:num(..10)>means matching 1 to 9 numeric characters;<id:num(3..10)>means matching 3 to 9 numeric characters;<id:num(..=10)>means matching 1 to 10 numeric characters;<id:num(3..=10)>means match 3 to 10 numeric characters;<id:num(10..)>means to match at least 10 numeric characters.
You can also use <*> or <**> to match all remaining path fragments. In order to make the code more readable, you can also add appropriate name to make the path semantics more clear, for example: <**file_path>.
It is allowed to combine multiple expressions to match the same path segment, such as /articles/article_<id:num>/.
File upload
We can get file async by the function get_file in Request:
async
Multiple files also very simple:
async
More Examples
Your can find more examples in examples folder:
- basic_auth.rs
- compression.rs
- file_list.rs
- proxy.rs
- remote_addr.rs
- routing.rs
- size_limiter.rs
- sse_chat.rs
- sse.rs
- tls.rs
- todos.rs
- unix_socket.rs
- ws_chat.rs
- ws.rs
Some code and examples port from warp, multipart-async, mime-multipart and actix-web.
☕ Supporters
Salvo is an open source project. If you want to support Salvo, you can ☕ buy a coffee here.
⚠️ License
Salvo is licensed under MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT).