How can I return a configured App in Actix-Web?
Asked Answered
B

3

5

I'm using actix-web to create a httpserver with state/data embedded in it. But vscode show me that the create_app function has wrong arguments in its return value type definition App<AppState>:

pub struct App<T, B>
wrong number of type arguments: expected 2, found 1
expected 2 type argumentsrustc(E0107)

app.rs:

use crate::api;
use crate::model::DbExecutor;
use actix::prelude::Addr;
use actix_web::{error, http::Method, middleware::Logger, web, App, HttpResponse};

pub struct AppState {
    pub db: Addr<DbExecutor>,
}

pub fn create_app(db: Addr<DbExecutor>) -> App<AppState> {
    App::new().data(AppState { db }).service(
        web::resource("/notes/").route(web::get().to(api::notes))
    );
}

main.rs:

fn main() {
    HttpServer::new(move || app::create_app(addr.clone()))
        .bind("127.0.0.1:3000")
        .expect("Can not bind to '127.0.0.1:3000'")
        .start();
}

As return type of "service" method is "Self" which is type actix_web::App, I tried modify return type to App (without generic parameter) but still got error, what should I do?

Bondsman answered 12/8, 2019 at 7:33 Comment(0)
R
10

First, App takes two generic type arguments, App<AppEntry, Body>, you've only given one.

Second, AppState is not AppEntry.

Third, instantiating App outside actix-web is hard, if not impossible, as the types you need from actix-web are not public.

Instead, you should use configure to achieve the same, here is a simplified example:

use actix_web::web::{Data, ServiceConfig};
use actix_web::{web, App, HttpResponse, HttpServer};

fn main() {
    let db = String::from("simplified example");

    HttpServer::new(move || App::new().configure(config_app(db.clone())))
        .bind("127.0.0.1:3000")
        .expect("Can not bind to '127.0.0.1:3000'")
        .run()
        .unwrap();
}

fn config_app(db: String) -> Box<dyn Fn(&mut ServiceConfig)> {
    Box::new(move |cfg: &mut ServiceConfig| {
        cfg.app_data(db.clone())
            .service(web::resource("/notes").route(web::get().to(notes)));
    })
}

fn notes(db: Data<String>) -> HttpResponse {
    HttpResponse::Ok().body(["notes from ", &db].concat())
}

Read more about ServiceConfig in the api documentation.

Reclinate answered 22/9, 2019 at 20:28 Comment(0)
E
1

The AppEntry type is deliberately and explicitly not exposed, and will not be. There is a fairly fugly type signature you can use that'll allow you to return an App, as shown in this test to setup the appropriate return type of your function:

  pub fn my_app() -> App<
      impl ServiceFactory<
          ServiceRequest,
          Response = ServiceResponse<impl MessageBody>,
          Config = (),
          InitError = (),
          Error = Error,
      >,
  > {
      App::new()
    }

That being said, for most cases, you can (and should) use App::configure() instead, and it looks like you would be able to do that in the case of the code you posted in your question.

Ernestineernesto answered 4/5 at 6:22 Comment(0)
H
-3

its really easy but you need to import AppEntry and the problem is that AppEntry not exported by actix_web

so you need to update the original code of the package

so go to /lib.rs by pressing on ctrl + right Click on actix_web; then add the next line after pub mod rt;

pub mod app_service ;

then you need to update the cache so firstly

cargo clean
cargo update
cargo fetch
cargo build

now everything is good so you could import AppEntry using this syntax

use actix_web::app_service::AppEntry;

after importing app entry you could do what ever you want by structing your code to mvc or doing what every you want

Heterogamy answered 14/7, 2023 at 13:33 Comment(2)
use actix_web::{Responder,HttpResponse,get,HttpServer,App,app_service::AppEntry}; #[get("/")] async fn hello() -> impl Responder { HttpResponse::Ok().body("Hello world!") } fn setup_routes_and_controllers(app:App<AppEntry>)->App<AppEntry>{ app.service(hello) } #[actix_web::main] async fn main()->std::io::Result<()>{ HttpServer::new( || { let app = App::new(); setup_routes_and_controllers(app) }). bind("")? .run() .await }Heterogamy
AppEntry is not exposed for public consumptionDiuresis

© 2022 - 2024 — McMap. All rights reserved.