在使用 actix_web 的时候发现的问题,
这是官方的代码:
use actix_web::{web, App, HttpServer, Responder};
async fn index() -> impl Responder {
"Hello world!"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new().service(
// prefixes all resources and routes attached to it...
web::scope("/app")
// ...so this handles requests for `GET /app/index.html`
.route("/index.html", web::get().to(index)),
)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
我觉得缩进层次有点深, 就想重构一下, 改为下面的样子:
(目前还没有问题)
use actix_web::{web, App, HttpServer, Responder};
async fn index() -> impl Responder {
"Hello world!"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let app = || {
App::new()
.service(
web::scope("/app")
.route(
"/index.html",
web::get().to(index)
)
)
};
HttpServer::new(app)
.bind(("127.0.0.1", 8080))?
.run()
.await
}
再次改进, 就出问题了:
use actix_web::{web, App, HttpServer, Responder};
async fn index() -> impl Responder {
"Hello world!"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let router = web::scope("/app").route(
"/index.html",
web::get().to(index)
);
let app = || {
App::new()
.service(router)
};
HttpServer::new(app)
.bind(("127.0.0.1", 8080))?
.run()
.await
}
报错特别长, 我仔细看了一下,
主要原因是将 router 放到外面后,
app 的类型就从 Fn 变为了 FnOnce,
而 HttpServer::new() 只接受 Fn, 所以就出问题了,
但不知道怎么解决,
报错内容:
error[E0525]: expected a closure that implements the `Fn` trait, but this
closure only implements `FnOnce`
--> src\main.rs:15:15
|
15 | let app = || {
| ^^ this closure implements `FnOnce`, not `Fn`
16 | App::new()
17 | .service(router)
| ------ closure is `FnOnce` because it moves the variable `router` out of its environment
...
20 | HttpServer::new(app)
| --------------- --- the requirement to implement `Fn` derives from here
| |
| required by a bound introduced by this call
|
note: required by a bound in `HttpServer::<F, I, S, B>::new`
--> C:\Users\baex\.cargo\registry\src\mirrors.ustc.edu.cn-12df342d903acd47\actix-web-4.4.0\src\server.rs:89:8
|
89 | F: Fn() -> I + Send + Clone + 'static,
| ^^^^^^^^^ required by this bound in `HttpServer::<F, I, S, B>::new`
...
102 | pub fn new(factory: F) -> Self {
| --- required by a bound in this associated function
error[E0277]: the trait bound `actix_web::Scope: Clone` is not satisfied in `{closure@src\main.rs:15:15: 15:17}`
--> src\main.rs:20:21
|
15 | let app = || {
| -- within this `{closure@src\main.rs:15:15: 15:17}`
...
20 | HttpServer::new(app)
| --------------- ^^^ within `{closure@src\main.rs:15:15: 15:17}`, the trait `Clone` is not implemented for `actix_web::Scope`
| |
| required by a bound introduced by this call
|
note: required because it's used within this closure
--> src\main.rs:15:15
|
15 | let app = || {
| ^^
note: required by a bound in `HttpServer::<F, I, S, B>::new`
--> C:\Users\baex\.cargo\registry\src\mirrors.ustc.edu.cn-12df342d903acd47\actix-web-4.4.0\src\server.rs:89:27
|
89 | F: Fn() -> I + Send + Clone + 'static,
| ^^^^^ required by this bound in `HttpServer::<F, I, S, B>::new`
...
102 | pub fn new(factory: F) -> Self {
| --- required by a bound in this associated function
error[E0277]: `Rc<RefCell<Option<actix_web::scope::ScopeFactory>>>` cannot be sent between threads safely
--> src\main.rs:20:21
|
15 | let app = || {
| -- within this `{closure@src\main.rs:15:15: 15:17}`
...
20 | HttpServer::new(app)
| --------------- ^^^ `Rc<RefCell<Option<actix_web::scope::ScopeFactory>>>` cannot be sent between threads safely
| |
| required by a bound introduced by this call
|
= help: within `{closure@src\main.rs:15:15: 15:17}`, the trait `Send`
is not implemented for `Rc<RefCell<Option<actix_web::scope::ScopeFactory>>>`
note: required because it appears within the type `Scope`
--> C:\Users\baex\.cargo\registry\src\mirrors.ustc.edu.cn-12df342d903acd47\actix-web-4.4.0\src\scope.rs:57:12
|
57 | pub struct Scope<T = ScopeEndpoint> {
| ^^^^^
note: required because it's used within this closure
--> src\main.rs:15:15
|
15 | let app = || {
| ^^
note: required by a bound in `HttpServer::<F, I, S, B>::new`
--> C:\Users\baex\.cargo\registry\src\mirrors.ustc.edu.cn-12df342d903acd47\actix-web-4.4.0\src\server.rs:89:20
|
89 | F: Fn() -> I + Send + Clone + 'static,
| ^^^^ required by this bound in `HttpServer::<F, I, S, B>::new`
...
102 | pub fn new(factory: F) -> Self {
| --- required by a bound in this associated function
error[E0277]: `Rc<actix_service::boxed::BoxServiceFactory<(), ServiceRequest, ServiceResponse, actix_web::Error, ()>>` cannot be sent between threads safely
--> src\main.rs:20:21
|
15 | let app = || {
| -- within this `{closure@src\main.rs:15:15: 15:17}`
...
20 | HttpServer::new(app)
| --------------- ^^^ `Rc<actix_service::boxed::BoxServiceFactory<(), ServiceRequest, ServiceResponse, actix_web::Error, ()>>` cannot be sent between threads safely
| |
| required by a bound introduced by this call
|
= help: within `{closure@src\main.rs:15:15: 15:17}`, the trait `Send`
is not implemented for `Rc<actix_service::boxed::BoxServiceFactory<(), ServiceRequest, ServiceResponse, actix_web::Error, ()>>`
note: required because it appears within the type `Option<Rc<BoxServiceFactory<(), ServiceRequest, ServiceResponse, Error, ()>>>`
--> C:\Users\baex\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\core\src\option.rs:563:10
|
563 | pub enum Option<T> {
| ^^^^^^
note: required because it appears within the type `Scope`
--> C:\Users\baex\.cargo\registry\src\mirrors.ustc.edu.cn-12df342d903acd47\actix-web-4.4.0\src\scope.rs:57:12
|
57 | pub struct Scope<T = ScopeEndpoint> {
| ^^^^^
note: required because it's used within this closure
--> src\main.rs:15:15
|
15 | let app = || {
| ^^
note: required by a bound in `HttpServer::<F, I, S, B>::new`
--> C:\Users\baex\.cargo\registry\src\mirrors.ustc.edu.cn-12df342d903acd47\actix-web-4.4.0\src\server.rs:89:20
|
89 | F: Fn() -> I + Send + Clone + 'static,
| ^^^^ required by this bound in `HttpServer::<F, I, S, B>::new`
...
102 | pub fn new(factory: F) -> Self {
| --- required by a bound in this associated function
error[E0277]: `(dyn actix_web::service::AppServiceFactory + 'static)` cannot be sent between threads safely
--> src\main.rs:20:21
|
20 | HttpServer::new(app)
| --------------- ^^^ `(dyn actix_web::service::AppServiceFactory
+ 'static)` cannot be sent between threads safely
| |
| required by a bound introduced by this call
|
= help: the trait `Send` is not implemented for `(dyn actix_web::service::AppServiceFactory + 'static)`
= note: required for `Unique<(dyn actix_web::service::AppServiceFactory + 'static)>` to implement `Send`
note: required because it appears within the type `Box<dyn AppServiceFactory>`
--> C:\Users\baex\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\alloc\src\boxed.rs:195:12
|
195 | pub struct Box<
| ^^^
= note: required for `Unique<Box<(dyn actix_web::service::AppServiceFactory + 'static)>>` to implement `Send`
note: required because it appears within the type `RawVec<Box<dyn AppServiceFactory>>`
--> C:\Users\baex\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\alloc\src\raw_vec.rs:51:19
|
51 | pub(crate) struct RawVec<T, A: Allocator = Global> {
| ^^^^^^
note: required because it appears within the type `Vec<Box<dyn AppServiceFactory>>`
--> C:\Users\baex\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\alloc\src\vec\mod.rs:396:12
|
396 | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = ...
| ^^^
note: required because it appears within the type `Scope`
--> C:\Users\baex\.cargo\registry\src\mirrors.ustc.edu.cn-12df342d903acd47\actix-web-4.4.0\src\scope.rs:57:12
|
57 | pub struct Scope<T = ScopeEndpoint> {
| ^^^^^
note: required because it's used within this closure
--> src\main.rs:15:15
|
15 | let app = || {
| ^^
note: required by a bound in `HttpServer::<F, I, S, B>::new`
--> C:\Users\baex\.cargo\registry\src\mirrors.ustc.edu.cn-12df342d903acd47\actix-web-4.4.0\src\server.rs:89:20
|
89 | F: Fn() -> I + Send + Clone + 'static,
| ^^^^ required by this bound in `HttpServer::<F, I, S, B>::new`
...
102 | pub fn new(factory: F) -> Self {
| --- required by a bound in this associated function
error[E0277]: `(dyn Guard + 'static)` cannot be sent between threads safely
--> src\main.rs:20:21
|
20 | HttpServer::new(app)
| --------------- ^^^ `(dyn Guard + 'static)` cannot be sent between threads safely
| |
| required by a bound introduced by this call
|
= help: the trait `Send` is not implemented for `(dyn Guard + 'static)`
= note: required for `Unique<(dyn Guard + 'static)>` to implement `Send`
note: required because it appears within the type `Box<dyn Guard>`
--> C:\Users\baex\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\alloc\src\boxed.rs:195:12
|
195 | pub struct Box<
| ^^^
= note: required for `Unique<Box<(dyn Guard + 'static)>>` to implement `Send`
note: required because it appears within the type `RawVec<Box<dyn Guard>>` --> C:\Users\baex\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\alloc\src\raw_vec.rs:51:19
|
51 | pub(crate) struct RawVec<T, A: Allocator = Global> {
| ^^^^^^
note: required because it appears within the type `Vec<Box<dyn Guard>>`
--> C:\Users\baex\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\alloc\src\vec\mod.rs:396:12
|
396 | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = ...
| ^^^
note: required because it appears within the type `Scope`
--> C:\Users\baex\.cargo\registry\src\mirrors.ustc.edu.cn-12df342d903acd47\actix-web-4.4.0\src\scope.rs:57:12
|
57 | pub struct Scope<T = ScopeEndpoint> {
| ^^^^^
note: required because it's used within this closure
--> src\main.rs:15:15
|
15 | let app = || {
| ^^
note: required by a bound in `HttpServer::<F, I, S, B>::new`
--> C:\Users\baex\.cargo\registry\src\mirrors.ustc.edu.cn-12df342d903acd47\actix-web-4.4.0\src\server.rs:89:20
|
89 | F: Fn() -> I + Send + Clone + 'static,
| ^^^^ required by this bound in `HttpServer::<F, I, S, B>::new`
...
102 | pub fn new(factory: F) -> Self {
| --- required by a bound in this associated function
error[E0277]: `(dyn std::any::Any + 'static)` cannot be sent between threads safely
--> src\main.rs:20:21
|
20 | HttpServer::new(app)
| --------------- ^^^ `(dyn std::any::Any + 'static)` cannot be sent between threads safely
| |
| required by a bound introduced by this call
|
= help: the trait `Send` is not implemented for `(dyn std::any::Any +
'static)`
= note: required for `Unique<(dyn std::any::Any + 'static)>` to implement `Send`
note: required because it appears within the type `Box<dyn Any>`
--> C:\Users\baex\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\alloc\src\boxed.rs:195:12
|
195 | pub struct Box<
| ^^^
= note: required because it appears within the type `(TypeId, Box<dyn
Any>)`
= note: required for `hashbrown::raw::RawTable<(TypeId, Box<(dyn std::any::Any + 'static)>)>` to implement `Send`
note: required because it appears within the type `HashMap<TypeId, Box<dyn Any>, BuildHasherDefault<NoOpHasher>>`
--> C:\Users\runneradmin\.cargo\registry\src\index.crates.io-6f17d22bba15001f\hashbrown-0.14.0\src\map.rs:188:12
note: required because it appears within the type `HashMap<TypeId, Box<dyn Any>, BuildHasherDefault<NoOpHasher>>`
--> C:\Users\baex\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\std\src\collections\hash\map.rs:216:12
|
216 | pub struct HashMap<K, V, S = RandomState> {
| ^^^^^^^
note: required because it appears within the type `Extensions`
--> C:\Users\baex\.cargo\registry\src\mirrors.ustc.edu.cn-12df342d903acd47\actix-http-3.4.0\src\extensions.rs:33:12
|
33 | pub struct Extensions {
| ^^^^^^^^^^
note: required because it appears within the type `Option<Extensions>`
--> C:\Users\baex\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\core\src\option.rs:563:10
|
563 | pub enum Option<T> {
| ^^^^^^
note: required because it appears within the type `Scope`
--> C:\Users\baex\.cargo\registry\src\mirrors.ustc.edu.cn-12df342d903acd47\actix-web-4.4.0\src\scope.rs:57:12
|
57 | pub struct Scope<T = ScopeEndpoint> {
| ^^^^^
note: required because it's used within this closure
--> src\main.rs:15:15
|
15 | let app = || {
| ^^
note: required by a bound in `HttpServer::<F, I, S, B>::new`
--> C:\Users\baex\.cargo\registry\src\mirrors.ustc.edu.cn-12df342d903acd47\actix-web-4.4.0\src\server.rs:89:20
|
89 | F: Fn() -> I + Send + Clone + 'static,
| ^^^^ required by this bound in `HttpServer::<F, I, S, B>::new`
...
102 | pub fn new(factory: F) -> Self {
| --- required by a bound in this associated function
Some errors have detailed explanations: E0277, E0525.
For more information about an error, try `rustc --explain E0277`.
1
共 5 条评论, 1 页
评论区
写评论换个写法吧
把router移动到app闭包内行不行?
--
👇
xiaopengli89: 看了下,HttpServer::new 的闭包设计上是 factory,需要能重复多次执行,但是 App::service 需要 router 的所有权,除非 router 实现了 clone,用 App:new().service(router.clone()),否则 Router 必须再 factory 内重新创建,不能复用
看了下,HttpServer::new 的闭包设计上是 factory,需要能重复多次执行,但是 App::service 需要 router 的所有权,除非 router 实现了 clone,用 App:new().service(router.clone()),否则 Router 必须再 factory 内重新创建,不能复用
又报错了: (截取最前面的一条)
👇
xiaopengli89: let app = move || { App::new() .service(router) };
let app = move || { App::new() .service(router) };