Rust 学习笔记 - Web 全栈开发2

384 阅读2分钟

Actix

Actix 是一个基于 Rust 的 web 框架,可以提供对 HTTP/1、HTTP/2,以及 TLS(HTTPS)的支持,设置还支持 WebSocket,而且速度非常快。

安装和使用

先创建一个项目:

cargo new webservice

webservice/Cargo.toml 添加 actix 依赖:

[dependencies]
actix-web = "3"

crate 官方地址

然后可以 build 一下,就会下载相关依赖:

cargo build

可能需要一点儿时间,尤其网络不是那么好的情况下,多 build 几次就行了。

按照 crate 官方文档的例子,我们可以搭建一个最简单的 web service:

use actix_web::{get, web, App, HttpServer, Responder};

#[get("/{id}/{name}/index.html")]
async fn index(web::Path((id, name)): web::Path<(u32, String)>) -> impl Responder {
    format!("Hello {}! id:{}", name, id)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(||
        App::new()
            .service(index)
        )
        .bind("127.0.0.1:8080")?
        .run()
        .await
}

然后访问 http://127.0.0.1:8080/1/eagle/index.html

rust-web4.jpg

获取请求参数

use actix_web::{get, web, App, HttpServer};
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
pub enum ResponseType {
   Token,
   Code
}

#[derive(Deserialize)]
pub struct AuthRequest {
   id: u64,
   response_type: ResponseType,
}

#[get("/api/v1/get")]
async fn get1(web::Query(info) : web::Query<AuthRequest>) -> String {
    format!("Authorization request for client with id={} and type={:?}!", info.id, info.response_type)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(||
        App::new()
            .service(get1)
        )
        .bind("127.0.0.1:8080")?
        .run()
        .await
}

访问 http://localhost:8080/api/v1/get?id=1&response_type=Token

访问效果如下:

rust-web5.jpg

获取 body 体的内容

webservice/Cargo.toml 添加 serde 依赖:

[dependencies]
serde = { version = "1.0.133", features = ["derive"] }
use actix_web::{web, App, HttpServer, post};
use serde::{Deserialize};

#[derive(Deserialize)]
struct FormData {
    name: String,
}

#[post("/api/v1/post")]
async fn post1(form: web::Form<FormData>) -> String {
    format!("Welcome {}!", form.name)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(||
        App::new()
            .service(post1)
        )
        .bind("127.0.0.1:8080")?
        .run()
        .await
}

访问效果如下:

rust-web6.jpg

返回 JSON 数据

use actix_web::{web, App, HttpServer, post, Result, Responder};
use serde::{Serialize, Deserialize};

#[derive(Deserialize)]
struct FormData {
    name: String,
    age: u8,
}

#[derive(Serialize)]
struct SomeForm {
    name: String,
    age: u8
}

#[post("/api/v1/post")]
async fn post1(form: web::Form<FormData>) -> Result<impl Responder> {
    let obj = SomeForm {
        name: form.name.to_string(),
        age: form.age,
    };
    Ok(web::Json(obj))
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(||
        App::new()
            .service(post1)
        )
        .bind("127.0.0.1:8080")?
        .run()
        .await
}

访问效果:

rust-web7.jpg

静态服务

webservice 目录下添加 public 目录,再添加一些 html 文件。

webservice/Cargo.toml 添加 actix-files 依赖:

[dependencies]
actix-files = "0.5.0"
use std::env;

use actix_files as fs;
use actix_web::{App, HttpServer};

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        let default_path = format!("{}/public", env!("CARGO_MANIFEST_DIR"));
        let public_path = env::var("PUBLIC_PATH").unwrap_or(default_path);
        App::new().service(fs::Files::new("/", &public_path).index_file("index.html"))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

访问效果:

rust-web8.jpg