Rust Crate之Actix Web
什么是Actix Web?
Actix Web is a poweful ,pragmatic,and extremely fast web framework for Rust
Actix Web 作为一个服务器框架,非常适合于搭建小型http服务器,方便快捷,它支持Http/1,Http2,TLS,尽管他也支持了Websocket,但在此不予讨论。
Actix Web 入门
代码示例:
useactix_web::{get, post, web,App,HttpResponse,HttpServer,Responder};#[get("/")]//使用ACtix定义的宏,可以直接将响应函数定义具体路由地址(url),并确定以什么方式访问(如这里的根,Get方式),asyncfnhello()->implResponder{HttpResponse::Ok().body("Hello world!")}#[post("/echo")]asyncfnecho(req_body:String)->implResponder{HttpResponse::Ok().body(req_body)}asyncfnmanual_hello()->implResponder{HttpResponse::Ok().body("Hey there!")}#[actix_web::main]//标明Actix web程序入口,默认支持异步编程asyncfnmain()->std::io::Result<()>{HttpServer::new(||{//创建HttpServerApp::new()//使用App 实例注册request处理程序..service(hello)//使用宏路由的,用sercvice注册.service(echo).route("/hey",web::get().to(manual_hello))//也可以手动,更清晰的注册路由}).bind(("127.0.0.1",8080))?//绑定具体的Ip & Port.run()//run起来您的程序.await}//ps:以上代码为官方示例
代码宏展开,看看
#[get("/")]
做了什么
#![feature(prelude_import)]#[prelude_import]usestd::prelude::rust_2021::*;#[macro_use]externcratestd;useactix_web::{get, post, web,App,HttpResponse,HttpServer,Responder};#[allow(non_camel_case_types, missing_docs)]pubstructhello;// 正如官文中描述的那样:Finally, the app is started inside an HttpServer which will serve incoming // requests using your App as an "application factory". 每一个request处理程序都实现了HttpServiceFactoryimpl::actix_web::dev::HttpServiceFactoryfor hello {fnregister(self, __config:&mutactix_web::dev::AppService){//register将会在Service做为参数传入时,最终调用HttpServiceFactory::register将resource注册asyncfnhello()->implResponder{HttpResponse::Ok().body("Hello world!")}let __resource =::actix_web::Resource::new("/").name("hello").guard(::actix_web::guard::Get()).to(hello);::actix_web::dev::HttpServiceFactory::register(__resource, __config);}}#[allow(non_camel_case_types, missing_docs)]pubstructecho;impl::actix_web::dev::HttpServiceFactoryfor echo {fnregister(self, __config:&mutactix_web::dev::AppService){asyncfnecho(req_body:String)->implResponder{HttpResponse::Ok().body(req_body)}let __resource =::actix_web::Resource::new("/echo").name("echo").guard(::actix_web::guard::Post()).to(echo);::actix_web::dev::HttpServiceFactory::register(__resource, __config);}}asyncfnmanual_hello()->implResponder{HttpResponse::Ok().body("Hey there!")}fnmain()->std::io::Result<()>{<::actix_web::rt::System>::new().block_on(asyncmove{{HttpServer::new(||{App::new().service(hello).service(echo).route("/hey",web::get().to(manual_hello))}).bind(("127.0.0.1",8080))?.run().await}})}
Actix Web中的State
Actix web 框架下的State,即承载Server内部非请求数据的数据载体,不要被名称迷惑,它可以通过自定义数据来表示Server的状态,而更多的是用以共享全局性质的变量,通常来讲,如在开发时对数据库链接管理的数据库连接池,也可以是只读的base_url,在共享此类变量时需要注意,Actix Web Server针对每一条数据请求都是会独立出一条thread,所以共享时的同步尤为重要,所以在实现自定义的数据时,请注意使用同步原语。
代码示例:
...let db_pool =Data::new(db_pool);....app_data(db_pool.clone())...
State在闭包直接初始化时是无法做同步的,当开发者需要同步机制,则需要如上述代码一般,先在外部声明,再clone传入。
Actix Web中的scope
Scope表示范围,在服务中即表示统一前缀,举个例子:/user/login /user/info中的/user便是前缀,这方便开发者将api以restful形式拆分,更好的做分类,进一步的,开发者可以通过ServiceConfig 将具体的请求处理程序分配到不同的module中,使得整个程序代码更加的结构化。
useactix_web::{web,App,HttpResponse,HttpServer};// this function could be located in a different modulefnscoped_config(cfg:&mutweb::ServiceConfig){
cfg.service(web::resource("/test").route(web::get().to(||async{HttpResponse::Ok().body("test")})).route(web::head().to(HttpResponse::MethodNotAllowed)),);}// this function could be located in a different modulefnconfig(cfg:&mutweb::ServiceConfig){
cfg.service(web::resource("/app").route(web::get().to(||async{HttpResponse::Ok().body("app")})).route(web::head().to(HttpResponse::MethodNotAllowed)),);}#[actix_web::main]asyncfnmain()->std::io::Result<()>{HttpServer::new(||{App::new().configure(config).service(web::scope("/api").configure(scoped_config)).route("/",web::get().to(||async{HttpResponse::Ok().body("/")}),)}).bind(("127.0.0.1",8080))?.run().await}//ps: 例子来源于官文
Actix Web中的extractors
extractors在Acitx Web中是类型安全的,extractors提供了提取请求数据中为特定类型的不同方法,使得代码更加清晰安全.
Path
Path用于将请求路径上的信息转为自定义类型。
//具体的#[derive(Deserialize)]//自定义类型一定需要实现反序列化structInfo{
user_id:u32,
friend:String,}/// extract path info using serde#[get("/users/{user_id}/{friend}")]//宏中名称要和自定义类型中的名称对齐.asyncfnindex(info:web::Path<Info>)->Result<String>{Ok(format!("Welcome {}, user_id {}!",
info.friend, info.user_id
))}
Query
Query用于请求参数的提取,将其转换成具体的类型。
#[derive(Deserialize)]structInfo{
username:String,}//如果请求参数中并不包含需要提取的字段数据,则server将会返回404#[get("/")]asyncfnindex(info:web::Query<Info>)->String{format!("Welcome {}!", info.username)}
JSON
JSON 用于将请求中的json格式请求体转为具体的类型。
useactix_web::{post, web,App,HttpServer,Result};useserde::Deserialize;#[derive(Deserialize)]structInfo{
username:String,}/// deserialize `Info` from request's body#[post("/submit")]asyncfnsubmit(info:web::Json<Info>)->Result<String>{Ok(format!("Welcome {}!", info.username))}
URL-encoded form
用于将表单数据提取成具体的数据类型。
useactix_web::{post, web,App,HttpServer,Result};useserde::Deserialize;#[derive(Deserialize)]structFormData{
username:String,}/// extract form data using serde/// this handler gets called only if the content type is *x-www-form-urlencoded*/// and the content of the request could be deserialized to a `FormData` struct#[post("/")]asyncfnindex(form:web::Form<FormData>)->Result<String>{Ok(format!("Welcome {}!", form.username))}
涉及到更具体的可以参阅官方文档的Api Document
Actix Web架构摘要
总结
Actix Web 易用性高,性能出众,如果开发者想在生产环境中使用Rust做Http Server,其是值得一选的,在整体的开发框架中,State同步,提取和Connfigure 以及Handler的 布局设计是重要的。
“不论我们接受与否,一个不确定的时代已经到来”
版权归原作者 monkey_meng 所有, 如有侵权,请联系我们删除。