国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Rust Web 全棧開發(fā)之 Actix 嘗鮮并構(gòu)建REST API

這篇具有很好參考價值的文章主要介紹了Rust Web 全棧開發(fā)之 Actix 嘗鮮并構(gòu)建REST API。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

Rust Web 全棧開發(fā)之 Actix 嘗鮮并構(gòu)建REST API

一、Actix 嘗鮮

需要使用的crate

  • actix-web v4.3.1
  • actix-rt v2.8.0
~ via ?? base
? cd rust

~/rust via ?? base
? cargo new ws  # workspace
     Created binary (application) `ws` package

~/rust via ?? base
? cd ws

ws on  master [?] is ?? 0.1.0 via ?? 1.67.1 via ?? base
? c

ws on  master [?] is ?? 0.1.0 via ?? 1.67.1 via ?? base
?

ws on  master [?] is ?? 0.1.0 via ?? 1.67.1 via ?? base
? cargo new webservice
     Created binary (application) `webservice` package

ws on  master [?] via ?? 1.67.1 via ?? base
?

目錄

ws on  master [?] via ?? 1.67.1 via ?? base
? tree -I target
.
├── Cargo.lock
├── Cargo.toml
├── src
│?? └── main.rs
└── webservice
    ├── Cargo.toml
    └── src
        ├── bin
        │?? └── server1.rs
        └── main.rs

5 directories, 6 files

ws on  master [?] via ?? 1.67.1 via ?? base
?

Cargo.toml

[workspace]
members = ["webservice"]

webservice/Cargo.toml

[package]
name = "webservice"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
actix-web = "4.3.1"
actix-rt = "2.8.0"

[[bin]]
name = "server1"

webservice/src/bin/server1.rs

use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use std::io;

// 配置 route
pub fn general_routes(cfg: &mut web::ServiceConfig) {
    cfg.route("/health", web::get().to(health_check_handler));
}

// 配置 handler
pub async fn health_check_handler() -> impl Responder {
    HttpResponse::Ok().json("Actix Web Service is running!")
}

// 實例化 HTTP Server 并運行
#[actix_rt::main]
async fn main() -> io::Result<()> {
    // 構(gòu)建 App 配置 route
    let app = move || App::new().configure(general_routes);

    // 運行 HTTP Server
    HttpServer::new(app).bind("127.0.0.1:3000")?.run().await
}

運行

ws on  master [?] via ?? 1.67.1 via ?? base 
? cargo run -p webservice --bin server1
   Compiling actix-rt v2.8.0
   Compiling actix-http v3.3.1
   Compiling actix-server v2.2.0
   Compiling actix-web v4.3.1
   Compiling webservice v0.1.0 (/Users/qiaopengjun/rust/ws/webservice)
    Finished dev [unoptimized + debuginfo] target(s) in 4.26s
     Running `target/debug/server1`


ws on  master [?] via ?? 1.67.1 via ?? base 
? cd webservice                        

ws/webservice on  master [?] is ?? 0.1.0 via ?? 1.67.1 via ?? base 
? cargo run --bin server1              
    Finished dev [unoptimized + debuginfo] target(s) in 0.15s
     Running `/Users/qiaopengjun/rust/ws/target/debug/server1`

Actix的基本組件

客戶端瀏覽器 互聯(lián)網(wǎng) Actix HTTP Server

Actix的并發(fā)(concurrency)

  • Actix支持兩類并發(fā):
    • 異步I/O:給定的OS原生線程在等待I/O時執(zhí)行其他任務(wù)(例如偵聽網(wǎng)絡(luò)連接)
    • 多線程并行:默認情況下啟動OS原生線程的數(shù)量與系統(tǒng)邏輯CPU數(shù)量相同

二、構(gòu)建REST API

需要使用的crate

  • serde, v1.0.163
  • chrono, v0.4.24

構(gòu)建的內(nèi)容

  • POST: /courses
  • GET:/courses/teacher_id
  • GET:/courses/teacher_id/course_id

相關(guān)文件

  • bin/teacher-service.rs
  • models.rs
  • state.rs
  • routers.rs
  • handlers.rs

目錄

ws on  master [?] via ?? 1.67.1 via ?? base 
? tree -I target
.
├── Cargo.lock
├── Cargo.toml
├── src
│   └── main.rs
└── webservice
    ├── Cargo.toml
    └── src
        ├── bin
        │   ├── server1.rs
        │   └── teacher-service.rs
        ├── handlers.rs
        ├── main.rs
        ├── models.rs
        ├── routers.rs
        └── state.rs

5 directories, 11 files

ws on  master [?] via ?? 1.67.1 via ?? base 
? 

webservice/Cargo.toml

[package]
name = "webservice"
version = "0.1.0"
edition = "2021"
default-run = "teacher-service"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
actix-web = "4.3.1"
actix-rt = "2.8.0"

[[bin]]
name = "server1"

[[bin]]
name = "teacher-service"

webservice/src/bin/teacher-service.rs

use actix_web::{web, App, HttpServer};
use std::io;
use std::sync::Mutex;

#[path = "../handlers.rs"]
mod handlers;
#[path = "../routers.rs"]
mod routers;
#[path = "../state.rs"]
mod state;

use routers::*;
use state::AppState;

#[actix_rt::main]
async fn main() -> io::Result<()> {
    let shared_data = web::Data::new(AppState {
        health_check_response: "I'm Ok.".to_string(),
        visit_count: Mutex::new(0),
    });
    let app = move || {
        App::new()
            .app_data(shared_data.clone())
            .configure(general_routes)
    };

    HttpServer::new(app).bind("127.0.0.1:3000")?.run().await
}

webservice/src/handlers.rs

use super::state::AppState;
use actix_web::{web, HttpResponse};

pub async fn health_check_handler(app_state: web::Data<AppState>) -> HttpResponse {
    let health_check_response = &app_state.health_check_response;
    let mut visit_count = app_state.visit_count.lock().unwrap();
    let response = format!("{} {} times", health_check_response, visit_count);
    *visit_count += 1;
    HttpResponse::Ok().json(&response)
}

webservice/src/routers.rs

use super::handlers::*;
use actix_web::web;

pub fn general_routes(cfg: &mut web::ServiceConfig) {
    cfg.route("/health", web::get().to(health_check_handler));
}

webservice/src/state.rs

use std::sync::Mutex;

pub struct AppState {
    pub health_check_response: String,
    pub visit_count: Mutex<u32>,
}

運行

ws on  master [?] via ?? 1.67.1 via ?? base 
? cd webservice 

ws/webservice on  master [?] is ?? 0.1.0 via ?? 1.67.1 via ?? base 
? cargo run              
   Compiling webservice v0.1.0 (/Users/qiaopengjun/rust/ws/webservice)
    Finished dev [unoptimized + debuginfo] target(s) in 1.49s
     Running `/Users/qiaopengjun/rust/ws/target/debug/teacher-service`

請求訪問

ws on  master [?] via ?? 1.67.1 via ?? base 
? curl localhost:3000/health 
"I'm Ok. 0 times"%                                                                                           

ws on  master [?] via ?? 1.67.1 via ?? base 
? curl localhost:3000/health
"I'm Ok. 1 times"%                                                                                           

ws on  master [?] via ?? 1.67.1 via ?? base 
? curl localhost:3000/health
"I'm Ok. 2 times"%                                                                                           

ws on  master [?] via ?? 1.67.1 via ?? base 
? 

webservice/Cargo.toml

[package]
name = "webservice"
version = "0.1.0"
edition = "2021"
default-run = "teacher-service"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
actix-web = "4.3.1"
actix-rt = "2.8.0"
serde = { version = "1.0.163", features = ["derive"] }
chrono = { version = "0.4.24", features = ["serde"] }

[[bin]]
name = "server1"

[[bin]]
name = "teacher-service"

webservice/src/models.rs

use actix_web::web;
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct Course {
    pub teacher_id: usize,
    pub id: Option<usize>,
    pub name: String,
    pub time: Option<NaiveDateTime>,
}
impl From<web::Json<Course>> for Course {
    fn from(course: web::Json<Course>) -> Self {
        Course {
            teacher_id: course.teacher_id,
            id: course.id,
            name: course.name.clone(),
            time: course.time,
        }
    }
}

webservice/src/state.rs

use super::models::Course;
use std::sync::Mutex;

pub struct AppState {
    pub health_check_response: String,
    pub visit_count: Mutex<u32>,
    pub courses: Mutex<Vec<Course>>,
}

webservice/src/bin/teacher-service.rs

use actix_web::{web, App, HttpServer};
use std::io;
use std::sync::Mutex;

#[path = "../handlers.rs"]
mod handlers;
#[path = "../models.rs"]
mod models;
#[path = "../routers.rs"]
mod routers;
#[path = "../state.rs"]
mod state;

use routers::*;
use state::AppState;

#[actix_rt::main]
async fn main() -> io::Result<()> {
    let shared_data = web::Data::new(AppState {
        health_check_response: "I'm Ok.".to_string(),
        visit_count: Mutex::new(0),
        courses: Mutex::new(vec![]),
    });
    let app = move || {
        App::new()
            .app_data(shared_data.clone())
            .configure(general_routes)
    };

    HttpServer::new(app).bind("127.0.0.1:3000")?.run().await
}

運行并訪問

ws/webservice on  master [?] is ?? 0.1.0 via ?? 1.67.1 via ?? base took 2h 37m 54.5s 
? cargo run
   Compiling webservice v0.1.0 (/Users/qiaopengjun/rust/ws/webservice)
    Finished dev [unoptimized + debuginfo] target(s) in 1.54s
     Running `/Users/qiaopengjun/rust/ws/target/debug/teacher-service`


ws on  master [?] via ?? 1.67.1 via ?? base 
? curl localhost:3000/health
"I'm Ok. 0 times"%                                                                                           

ws on  master [?] via ?? 1.67.1 via ?? base 
? 

添加課程信息

webservice/src/routers.rs

use super::handlers::*;
use actix_web::web;

pub fn general_routes(cfg: &mut web::ServiceConfig) {
    cfg.route("/health", web::get().to(health_check_handler));
}

pub fn course_routes(cfg: &mut web::ServiceConfig) {
    // courses 是一套資源的根路徑
    cfg.service(web::scope("/courses").route("/", web::post().to(new_course)));
}

webservice/src/bin/teacher-service.rs

use actix_web::{web, App, HttpServer};
use std::io;
use std::sync::Mutex;

#[path = "../handlers.rs"]
mod handlers;
#[path = "../models.rs"]
mod models;
#[path = "../routers.rs"]
mod routers;
#[path = "../state.rs"]
mod state;

use routers::*;
use state::AppState;

#[actix_rt::main]
async fn main() -> io::Result<()> {
    let shared_data = web::Data::new(AppState {
        health_check_response: "I'm Ok.".to_string(),
        visit_count: Mutex::new(0),
        courses: Mutex::new(vec![]),
    });
    let app = move || {
        App::new()
            .app_data(shared_data.clone())
            .configure(general_routes)
            .configure(course_routes) // 路由注冊
    };

    HttpServer::new(app).bind("127.0.0.1:3000")?.run().await
}

webservice/src/handlers.rs

use super::state::AppState;
use actix_web::{web, HttpResponse};

pub async fn health_check_handler(app_state: web::Data<AppState>) -> HttpResponse {
    let health_check_response = &app_state.health_check_response;
    let mut visit_count = app_state.visit_count.lock().unwrap();
    let response = format!("{} {} times", health_check_response, visit_count);
    *visit_count += 1;
    HttpResponse::Ok().json(&response)
}

use super::models::Course;
use chrono::Utc;

pub async fn new_course(
    new_course: web::Json<Course>,
    app_state: web::Data<AppState>,
) -> HttpResponse {
    println!("Received new course");
    let course_count = app_state
        .courses
        .lock()
        .unwrap()
        .clone()
        .into_iter()
        .filter(|course| course.teacher_id == new_course.teacher_id)
        .collect::<Vec<Course>>()
        .len();
    let new_course = Course {
        // 創(chuàng)建一個新的課程
        teacher_id: new_course.teacher_id,
        id: Some(course_count + 1),
        name: new_course.name.clone(),
        time: Some(Utc::now().naive_utc()), // 當(dāng)前時間
    };
    app_state.courses.lock().unwrap().push(new_course);
    HttpResponse::Ok().json("Course added")
}

#[cfg(test)]
mod tests {
    use super::*;
    use actix_web::http::StatusCode;
    use std::sync::Mutex;

    #[actix_rt::test] // 異步測試
    async fn post_course_test() {
        let course = web::Json(Course {
            teacher_id: 1,
            name: "Test course".into(),
            id: None,
            time: None,
        });
        let app_state: web::Data<AppState> = web::Data::new(AppState {
            health_check_response: "".to_string(),
            visit_count: Mutex::new(0),
            courses: Mutex::new(vec![]),
        });
        let resp = new_course(course, app_state).await;
        assert_eq!(resp.status(), StatusCode::OK);
    }
}


運行并測試

ws/webservice on  master [?] is ?? 0.1.0 via ?? 1.67.1 via ?? base took 41m 26.8s 
? cargo test        
   Compiling webservice v0.1.0 (/Users/qiaopengjun/rust/ws/webservice)
    Finished test [unoptimized + debuginfo] target(s) in 0.68s
     Running unittests src/bin/server1.rs (/Users/qiaopengjun/rust/ws/target/debug/deps/server1-db3d08c1708d3a7c)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running unittests src/bin/teacher-service.rs (/Users/qiaopengjun/rust/ws/target/debug/deps/teacher_service-41d6f77eb4f5c36e)

running 1 test
test handlers::tests::post_course_test ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running unittests src/main.rs (/Users/qiaopengjun/rust/ws/target/debug/deps/webservice-fd79900ffad88ae5)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s


ws/webservice on  master [?] is ?? 0.1.0 via ?? 1.67.1 via ?? base took 2.7s 
? cargo run 
   Compiling webservice v0.1.0 (/Users/qiaopengjun/rust/ws/webservice)
    Finished dev [unoptimized + debuginfo] target(s) in 1.04s
     Running `/Users/qiaopengjun/rust/ws/target/debug/teacher-service`
Received new course


ws on  master [?] via ?? 1.67.1 via ?? base 
? curl -X POST localhost:3000/courses/ -H "Content-Type: application/json" -d '{"teacher_id":1, "name":"First course"}' 
"Course added"%                                                                                                                   

ws on  master [?] via ?? 1.67.1 via ?? base 
? 

查詢所有課程信息

webservice/src/routers.rs

use super::handlers::*;
use actix_web::web;

pub fn general_routes(cfg: &mut web::ServiceConfig) {
    cfg.route("/health", web::get().to(health_check_handler));
}

pub fn course_routes(cfg: &mut web::ServiceConfig) {
    // courses 是一套資源的根路徑
    cfg.service(
        web::scope("/courses")
            .route("/", web::post().to(new_course))
            .route("/{user_id}", web::get().to(get_courses_for_tescher)),
    );
}

webservice/src/handlers.rs

use super::state::AppState;
use actix_web::{web, HttpResponse};

pub async fn health_check_handler(app_state: web::Data<AppState>) -> HttpResponse {
    let health_check_response = &app_state.health_check_response;
    let mut visit_count = app_state.visit_count.lock().unwrap();
    let response = format!("{} {} times", health_check_response, visit_count);
    *visit_count += 1;
    HttpResponse::Ok().json(&response)
}

use super::models::Course;
use chrono::Utc;

pub async fn new_course(
    new_course: web::Json<Course>,
    app_state: web::Data<AppState>,
) -> HttpResponse {
    println!("Received new course");
    let course_count = app_state
        .courses
        .lock()
        .unwrap()
        .clone()
        .into_iter()
        .filter(|course| course.teacher_id == new_course.teacher_id)
        .collect::<Vec<Course>>()
        .len();
    let new_course = Course {
        // 創(chuàng)建一個新的課程
        teacher_id: new_course.teacher_id,
        id: Some(course_count + 1),
        name: new_course.name.clone(),
        time: Some(Utc::now().naive_utc()), // 當(dāng)前時間
    };
    app_state.courses.lock().unwrap().push(new_course);
    HttpResponse::Ok().json("Course added")
}

pub async fn get_courses_for_tescher(
    app_state: web::Data<AppState>,
    params: web::Path<(usize)>,
) -> HttpResponse {
    let teacher_id: usize = params.into_inner();

    let filtered_courses = app_state
        .courses
        .lock()
        .unwrap()
        .clone()
        .into_iter()
        .filter(|course| course.teacher_id == teacher_id)
        .collect::<Vec<Course>>();

    if filtered_courses.len() > 0 {
        HttpResponse::Ok().json(filtered_courses)
    } else {
        HttpResponse::Ok().json("No courses found for teacher".to_string())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use actix_web::http::StatusCode;
    use std::sync::Mutex;

    #[actix_rt::test] // 異步測試
    async fn post_course_test() {
        let course = web::Json(Course {
            teacher_id: 1,
            name: "Test course".into(),
            id: None,
            time: None,
        });
        let app_state: web::Data<AppState> = web::Data::new(AppState {
            health_check_response: "".to_string(),
            visit_count: Mutex::new(0),
            courses: Mutex::new(vec![]),
        });
        let resp = new_course(course, app_state).await;
        assert_eq!(resp.status(), StatusCode::OK);
    }

    #[actix_rt::test]
    async fn get_all_course_success() {
        let app_state: web::Data<AppState> = web::Data::new(AppState {
            health_check_response: "".to_string(),
            visit_count: Mutex::new(0),
            courses: Mutex::new(vec![]),
        });
        let teacher_id: web::Path<(usize)> = web::Path::from((1));
        let resp = get_courses_for_tescher(app_state, teacher_id).await;
        assert_eq!(resp.status(), StatusCode::OK);
    }
}

測試

ws/webservice on  master [?] is ?? 0.1.0 via ?? 1.67.1 via ?? base took 1m 1.8s 
? cargo test
   Compiling webservice v0.1.0 (/Users/qiaopengjun/rust/ws/webservice)
warning: unnecessary parentheses around type
  --> webservice/src/bin/../handlers.rs:42:23
   |
42 |     params: web::Path<(usize)>,
   |                       ^     ^
   |
   = note: `#[warn(unused_parens)]` on by default
help: remove these parentheses
   |
42 -     params: web::Path<(usize)>,
42 +     params: web::Path<usize>,
   |

warning: unnecessary parentheses around type
  --> webservice/src/bin/../handlers.rs:92:35
   |
92 |         let teacher_id: web::Path<(usize)> = web::Path::from((1));
   |                                   ^     ^
   |
help: remove these parentheses
   |
92 -         let teacher_id: web::Path<(usize)> = web::Path::from((1));
92 +         let teacher_id: web::Path<usize> = web::Path::from((1));
   |

warning: unnecessary parentheses around function argument
  --> webservice/src/bin/../handlers.rs:92:62
   |
92 |         let teacher_id: web::Path<(usize)> = web::Path::from((1));
   |                                                              ^ ^
   |
help: remove these parentheses
   |
92 -         let teacher_id: web::Path<(usize)> = web::Path::from((1));
92 +         let teacher_id: web::Path<(usize)> = web::Path::from(1);
   |

warning: `webservice` (bin "teacher-service" test) generated 3 warnings (run `cargo fix --bin "teacher-service" --tests` to apply 3 suggestions)
    Finished test [unoptimized + debuginfo] target(s) in 0.60s
     Running unittests src/bin/server1.rs (/Users/qiaopengjun/rust/ws/target/debug/deps/server1-db3d08c1708d3a7c)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running unittests src/bin/teacher-service.rs (/Users/qiaopengjun/rust/ws/target/debug/deps/teacher_service-41d6f77eb4f5c36e)

running 2 tests
test handlers::tests::post_course_test ... ok
test handlers::tests::get_all_course_success ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running unittests src/main.rs (/Users/qiaopengjun/rust/ws/target/debug/deps/webservice-fd79900ffad88ae5)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s


ws/webservice on  master [?] is ?? 0.1.0 via ?? 1.67.1 via ?? base 
? 


ws/webservice on  master [?] is ?? 0.1.0 via ?? 1.67.1 via ?? base 
? cargo run 
   Compiling webservice v0.1.0 (/Users/qiaopengjun/rust/ws/webservice)
warning: unnecessary parentheses around type
  --> webservice/src/bin/../handlers.rs:42:23
   |
42 |     params: web::Path<(usize)>,
   |                       ^     ^
   |
   = note: `#[warn(unused_parens)]` on by default
help: remove these parentheses
   |
42 -     params: web::Path<(usize)>,
42 +     params: web::Path<usize>,
   |

warning: `webservice` (bin "teacher-service") generated 1 warning (run `cargo fix --bin "teacher-service"` to apply 1 suggestion)
    Finished dev [unoptimized + debuginfo] target(s) in 1.54s
     Running `/Users/qiaopengjun/rust/ws/target/debug/teacher-service`
Received new course
Received new course
Received new course



ws on  master [?] via ?? 1.67.1 via ?? base 
? curl -X POST localhost:3000/courses/ -H "Content-Type: application/json" -d '{"teacher_id":1, "name":"First course"}'
"Course added"%                                                                                                                   

ws on  master [?] via ?? 1.67.1 via ?? base 
? curl -X POST localhost:3000/courses/ -H "Content-Type: application/json" -d '{"teacher_id":1, "name":"Second course"}'
"Course added"%                                                                                                                   

ws on  master [?] via ?? 1.67.1 via ?? base 
? curl -X POST localhost:3000/courses/ -H "Content-Type: application/json" -d '{"teacher_id":1, "name":"Third course"}' 
"Course added"%                                                                                                                   

ws on  master [?] via ?? 1.67.1 via ?? base 
? curl localhost:3000/courses/1                                                                                        
[{"teacher_id":1,"id":1,"name":"First course","time":"2023-05-28T11:16:50.312820"},{"teacher_id":1,"id":2,"name":"Second course","time":"2023-05-28T11:17:08.358168"},{"teacher_id":1,"id":3,"name":"Third course","time":"2023-05-28T11:17:23.295881"}]%           

ws on  master [?] via ?? 1.67.1 via ?? base 
? 

查詢單個課程信息

webservice/src/routers.rs

use super::handlers::*;
use actix_web::web;

pub fn general_routes(cfg: &mut web::ServiceConfig) {
    cfg.route("/health", web::get().to(health_check_handler));
}

pub fn course_routes(cfg: &mut web::ServiceConfig) {
    // courses 是一套資源的根路徑
    cfg.service(
        web::scope("/courses")
            .route("/", web::post().to(new_course))
            .route("/{user_id}", web::get().to(get_courses_for_tescher))
            .route("/{user_id}/{course_id}", web::get().to(get_courses_detail)),
    );
}

webservice/src/handlers.rs

use super::state::AppState;
use actix_web::{web, HttpResponse};

pub async fn health_check_handler(app_state: web::Data<AppState>) -> HttpResponse {
    let health_check_response = &app_state.health_check_response;
    let mut visit_count = app_state.visit_count.lock().unwrap();
    let response = format!("{} {} times", health_check_response, visit_count);
    *visit_count += 1;
    HttpResponse::Ok().json(&response)
}

use super::models::Course;
use chrono::Utc;

pub async fn new_course(
    new_course: web::Json<Course>,
    app_state: web::Data<AppState>,
) -> HttpResponse {
    println!("Received new course");
    let course_count = app_state
        .courses
        .lock()
        .unwrap()
        .clone()
        .into_iter()
        .filter(|course| course.teacher_id == new_course.teacher_id)
        .collect::<Vec<Course>>()
        .len();
    let new_course = Course {
        // 創(chuàng)建一個新的課程
        teacher_id: new_course.teacher_id,
        id: Some(course_count + 1),
        name: new_course.name.clone(),
        time: Some(Utc::now().naive_utc()), // 當(dāng)前時間
    };
    app_state.courses.lock().unwrap().push(new_course);
    HttpResponse::Ok().json("Course added")
}

pub async fn get_courses_for_tescher(
    app_state: web::Data<AppState>,
    params: web::Path<usize>,
) -> HttpResponse {
    let teacher_id: usize = params.into_inner();

    let filtered_courses = app_state
        .courses
        .lock()
        .unwrap()
        .clone()
        .into_iter()
        .filter(|course| course.teacher_id == teacher_id)
        .collect::<Vec<Course>>();

    if filtered_courses.len() > 0 {
        HttpResponse::Ok().json(filtered_courses)
    } else {
        HttpResponse::Ok().json("No courses found for teacher".to_string())
    }
}

pub async fn get_courses_detail(
    app_state: web::Data<AppState>,
    params: web::Path<(usize, usize)>,
) -> HttpResponse {
    let (teacher_id, course_id) = params.into_inner();
    let selected_course = app_state
        .courses
        .lock()
        .unwrap()
        .clone()
        .into_iter()
        .find(|x| x.teacher_id == teacher_id && x.id == Some(course_id))
        .ok_or("Course not found"); // Option 類型 轉(zhuǎn)化成 Result<T, E> 類型

    if let Ok(course) = selected_course {
        HttpResponse::Ok().json(course)
    } else {
        HttpResponse::Ok().json("Course not found".to_string())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use actix_web::http::StatusCode;
    use std::sync::Mutex;

    #[actix_rt::test] // 異步測試
    async fn post_course_test() {
        let course = web::Json(Course {
            teacher_id: 1,
            name: "Test course".into(),
            id: None,
            time: None,
        });
        let app_state: web::Data<AppState> = web::Data::new(AppState {
            health_check_response: "".to_string(),
            visit_count: Mutex::new(0),
            courses: Mutex::new(vec![]),
        });
        let resp = new_course(course, app_state).await;
        assert_eq!(resp.status(), StatusCode::OK);
    }

    #[actix_rt::test]
    async fn get_all_course_success() {
        let app_state: web::Data<AppState> = web::Data::new(AppState {
            health_check_response: "".to_string(),
            visit_count: Mutex::new(0),
            courses: Mutex::new(vec![]),
        });
        let teacher_id: web::Path<usize> = web::Path::from(1);
        let resp = get_courses_for_tescher(app_state, teacher_id).await;
        assert_eq!(resp.status(), StatusCode::OK);
    }

    #[actix_rt::test]
    async fn get_one_course_success() {
        let app_state: web::Data<AppState> = web::Data::new(AppState {
            health_check_response: "".to_string(),
            visit_count: Mutex::new(0),
            courses: Mutex::new(vec![]),
        });
        let params: web::Path<(usize, usize)> = web::Path::from((1, 1));
        let resp = get_courses_detail(app_state, params).await;
        assert_eq!(resp.status(), StatusCode::OK);
    }
}

運行測試文章來源地址http://www.zghlxwxcb.cn/news/detail-462401.html

ws/webservice on  master [?] is ?? 0.1.0 via ?? 1.67.1 via ?? base took 18m 27.8s 
? cargo test
   Compiling webservice v0.1.0 (/Users/qiaopengjun/rust/ws/webservice)
    Finished test [unoptimized + debuginfo] target(s) in 1.02s
     Running unittests src/bin/server1.rs (/Users/qiaopengjun/rust/ws/target/debug/deps/server1-db3d08c1708d3a7c)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running unittests src/bin/teacher-service.rs (/Users/qiaopengjun/rust/ws/target/debug/deps/teacher_service-41d6f77eb4f5c36e)

running 3 tests
test handlers::tests::get_one_course_success ... ok
test handlers::tests::get_all_course_success ... ok
test handlers::tests::post_course_test ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running unittests src/main.rs (/Users/qiaopengjun/rust/ws/target/debug/deps/webservice-fd79900ffad88ae5)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s


ws/webservice on  master [?] is ?? 0.1.0 via ?? 1.67.1 via ?? base 
? cargo run                                                                                                             
   Compiling webservice v0.1.0 (/Users/qiaopengjun/rust/ws/webservice)
    Finished dev [unoptimized + debuginfo] target(s) in 0.86s
     Running `/Users/qiaopengjun/rust/ws/target/debug/teacher-service`
Received new course
Received new course


ws on  master [?] via ?? 1.67.1 via ?? base 
? curl -X POST localhost:3000/courses/ -H "Content-Type: application/json" -d '{"teacher_id":1, "name":"First course"}' 
"Course added"%                                                                                                                   

ws on  master [?] via ?? 1.67.1 via ?? base 
? curl -X POST localhost:3000/courses/ -H "Content-Type: application/json" -d '{"teacher_id":1, "name":"Second course"}'
"Course added"%                                                                                                                   

ws on  master [?] via ?? 1.67.1 via ?? base 
? curl localhost:3000/courses/1/1                                                                                       
{"teacher_id":1,"id":1,"name":"First course","time":"2023-05-28T11:35:49.260822"}%                                                

ws on  master [?] via ?? 1.67.1 via ?? base 
? 

到了這里,關(guān)于Rust Web 全棧開發(fā)之 Actix 嘗鮮并構(gòu)建REST API的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Rust Web 全棧開發(fā)之增加教師管理功能

    Actix HTTP Server Actix App Routes GET /teachers GET / teachers / POST /teachers PUT /teachers / DELETE /teachers / Handlers get_all_teachers get_teacher_details post_new_teacher update_teacher_details delete_teacher DB Access get_all_teachers_db get_teacher_details_db post_new_teacher_db update_teacher_details_db delete_teacher_db 項目目錄 webservice/sr

    2024年02月07日
    瀏覽(27)
  • Rust Web 全棧開發(fā)之 Web Service 中的錯誤處理

    數(shù)據(jù)庫 數(shù)據(jù)庫錯誤 串行化 serde 錯誤 I/O 操作 I/O 錯誤 Actix-Web 庫 Actix 錯誤 用戶非法輸入 用戶非法輸入錯誤 編程語言常用的兩種錯誤處理方式: 異常 返回值( Rust 使用這種) Rust 希望開發(fā)者顯式的處理錯誤,因此,可能出錯的函數(shù)返回Result 枚舉類型,其定義如下: 例子 在

    2024年02月07日
    瀏覽(22)
  • Rust Web 全棧開發(fā)之自建TCP、HTTP Server

    Rust 編程語言入門 https://www.bilibili.com/video/BV1hp4y1k7SV WebService 服務(wù)器端Web App 客戶端Web App(WebAssembly) Web框架:Actix 數(shù)據(jù)庫:PostgreSQL 數(shù)據(jù)庫連接:SQLx 全部使用純Rust編寫! 編寫TCP Server和Client 標(biāo)準庫的std::net模塊,提供網(wǎng)絡(luò)基本功能 支持TCP和UDP通信 TcpListener和TcpStream 創(chuàng)建項目

    2024年02月06日
    瀏覽(23)
  • 頂級 Rust Web 框架:Rocket、Actix-web、Tide、Warp 和 Gotham

    在 Web 開發(fā)領(lǐng)域,擁有一個可靠且高效的 Web 框架對開發(fā)人員來說至關(guān)重要。Rust 是一種強大的現(xiàn)代編程語言,它提供了許多優(yōu)秀的 Web 框架來幫助完成這個過程。在這篇博文中,我們將探討五個最流行的 Rust web 框架——Rocket、Actix-web、Tide、Warp 和 Gotham——并發(fā)現(xiàn)它們的獨特特

    2024年02月10日
    瀏覽(15)
  • rust庫學(xué)習(xí)-env_logger(actix-web添加彩色日志、rust添加彩色日志 )

    rust庫學(xué)習(xí)-env_logger(actix-web添加彩色日志、rust添加彩色日志 )

    我們在進行rust的web開發(fā)時,如果不指定日志,就不會有輸出,非常不友好 這里我們使用 env_logger 進行日志打印 env_logger 需要配合 log 庫使用, env_logger 是 Rust 社區(qū)中一個非常流行的日志記錄庫。它提供了一個簡單且易于使用的接口,用于配置和記錄日志消息。 env_logger 可以與

    2024年02月11日
    瀏覽(21)
  • rust actix-web定義中間件(middleware)記錄接口耗時(接口耗時中間件和鑒權(quán)中間件)

    rust actix-web定義中間件(middleware)記錄接口耗時(接口耗時中間件和鑒權(quán)中間件)

    actix-web的官網(wǎng)關(guān)于中間件的介紹如下 https://actix.rs/docs/middleware/ 這里使用的是最新版的actix-web,舊版本的可能接口不太一樣 我們添加的中間件能干什么?我們用一段代碼來觀察一下 下面是官方提供的中間件的定義方式之一,我們可以看到閉包里面有兩個參數(shù) req 和 srv 其中

    2024年02月11日
    瀏覽(25)
  • Web3 開發(fā)指南:使用 NFTScan NFT API 構(gòu)建一個 NFT 鏈上追蹤器

    Web3 開發(fā)指南:使用 NFTScan NFT API 構(gòu)建一個 NFT 鏈上追蹤器

    對于大多數(shù) Web3 團隊來說,構(gòu)建一個完整的鏈上 NFT 數(shù)據(jù)追蹤系統(tǒng)是一項具有挑戰(zhàn)性的任務(wù),構(gòu)建一個 NFT 鏈上追蹤器更是如此。涉及到處理區(qū)塊鏈上的智能合約和交易數(shù)據(jù),并將其與外部數(shù)據(jù)源進行整合和分析工作量是十分巨大的: 區(qū)塊鏈數(shù)據(jù)的復(fù)雜性:區(qū)塊鏈上的數(shù)據(jù)結(jié)

    2024年02月15日
    瀏覽(29)
  • web前端開發(fā)項目走proxy代理后端接口,構(gòu)建發(fā)布到生產(chǎn)等環(huán)境后,如何修改api接口

    在開發(fā)環(huán)境,因為本地站點和接口站點不是同一個域名,就產(chǎn)生了跨域問題,但是不可能讓后端開發(fā)跨域端口或使用 jsonp ,所以,一般是讓前端通過在 webpack.config.js 中配置 proxy 來走接口代理。 代碼如下: 這樣,就將本地域名代理到接口了。 構(gòu)建成 dist目錄 后,就不能修改

    2024年02月15日
    瀏覽(24)
  • 〖Web全棧開發(fā)⑤〗— CSS基礎(chǔ)

    〖Web全棧開發(fā)⑤〗— CSS基礎(chǔ)

    ??????個人簡介:以山河作禮。 ??????: Python領(lǐng)域新星創(chuàng)作者,CSDN實力新星認證,阿里云社區(qū)專家博主 ????:Web全棧開發(fā)專欄:《Web全棧開發(fā)》免費專欄,歡迎閱讀! CSS 的意思為 Cascading Style Sheets,中文名是層疊樣式表。 CSS 是由大名鼎鼎的 W3C 中 CSS 工作組來發(fā)布以

    2024年02月09日
    瀏覽(25)
  • 【 Python 全棧開發(fā) - WEB開發(fā)篇 - 26 】Javascript 基礎(chǔ)

    Javascript 是一種動態(tài)的、基于對象的編程語言,通常用于網(wǎng)頁的客戶端腳本編程。它可以在網(wǎng)頁上實現(xiàn)交互效果、動態(tài)效果、表單驗證、數(shù)據(jù)處理等功能。 學(xué)習(xí) Javascript 可以通過以下途徑: 在線教程:像 w3schools、MDN 等網(wǎng)站提供了詳細的 Javascript 教程和示例代碼。 書籍:可以

    2024年02月08日
    瀏覽(16)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包