行业知识
Rust web开发 ActixWeb 入门
Rust Actix Web 入门
目前,Actix Web 仍然是 Rust Web 后端生态系统中极其强大的竞争对手。尽管之前的事件可能对其产生影响,但它仍然很强大,并且是 Rust 中最受推荐的 Web 框架之一。最初基于同名的 actor 框架 ( actix ),后来它已经消失,并且 actix 现在仅用于 websocket 端点。
本文将主要讨论 v4.4。
Actix Web 入门
首先,使用 cargo init example-api 生成项目,将 cd 到该文件夹中,然后使用以下命令将 actix-web crate 添加到项目中:
cargo add actix-web
现在已经准备好开始了!如果想复制样板文件以直接编写您的应用程序,如下所示:
use actix_web::{web, App, HttpServer, Responder};#[get("/")]async fn index() -> impl Responder { "Hello world!"}#[actix_web::main]async fn main() -> std::io::Result { HttpServer::new(|| { App::new().service( // prefixes all resources and routes attached to it... web::scope("/") // ...so this handles requests for `GET /app/index.html` .route("/", web::get().to(index)), ) }) .bind(("127.0.0.1", 8080))? .run() .await} Actix Web 中的路由
使用 Actix Web 时,大多数返回 实现actix_web::Responder trait 的函数都可以用作路由。请参阅下面的基本 Hello World 示例:
#[get("/")]async fn index() -> impl Responder { "Hello world!"} 然后可以将此处理函数输入到 actix_web::App 中,然后将其作为参数传递给 HttpServer :
#[actix_web::main]async fn main() -> std::io::Result { HttpServer::new(|| { App::new().service( // prefixes all resources and routes attached to it... web::scope("/") // ...so this handles requests for the base route .route("/index.html", web::get().to(index)), ) }) .bind(("127.0.0.1", 8080))? .run() .await} 现在,每当您访问 /index.html 时,它都应该返回“Hello world!”。但是,如果您想创建多个 子路由 类型,然后最后将它们全部合并到应用程序中,您可能会发现这种方法有点缺乏。在这种情况下,您将需要 ServiceConfig 类型,您也可以这样写:
use actix_web::{web, App, HttpResponse};// this function could be located in different modulefn config(cfg: &mut web::ServiceConfig) { cfg.service(web::resource("/test") .route(web::get().to(|| HttpResponse::Ok())) .route(web::head().to(|| HttpResponse::MethodNotAllowed())) );}#[actix_web::main]async fn main() -> std::io::Result { HttpServer::new(|| { App::new().configure(config) }) .bind(("127.0.0.1", 8080))? .run() .await} Actix Web 中的提取器(Extractor)正是这样的:实现类型安全的请求,当传递到处理函数时,将尝试从处理函数的请求中提取相关数据。例如, actix_web::web::Json 提取器将尝试从请求正文中提取 JSON。然而,要成功反序列化 JSON,您需要使用 serde 包 - 最好与 derive 函数一起使用,为您的结构添加自动反序列化和序列化派生宏。您可以通过执行以下命令来安装 serde:
cargo add serde -F derive
现在可以将其用作派生宏,如下所示:
use actix_web::web;use serde::Deserialize;#[derive(Deserialize)]struct Info { username: String,}// deserialize `Info` from request's body#[post("/submit")]async fn submit(info: web::Json) -> String { format!("Welcome {}!", info.username)} Actix Web 还支持 paths, queries and forms。您还需要在此处使用 serde - 尽管对于paths,您还需要使用 Actix Web 路由宏来声明路径参数的确切位置。我们可以在下面找到所有这 3 种方法的示例:
#[derive(Deserialize)]struct Info { username: String,}// extract path info using serde#[get("/users/{username}")] // String { format!("Welcome {}!", info.username)}// data is passed in here through query parameters in the URL// for example, google.com/?hello=world#[get("/")]async fn index(info: web::Query) -> String { format!("Welcome {}!", info.username)}// data is passed into the Form extractor through a HTML Form element#[post("/")]async fn index(form: web::Form) -> actix_web::Result { Ok(format!("Welcome {}!", form.username))} 有兴趣编写自己的提取器吗?你可以做到的!编写自己的提取器只需要实现 FromRequest 特征。查看 HTTP 标头提取器的这段代码,它向您展示了它的具体工作原理:
use actix_web::dev::Payload;use actix_web::{FromRequest, http::header::Header as ParseHeader, HttpRequest, error::ParseError};#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]pub struct Header(pub T);impl FromRequest for Headerwhere T: ParseHeader,{ type Error = ParseError; type Future = Ready; #[inline] fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { match T::parse(req) { Ok(header) => ok(Header(header)), Err(e) => err(e), } }} 请注意, T: ParseHeader trait 约束 特定于此特征实现,因为为了使header有效,它需要能够成功解析为header,并在实现 actix_web::error::Error 。虽然我们也有 extract 作为提供的方法,但 from_request 是这里唯一需要实现的方法,它返回 Self::Future 。也就是说,我们需要返回一个 已准备好等待的结果(ready to be awaited) - 您可以在此处找到有关 Ready 结构的更多信息。其他提取器(例如 JSON 提取器)也允许您更改其配置 - 您可以在此文档页面中找到有关它的更多信息。
一般来说,responses只需要实现 actix_web::Responder trait就能够响应。尽管在实际响应类型方面已经有广泛的实现,因此您通常不需要实现自己的类型,但在某些特定的用例中这可能会很有帮助;例如,能够记录您的应用程序可能具有的所有类型的响应。
连接到数据库
通常,在设置数据库时,您可能需要设置数据库连接:
use sqlx::PgPoolOptions;#[actix_web::main]async fn main() -> std::io::Result { let dbconnection = PgPoolOptions::new() .max_connections(5) .connect(r#""#).await; //... rest of your code} 然后,您需要配置自己的 Postgres 实例,无论是本地安装在计算机上、通过 Docker 还是其他方式配置。但是,使用 Shuttle,我们可以消除这种情况,因为运行时会为您配置数据库:
use actix_web::{get, web::ServiceConfig};use shuttle_actix_web::ShuttleActixWeb;#[shuttle_runtime::main]async fn actixweb( #[shuttle_shared_db::Postgres] pool: PgPool,) -> ShuttleActixWeb
上一篇:手机下载空调遥控器的简易指南
下一篇:nat服务器怎么设置?