使用功能修饰时,如何将App数据传递给actix-web中的服务路由处理程序功能?

时间:2019-10-17 16:07:46

标签: rust global-variables actix-web

我在文档中找到了一个示例,该示例说明了如何创建由Mutex保护的全局状态,该状态在处理线程之间共享,该处理线程可用于所有路由处理程序。完善!但是,我更喜欢使用函数附带的属性来连接路由处理程序。我不知道使用归因函数并传递全局状态的语法(如果允许)。

这是来自https://docs.rs/actix-web/1.0.2/actix_web/web/struct.Data.html

的actix-web文档中的示例
Traceback (most recent call last):
  File "/home/myUser/Documents/MICROSERVICES/service-upload-img/env/lib64/python3.7/site-packages/flask/app.py", line 2446, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/myUser/Documents/MICROSERVICES/service-upload-img/env/lib64/python3.7/site-packages/flask/app.py", line 1951, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/myUser/Documents/MICROSERVICES/service-upload-img/env/lib64/python3.7/site-packages/flask/app.py", line 1820, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/myUser/Documents/MICROSERVICES/service-upload-img/env/lib64/python3.7/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/home/myUser/Documents/MICROSERVICES/service-upload-img/env/lib64/python3.7/site-packages/flask/app.py", line 1949, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/myUser/Documents/MICROSERVICES/service-upload-img/env/lib64/python3.7/site-packages/flask/app.py", line 1935, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/myUser/Documents/MICROSERVICES/service-upload-img/main.py", line 17, in generate_image_v2
    return resource.generate_image(req)
  File "/home/myUser/Documents/MICROSERVICES/service-upload-img/service/imageGenerator.py", line 20, in generate_image
    transfersResponse = self.testSaveImageLocal(inputData)
  File "/home/myUser/Documents/MICROSERVICES/service-upload-img/service/imageGenerator.py", line 173, in testSaveImageLocal
    self.upload_image_file(output)
  File "/home/myUser/Documents/MICROSERVICES/service-upload-img/service/imageGenerator.py", line 195, in upload_image_file
    "jpg"
  File "/home/myUser/Documents/MICROSERVICES/service-upload-img/service/storage.py", line 66, in upload_file
    content_type=content_type)
  File "/home/myUser/Documents/MICROSERVICES/service-upload-img/env/lib64/python3.7/site-packages/google/cloud/storage/blob.py", line 1296, in upload_from_string
    predefined_acl=predefined_acl,
  File "/home/myUser/Documents/MICROSERVICES/service-upload-img/env/lib64/python3.7/site-packages/google/cloud/storage/blob.py", line 1200, in upload_from_file
    _raise_from_invalid_response(exc)
  File "/home/myUser/Documents/MICROSERVICES/service-upload-img/env/lib64/python3.7/site-packages/google/cloud/storage/blob.py", line 2089, in _raise_from_invalid_response
    raise exceptions.from_http_status(response.status_code, message, response=response)
google.api_core.exceptions.BadRequest: 400 POST https://www.googleapis.com/upload/storage/v1/b/image-buck-share/o?uploadType=multipart: ('Request failed with status code', 400, 'Expected one of', <HTTPStatus.OK: 200>)
127.0.0.1 - - [17/Oct/2019 10:52:04] "POST /img/up/ser/generator/v2 HTTP/1.1" 500

注意如何将use std::sync::Mutex; use actix_web::{web, App}; struct MyData { counter: usize, } /// Use `Data<T>` extractor to access data in handler. fn index(data: web::Data<Mutex<MyData>>) { let mut data = data.lock().unwrap(); data.counter += 1; } fn main() { let data = web::Data::new(Mutex::new(MyData{ counter: 0 })); let app = App::new() // Store `MyData` in application storage. .register_data(data.clone()) .service( web::resource("/index.html").route( web::get().to(index))); } 传递给名为index的路由处理程序。

现在这是我的代码片段。

web::Data

注意我如何调用方法use actix_web::{get, App, HttpResponse, HttpServer, Responder}; pub mod request; pub mod routes; const SERVICE_NAME : &str = "Shy Rules Engine"; const SERVICE_VERSION : &str = "0.1"; #[get("/")] fn index() -> impl Responder { HttpResponse::Ok().body(format!("{} version {}", SERVICE_NAME, SERVICE_VERSION)) } mod expression_execute { #[post("/expression/execute")] fn route(req: web::Json<ExpressionExecuteRequest>) -> HttpResponse { // ... lots of code omitted ... if response.has_error() { HttpResponse::Ok().json(response) } else { HttpResponse::BadRequest().json(response) } } } pub fn shy_service(ip : &str, port : &str) { HttpServer::new(|| { App::new() .service(index) .service(expression_execute::route) }) .bind(format!("{}:{}", ip, port)) .unwrap() .run() .unwrap(); } 来连接路由处理程序。

还要注意我的路由处理程序如何不接收全局状态(因为我尚未将其添加到我的应用程序中)。如果我使用与使用App::service的文档类似的模式来创建全局App数据,那么我会对我的方法签名,register_dataget属性以及其他任何内容进行哪些更改,以便我可以将全局状态传递给处理程序?

还是无法使用postget属性来访问全局状态?

1 个答案:

答案 0 :(得分:2)

您列出的两种情况确实没有太大区别:

//# actix-web = "1.0.8"
use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
use std::sync::Mutex;

const SERVICE_NAME : &str = "Shy Rules Engine";
const SERVICE_VERSION : &str  = "0.1";

struct MyData {
    counter: usize,
}

#[get("/")]
fn index(data: web::Data<Mutex<MyData>>) -> impl Responder {
    let mut data = data.lock().unwrap();
    data.counter += 1;
    println!("Endpoint visited: {}", data.counter);
    HttpResponse::Ok().body(format!("{} version {}", SERVICE_NAME, SERVICE_VERSION))
}

pub fn shy_service(ip : &str, port : &str) {
    let data = web::Data::new(Mutex::new(MyData{ counter: 0 }));

    HttpServer::new(move || {
        App::new()
            .register_data(data.clone())
            .service(index)
    })
    .bind(format!("{}:{}", ip, port))
    .unwrap()
    .run()
    .unwrap();
}

fn main() {
    shy_service("127.0.0.1", "8080");
}

您可以仅通过curl http端点来验证其是否有效。对于multiple extractors,您必须使用元组:

    #[post("/expression/execute")]
    fn route((req, data): (web::Json<ExpressionExecuteRequest>, web::Data<Mutex<MyData>>)) -> HttpResponse {
        unimplemented!()
    }