Как передать данные приложения в функцию обработчика маршрута службы в actix-web при использовании художественных оформлений? - PullRequest
0 голосов
/ 17 октября 2019

В документах я нашел пример того, как создать глобальное состояние, защищенное Mutex, для общего доступа к потокам обработки, доступное для всех ваших обработчиков маршрутов. Отлично! Однако я предпочитаю использовать атрибуты, прикрепленные к моим функциям, для подключения моих обработчиков маршрутов. Я не знаю синтаксис (если разрешено) использовать атрибутные функции, а также передать в глобальном состоянии.

Вот пример из документов actix-web, из https://docs.rs/actix-web/1.0.2/actix_web/web/struct.Data.html

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 для подключения моих обработчиков маршрута.

Также обратите внимание, как это делает мой обработчик маршрутане получил глобальное состояние (потому что я еще не добавил его в свое приложение). Если я использовал шаблон, аналогичный документам, использующим register_data для создания глобальных данных приложения, какие изменения я внесу в сигнатуру своего метода, атрибуты get и post и все остальное, чтобы я мог передать это глобальное состояние вобработчик?

Или невозможно использовать атрибуты get и post для получения доступа к глобальному состоянию?

1 Ответ

1 голос
/ 18 октября 2019

Два перечисленных вами случая на самом деле не имеют большой разницы:

//# 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. Для нескольких экстракторов вам придется использовать кортеж:

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