Actix/Diesel API未响应Postman的请求

huangapple go评论94阅读模式
英文:

Actix/Diesel API not responding to requests from Postman

问题

我的代码 看起来 是正确的,因为它能够正确编译并且相当简单。但是当我使用 cargo run 运行我的应用程序时,尽管程序正常执行并输出一些调试信息,它不会响应任何请求。

这是我的 main.rs 文件:

  1. use actix_web::{web, App, HttpServer};
  2. use diesel::r2d2::{ConnectionManager, Pool};
  3. use diesel::sqlite::SqliteConnection;
  4. use dotenv::dotenv;
  5. #[path = "api/books/books_handlers.rs"]
  6. mod books_handlers;
  7. #[path = "api/books_relationships/books_relationships_handlers.rs"]
  8. mod books_relationships_handlers;
  9. mod models;
  10. mod routes;
  11. mod schema;
  12. mod logger;
  13. #[actix_rt::main]
  14. async fn main() -> std::io::Result<()> {
  15. // 加载 .env 文件并设置初始化变量
  16. dotenv().ok();
  17. std::env::set_var("RUST_LOG", "actix_web=debug");
  18. let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL 必须设置");
  19. // 创建 SQLite 的数据库连接池
  20. let manager = ConnectionManager::<SqliteConnection>::new(database_url);
  21. let pool: Pool<ConnectionManager<SqliteConnection>> = r2d2::Pool::builder()
  22. .build(manager)
  23. .expect("无法创建连接池。");
  24. // 启动 HTTP 服务器并注册路由
  25. println!("在 http://localhost:8080 上启动服务器");
  26. HttpServer::new(move || {
  27. App::new()
  28. .app_data(pool.clone())
  29. // Book 类
  30. .route("/create_book", web::post().to(books_handlers::create_book_handler))
  31. .route("/list_books", web::get().to(books_handlers::list_books_handler))
  32. .route("/get_book/{id}", web::post().to(books_handlers::read_book_by_id_handler))
  33. .route("/update_book/{id}", web::put().to(books_handlers::update_book_handler))
  34. .route("/delete_book/{id}", web::delete().to(books_handlers::delete_book_handler))
  35. // BookRelationships 类
  36. .route("/create_book_relationship", web::post().to(books_relationships_handlers::create_book_relationship_handler))
  37. .route("/list_book_relationships", web::get().to(books_relationships_handlers::list_books_handler))
  38. .route("/get_book_relationship/{id}", web::post().to(books_relationships_handlers::read_book_by_id_handler))
  39. .route("/update_book_relationship/{id}", web::put().to(books_relationships_handlers::update_book_handler))
  40. .route("/delete_book_relationship/{id}", web::delete().to(books_relationships_handlers::delete_book_handler))
  41. })
  42. .bind("127.0.0.1:8080")?
  43. .run()
  44. .await
  45. }

这是你正在使用 Postman 尝试的第一个处理程序:

  1. pub async fn create_book_handler(book_data: web::Json<Book>, pool: web::Data<DbPool>) -> HttpResponse {
  2. println!("create_book_handler: {:#?}", book_data); // <-- 这里从未执行
  3. let result = books_dao::create_book(book_data, pool).await;
  4. match result {
  5. Ok(book) => {
  6. println!("create_book_handler, OK. Book: {:#?}", book);
  7. HttpResponse::Ok()
  8. .content_type(ContentType::json())
  9. .json(&book)
  10. },
  11. Err(err) => {
  12. println!("create_book_handler, ERROR: {:#?}", err);
  13. log(LogType::Error, err.to_string());
  14. HttpResponse::InternalServerError()
  15. .content_type(ContentType::json())
  16. .body("{err: '无法将书插入到数据库中'")
  17. }
  18. }
  19. }

然后代码执行此函数,调用 Diesel 并更改数据库:

  1. pub async fn create_book(book: web::Json<Book>, pool: web::Data<DbPool>) -> Result<usize, Error> {
  2. let mut conn = pool
  3. .get()
  4. .expect("无法从连接池获取数据库连接");
  5. diesel::insert_into(books::table)
  6. .values(book.into_inner())
  7. .execute(&mut conn)
  8. }

但问题似乎甚至发生在此之前:即使在处理程序的开始处的 println! 也不执行。当我启动应用程序并向 http://127.0.0.1:8080/create_book 发送 POST 请求时,Postman 中会出现以下错误:

"请求的应用程序数据配置不正确。查看/启用调试日志以获取更多详细信息。"

我是否以错误的方式发送请求,或者是 API 发生故障?

英文:

My code seems to be ok, as it properly compiles and is quite simple. But when I run my app with cargo run, even though the program executes properly and outputs some debug printlns, it won't answer to any request.

This is my main.rs:

  1. use actix_web::{web, App, HttpServer};
  2. use diesel::r2d2::{ConnectionManager, Pool};
  3. use diesel::sqlite::SqliteConnection;
  4. use dotenvy::dotenv;
  5. #[path = &quot;api/books/books_handlers.rs&quot;]
  6. mod books_handlers;
  7. #[path = &quot;api/books_relationships/books_relationships_handlers.rs&quot;]
  8. mod books_relationships_handlers;
  9. mod models;
  10. mod routes;
  11. mod schema;
  12. mod logger;
  13. #[actix_rt::main]
  14. async fn main() -&gt; std::io::Result&lt;()&gt; {
  15. // Load .env file and set initialization variables
  16. dotenv().ok();
  17. std::env::set_var(&quot;RUST_LOG&quot;, &quot;actix_web=debug&quot;);
  18. let database_url = std::env::var(&quot;DATABASE_URL&quot;).expect(&quot;DATABASE_URL must be set&quot;);
  19. // Create db connection pool with SQLite
  20. let manager = ConnectionManager::&lt;SqliteConnection&gt;::new(database_url);
  21. let pool: Pool&lt;ConnectionManager&lt;SqliteConnection&gt;&gt; = r2d2::Pool::builder()
  22. .build(manager)
  23. .expect(&quot;Failed to create pool.&quot;);
  24. // Start HTTP server and register routes
  25. println!(&quot;Starting server at http://localhost:8080&quot;);
  26. HttpServer::new(move || {
  27. App::new()
  28. .app_data(pool.clone())
  29. // Book class
  30. .route(&quot;/create_book&quot;, web::post().to(books_handlers::create_book_handler))
  31. .route(&quot;/list_books&quot;, web::get().to(books_handlers::list_books_handler))
  32. .route(&quot;/get_book/{id}&quot;, web::post().to(books_handlers::read_book_by_id_handler))
  33. .route(&quot;/update_book/{id}&quot;, web::put().to(books_handlers::update_book_handler))
  34. .route(&quot;/delete_book/{id}&quot;, web::delete().to(books_handlers::delete_book_handler))
  35. // BookRelationships class
  36. .route(&quot;/create_book_relationship&quot;, web::post().to(books_relationships_handlers::create_book_relationship_handler))
  37. .route(&quot;/list_book_relationships&quot;, web::get().to(books_relationships_handlers::list_books_handler))
  38. .route(&quot;/get_book_relationship/{id}&quot;, web::post().to(books_relationships_handlers::read_book_by_id_handler))
  39. .route(&quot;/update_book_relationship/{id}&quot;, web::put().to(books_relationships_handlers::update_book_handler))
  40. .route(&quot;/delete_book_relationship/{id}&quot;, web::delete().to(books_relationships_handlers::delete_book_handler))
  41. })
  42. .bind(&quot;127.0.0.1:8080&quot;)?
  43. .run()
  44. .await
  45. }

This is the first handler, the one I'm trying with Postman:

  1. pub async fn create_book_handler(book_data: web::Json&lt;Book&gt;, pool: web::Data&lt;DbPool&gt;) -&gt; HttpResponse {
  2. println!(&quot;create_book_handler: {:#?}&quot;, book_data); // &lt;-- this never gets executed
  3. let result = books_dao::create_book(book_data, pool).await;
  4. match result {
  5. Ok(book) =&gt; {
  6. println!(&quot;create_book_handler, OK. Book: {:#?}&quot;, book);
  7. HttpResponse::Ok()
  8. .content_type(ContentType::json())
  9. .json(&amp;book)
  10. },
  11. Err(err) =&gt; {
  12. println!(&quot;create_book_handler, ERROR: {:#?}&quot;, err);
  13. log(LogType::Error, err.to_string());
  14. HttpResponse::InternalServerError()
  15. .content_type(ContentType::json())
  16. .body(&quot;{err: &#39;Unable to insert book into database&#39;&quot;)
  17. }
  18. }
  19. }

Then the code executes this function, calling Diesel and altering the DB:

  1. pub async fn create_book(book: web::Json&lt;Book&gt;, pool: web::Data&lt;DbPool&gt;) -&gt; Result&lt;usize, Error&gt; {
  2. let mut conn = pool
  3. .get()
  4. .expect(&quot;Failed to get database connection from pool&quot;);
  5. diesel::insert_into(books::table)
  6. .values(book.into_inner())
  7. .execute(&amp;mut conn)
  8. }

But the problem seems to be even before: not even the println! at the beginning of the handler get executed. When I start the app and send a POST request to http://127.0.0.1:8080/create_book, I get the following error in Postman:

Requested application data is not configured correctly. View/enable debug logs for more details.

Am I sending the requests in a wrong way, or is the API malfunctioning?

答案1

得分: 2

The DbPool is wrapped incorrectly. It should look like

  1. ...
  2. App::new()
  3. .app_data(actix_web::web::Data::new(pool.clone()))
  4. ...

This correctly wraps the DB Pool in the smart pointer that the route handlers can then use across your application

英文:

The DbPool is wrapped incorrectly. It should look like

  1. ...
  2. App::new()
  3. .app_data(actix_web::web::Data::new(pool.clone()))
  4. ...

This correctly wraps the DB Pool in the smart pointer that the route handlers can then use across your application

huangapple
  • 本文由 发表于 2023年2月9日 00:05:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/75388536.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定