For some reason, I have to return HttpServer from a function (say consume a Config struct and generate a HttpServer). But the type signature of HttpServer is REALLY HARD for me to return, or even possible. Tons of depending types are private.
Even worse, so as actix_Web::App. App::new will return App<AppEntry, Body>, where AppEntry is private also... So it is still impossible to return from my function...
App is not designed to be used directly.
I ran into this recently because I wanted to parameterize and factor out the construction of App in my actix-web project for prod vs. test use-cases. I gave up and solved it with copy-pasta when I saw @fafhrd91 say not to bother when someone was trying to reconcile the middleware struct wrapping the type w/ them returning an App.
I accept that this might be his design intent but having to copy-pasta the App init for every test suite is a design fault even if it's intentional. This is the basic prelude to every #[test] that talks to the API:
let conf = config::get_env();
let dbexec = config::make_app_state(conf.db);
let mut app = test::init_service(
App::new()
.data(AppState { db: dbexec.clone() })
.configure(router::config_app),
);
let conn = dbexec.0.get().unwrap();
Is there something else I'm supposed to do here?
Finding that actix_web::Resource, actix_web::Scope are usable. So maybe I can return there types instead
This bug is still valid and I think it should still be open.
I think if you can assign a value to a variable in your program, you should also be able to return that value from a function.
https://actix.rs/docs/application/
Configure section
I ran into the same issue and tried to use the example in the "Configure" section linked above. I can't get even this simple example to work. I've copied most of the code exactly, and added main from the same page, modified to use create_app:
use actix_service::ServiceFactory;
use actix_web::dev::{MessageBody, ServiceRequest, ServiceResponse};
use actix_web::{web, App, Error, HttpResponse};
use actix_web::HttpServer;
fn create_app() -> App<
impl ServiceFactory<
Config = (),
Request = ServiceRequest,
Response = ServiceResponse<impl MessageBody>,
Error = Error,
>,
impl MessageBody,
> {
App::new().service(
web::scope("/app")
.route("/index.html", web::get().to(|| HttpResponse::Ok())),
)
}
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| create_app())
.bind("127.0.0.1:8088")?
.run()
.await
}
Here's what I get:
[email protected] actix-config $ cargo check
Checking actix-config v0.1.0 (/Users/dap/oxide/experiments/actix-config)
error[E0277]: the trait bound `actix_web::app::App<impl actix_service::ServiceFactory, impl actix_http::body::MessageBody>: actix_service::IntoServiceFactory<_>` is not satisfied
--> src/main.rs:23:5
|
23 | HttpServer::new(|| create_app())
| ^^^^^^^^^^^^^^^ the trait `actix_service::IntoServiceFactory<_>` is not implemented for `actix_web::app::App<impl actix_service::ServiceFactory, impl actix_http::body::MessageBody>`
|
= help: the following implementations were found:
<actix_web::app::App<T, B> as actix_service::IntoServiceFactory<actix_web::app_service::AppInit<T, B>>>
= note: required by `actix_web::server::HttpServer::<F, I, S, B>::new`
error[E0277]: the trait bound `actix_web::app::App<impl actix_service::ServiceFactory, impl actix_http::body::MessageBody>: actix_service::IntoServiceFactory<_>` is not satisfied
--> src/main.rs:23:5
|
23 | HttpServer::new(|| create_app())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `actix_service::IntoServiceFactory<_>` is not implemented for `actix_web::app::App<impl actix_service::ServiceFactory, impl actix_http::body::MessageBody>`
|
= help: the following implementations were found:
<actix_web::app::App<T, B> as actix_service::IntoServiceFactory<actix_web::app_service::AppInit<T, B>>>
= note: required by `actix_web::server::HttpServer`
error[E0277]: the trait bound `actix_web::app::App<impl actix_service::ServiceFactory, impl actix_http::body::MessageBody>: actix_service::IntoServiceFactory<_>` is not satisfied
--> src/main.rs:24:6
|
24 | .bind("127.0.0.1:8088")?
| ^^^^ the trait `actix_service::IntoServiceFactory<_>` is not implemented for `actix_web::app::App<impl actix_service::ServiceFactory, impl actix_http::body::MessageBody>`
|
= help: the following implementations were found:
<actix_web::app::App<T, B> as actix_service::IntoServiceFactory<actix_web::app_service::AppInit<T, B>>>
error[E0277]: the trait bound `actix_web::app::App<impl actix_service::ServiceFactory, impl actix_http::body::MessageBody>: actix_service::IntoServiceFactory<_>` is not satisfied
--> src/main.rs:23:5
|
23 | / HttpServer::new(|| create_app())
24 | | .bind("127.0.0.1:8088")?
| |____________________________^ the trait `actix_service::IntoServiceFactory<_>` is not implemented for `actix_web::app::App<impl actix_service::ServiceFactory, impl actix_http::body::MessageBody>`
|
= help: the following implementations were found:
<actix_web::app::App<T, B> as actix_service::IntoServiceFactory<actix_web::app_service::AppInit<T, B>>>
= note: required by `actix_web::server::HttpServer`
error[E0277]: the trait bound `actix_web::app::App<impl actix_service::ServiceFactory, impl actix_http::body::MessageBody>: actix_service::IntoServiceFactory<_>` is not satisfied
--> src/main.rs:25:6
|
25 | .run()
| ^^^ the trait `actix_service::IntoServiceFactory<_>` is not implemented for `actix_web::app::App<impl actix_service::ServiceFactory, impl actix_http::body::MessageBody>`
|
= help: the following implementations were found:
<actix_web::app::App<T, B> as actix_service::IntoServiceFactory<actix_web::app_service::AppInit<T, B>>>
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0277`.
error: could not compile `actix-config`.
To learn more, run the command again with --verbose.
Sorry if I'm doing something wrong but I can't get this to work.
https://actix.rs/docs/application/
Configuresection
configure can't use middeware
Most helpful comment
This bug is still valid and I think it should still be open.
I think if you can assign a value to a variable in your program, you should also be able to return that value from a function.