mthelm
December 4, 2021, 12:10am
1
I'm trying to figure out how to set up an API with actix-web and mongodb. I found this thread which shows the following code snippet as the solution:
struct AppState {
pub db: Database,
pub client: Client
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let bind_addr = "127.0.0.1:8080";
println!("Server Running at {} ....", bind_addr);
// A Client is needed to connect to MongoDB:
let client_uri = "mongodb://127.0.0.1:27017";
let mut options = ClientOptions::parse(&client_uri).await?;
let client = Client::with_options(options)?;
let db = client.database("my_database");
HttpServer::new(|| App::new()
.data(AppState {
db,
client
})
.configure(config))
.bind(bind_addr)?
.run()
.await
}
However, when I try to replicate this with the following code:
use actix_web::{App, HttpServer};
use mongodb::{ Client, Database, bson::doc, options::ClientOptions };
use serde::{ Deserialize, Serialize };
struct AppState {
pub db: Database,
pub client: Client
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct Naic {
code: u32,
title: String,
}
#[actix_web::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client_options = ClientOptions::parse("mongodb://localhost:27017").await?;
let client = Client::with_options(client_options)?;
let db = client.database("NAICS");
// let collection = db.collection::<Naic>("Descriptions");
// match collection.find_one(doc! { "Code": 444 }, None).await? {
// Some(naic) => println!("Description: {}", naic.title),
// None => println!("NAIC not found")
// }
HttpServer::new(|| App::new()
.data(AppState {
db,
client
}))
.bind("127.0.0.1:8080")?
.run()
.await;
Ok(())
}
I get an error because db
has type mongodb::Database
, which does not implement the Copy
trait (the same goes for the client).
How do I overcome this?
mthelm
December 4, 2021, 6:49pm
3
error[E0507]: cannot move out of `db`, a captured variable in an `Fn` closure
--> src\main.rs:29:17
|
21 | let db = client.database("NAICS");
| -- captured outer variable
...
29 | db,
| ^^ move occurs because `db` has type `Database`, which does not implement the `Copy` trait
error[E0507]: cannot move out of `client`, a captured variable in an `Fn` closure
--> src\main.rs:30:17
|
20 | let client = Client::with_options(client_options)?;
| ------ captured outer variable
...
30 | client
| ^^^^^^ move occurs because `client` has type `mongodb::Client`, which does not implement the `Copy` trait
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0507`.
alice
December 4, 2021, 6:50pm
4
Ah, right. So this is because the closure is called once per thread that the web server will spawn. You'll need to clone them, or create them inside the closure if they aren't cloneable.
1 Like
mthelm
December 4, 2021, 7:01pm
5
If I try to do this:
#[actix_web::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
HttpServer::new(|| {
let client_options = ClientOptions::parse("mongodb://localhost:27017").await?;
let client = Client::with_options(client_options)?;
let db = client.database("NAICS");
App::new().data(AppState { db, client })
.bind("127.0.0.1:8080")?
.run()
.await
});
Ok(())
}
it breaks because await
is only allowed inside async
functions/blocks
UPDATE: This looks like it might work:
use actix_web::{ App, HttpServer };
use mongodb::{ Client, Database, bson::doc, options::ClientOptions };
use serde::{ Deserialize, Serialize };
#[derive(Debug, Clone)]
struct AppState {
pub db: Database,
pub client: Client
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct Naic {
code: u32,
title: String,
}
#[actix_web::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client_options = ClientOptions::parse("mongodb://localhost:27017").await?;
let client = Client::with_options(client_options)?;
let db = client.database("NAICS");
let state = AppState { db, client };
HttpServer::new(move || {
App::new().data(state.clone())
}).bind("127.0.0.1:8080")?
.run()
.await?;
Ok(())
}
system
Closed
March 4, 2022, 7:01pm
6
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.