1
0
mirror of https://github.com/actix/examples synced 2024-11-23 22:41:07 +01:00

Update basics/todo to v4. (#486)

Co-authored-by: Rob Ede <robjtede@icloud.com>
This commit is contained in:
Rafael Bachmann 2022-02-02 03:19:01 +01:00 committed by GitHub
parent d36c2f0f1f
commit c01f0ea5f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 80 additions and 79 deletions

34
Cargo.lock generated
View File

@ -586,23 +586,6 @@ dependencies = [
"webpki-roots 0.22.2", "webpki-roots 0.22.2",
] ]
[[package]]
name = "actix-todo"
version = "1.0.0"
dependencies = [
"actix-files 0.3.0",
"actix-session 0.4.1",
"actix-web 3.3.3",
"diesel",
"dotenv",
"env_logger 0.8.4",
"futures",
"log",
"serde 1.0.136",
"serde_json",
"tera",
]
[[package]] [[package]]
name = "actix-utils" name = "actix-utils"
version = "2.0.0" version = "2.0.0"
@ -6069,6 +6052,23 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "todo"
version = "1.0.0"
dependencies = [
"actix-files 0.6.0-beta.16",
"actix-session 0.5.0-beta.7",
"actix-web 4.0.0-rc.1",
"diesel",
"dotenv",
"env_logger 0.9.0",
"futures",
"log",
"serde 1.0.136",
"serde_json",
"tera",
]
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "0.2.25" version = "0.2.25"

View File

@ -1,21 +1,18 @@
[package] [package]
name = "actix-todo" name = "todo"
version = "1.0.0" version = "1.0.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
actix-web = "3" actix-web = "4.0.0-rc.1"
actix-files = "0.3" actix-files = "0.6.0-beta.15"
actix-session = "0.4" actix-session = "0.5.0-beta.7"
diesel = { version = "1.3.2", features = ["postgres", "r2d2"] }
dotenv = "0.15" dotenv = "0.15"
env_logger = "0.8" env_logger = "0.9"
futures = "0.3.1" futures = "0.3.7"
log = "0.4.3" log = "0.4"
serde = { version = "1.0.69", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1.0.22" serde_json = "1"
tera = "1.5.0" tera = "1.5"
[dependencies.diesel]
features = ["postgres", "r2d2"]
version = "1.3.2"

View File

@ -45,4 +45,4 @@ To run the application execute:
cargo run cargo run
``` ```
Then to view it in your browser navigate to: [http://localhost:8088/](http://localhost:8088/) Then to view it in your browser navigate to: [http://localhost:8080/](http://localhost:8080/)

View File

@ -1,12 +1,15 @@
use actix_files::NamedFile; use actix_files::NamedFile;
use actix_session::Session; use actix_session::Session;
use actix_web::middleware::errhandlers::ErrorHandlerResponse; use actix_web::{
use actix_web::{dev, error, http, web, Error, HttpResponse, Result}; dev, error, http, middleware::ErrorHandlerResponse, web, Error, HttpResponse, Result,
};
use serde::Deserialize; use serde::Deserialize;
use tera::{Context, Tera}; use tera::{Context, Tera};
use crate::db; use crate::{
use crate::session::{self, FlashMessage}; db,
session::{self, FlashMessage},
};
pub async fn index( pub async fn index(
pool: web::Data<db::PgPool>, pool: web::Data<db::PgPool>,
@ -50,7 +53,8 @@ pub async fn create(
Ok(redirect_to("/")) Ok(redirect_to("/"))
} else { } else {
web::block(move || db::create_task(params.into_inner().description, &pool)) web::block(move || db::create_task(params.into_inner().description, &pool))
.await?; .await?
.map_err(error::ErrorInternalServerError)?;
session::set_flash(&session, FlashMessage::success("Task successfully added"))?; session::set_flash(&session, FlashMessage::success("Task successfully added"))?;
Ok(redirect_to("/")) Ok(redirect_to("/"))
} }
@ -86,7 +90,9 @@ async fn toggle(
pool: web::Data<db::PgPool>, pool: web::Data<db::PgPool>,
params: web::Path<UpdateParams>, params: web::Path<UpdateParams>,
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
web::block(move || db::toggle_task(params.id, &pool)).await?; web::block(move || db::toggle_task(params.id, &pool))
.await?
.map_err(error::ErrorInternalServerError)?;
Ok(redirect_to("/")) Ok(redirect_to("/"))
} }
@ -95,33 +101,33 @@ async fn delete(
params: web::Path<UpdateParams>, params: web::Path<UpdateParams>,
session: Session, session: Session,
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
web::block(move || db::delete_task(params.id, &pool)).await?; web::block(move || db::delete_task(params.id, &pool))
.await?
.map_err(error::ErrorInternalServerError)?;
session::set_flash(&session, FlashMessage::success("Task was deleted."))?; session::set_flash(&session, FlashMessage::success("Task was deleted."))?;
Ok(redirect_to("/")) Ok(redirect_to("/"))
} }
fn redirect_to(location: &str) -> HttpResponse { fn redirect_to(location: &str) -> HttpResponse {
HttpResponse::Found() HttpResponse::Found()
.header(http::header::LOCATION, location) .append_header((http::header::LOCATION, location))
.finish() .finish()
} }
pub fn bad_request<B>(res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> { pub fn bad_request<B>(res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
let new_resp = NamedFile::open("static/errors/400.html")? let new_resp = NamedFile::open("static/errors/400.html")?
.set_status_code(res.status()) .set_status_code(res.status())
.into_response(res.request())?; .into_response(res.request())
Ok(ErrorHandlerResponse::Response( .map_into_right_body();
res.into_response(new_resp.into_body()), Ok(ErrorHandlerResponse::Response(res.into_response(new_resp)))
))
} }
pub fn not_found<B>(res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> { pub fn not_found<B>(res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
let new_resp = NamedFile::open("static/errors/404.html")? let new_resp = NamedFile::open("static/errors/404.html")?
.set_status_code(res.status()) .set_status_code(res.status())
.into_response(res.request())?; .into_response(res.request())
Ok(ErrorHandlerResponse::Response( .map_into_right_body();
res.into_response(new_resp.into_body()), Ok(ErrorHandlerResponse::Response(res.into_response(new_resp)))
))
} }
pub fn internal_server_error<B>( pub fn internal_server_error<B>(
@ -129,8 +135,7 @@ pub fn internal_server_error<B>(
) -> Result<ErrorHandlerResponse<B>> { ) -> Result<ErrorHandlerResponse<B>> {
let new_resp = NamedFile::open("static/errors/500.html")? let new_resp = NamedFile::open("static/errors/500.html")?
.set_status_code(res.status()) .set_status_code(res.status())
.into_response(res.request())?; .into_response(res.request())
Ok(ErrorHandlerResponse::Response( .map_into_right_body();
res.into_response(new_resp.into_body()), Ok(ErrorHandlerResponse::Response(res.into_response(new_resp)))
))
} }

View File

@ -1,7 +1,9 @@
use std::ops::Deref; use std::ops::Deref as _;
use diesel::pg::PgConnection; use diesel::{
use diesel::r2d2::{ConnectionManager, Pool, PoolError, PooledConnection}; pg::PgConnection,
r2d2::{ConnectionManager, Pool, PoolError, PooledConnection},
};
use crate::model::{NewTask, Task}; use crate::model::{NewTask, Task};

View File

@ -1,14 +1,15 @@
#[macro_use] #[macro_use]
extern crate diesel; extern crate diesel;
#[macro_use]
extern crate log;
use std::{env, io}; use std::{env, io};
use actix_files as fs; use actix_files::Files;
use actix_session::CookieSession; use actix_session::CookieSession;
use actix_web::middleware::{errhandlers::ErrorHandlers, Logger}; use actix_web::{
use actix_web::{http, web, App, HttpServer}; http,
middleware::{ErrorHandlers, Logger},
web, App, HttpServer,
};
use dotenv::dotenv; use dotenv::dotenv;
use tera::Tera; use tera::Tera;
@ -24,22 +25,18 @@ static SESSION_SIGNING_KEY: &[u8] = &[0; 32];
async fn main() -> io::Result<()> { async fn main() -> io::Result<()> {
dotenv().ok(); dotenv().ok();
env::set_var("RUST_LOG", "actix_todo=debug,actix_web=info"); env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
env_logger::init();
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let pool = db::init_pool(&database_url).expect("Failed to create pool"); let pool = db::init_pool(&database_url).expect("Failed to create pool");
let app = move || { log::info!("starting HTTP serer at http://localhost:8080");
debug!("Constructing the App");
let mut templates = match Tera::new("templates/**/*") { HttpServer::new(move || {
Ok(t) => t, log::debug!("Constructing the App");
Err(e) => {
println!("Parsing error(s): {}", e); let mut templates =
::std::process::exit(1); Tera::new("templates/**/*").expect("errors in tera templates");
}
};
templates.autoescape_on(vec!["tera"]); templates.autoescape_on(vec!["tera"]);
let session_store = CookieSession::signed(SESSION_SIGNING_KEY).secure(false); let session_store = CookieSession::signed(SESSION_SIGNING_KEY).secure(false);
@ -53,17 +50,17 @@ async fn main() -> io::Result<()> {
.handler(http::StatusCode::NOT_FOUND, api::not_found); .handler(http::StatusCode::NOT_FOUND, api::not_found);
App::new() App::new()
.data(templates) .app_data(templates)
.data(pool.clone()) .app_data(pool.clone())
.wrap(Logger::default()) .wrap(Logger::default())
.wrap(session_store) .wrap(session_store)
.wrap(error_handlers) .wrap(error_handlers)
.service(web::resource("/").route(web::get().to(api::index))) .service(web::resource("/").route(web::get().to(api::index)))
.service(web::resource("/todo").route(web::post().to(api::create))) .service(web::resource("/todo").route(web::post().to(api::create)))
.service(web::resource("/todo/{id}").route(web::post().to(api::update))) .service(web::resource("/todo/{id}").route(web::post().to(api::update)))
.service(fs::Files::new("/static", "static/")) .service(Files::new("/static", "./static/"))
}; })
.bind(("127.0.0.1", 8088))?
debug!("Starting server"); .run()
HttpServer::new(app).bind("localhost:8088")?.run().await .await
} }

View File

@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
const FLASH_KEY: &str = "flash"; const FLASH_KEY: &str = "flash";
pub fn set_flash(session: &Session, flash: FlashMessage) -> Result<()> { pub fn set_flash(session: &Session, flash: FlashMessage) -> Result<()> {
session.set(FLASH_KEY, flash) session.insert(FLASH_KEY, flash)
} }
pub fn get_flash(session: &Session) -> Result<Option<FlashMessage>> { pub fn get_flash(session: &Session) -> Result<Option<FlashMessage>> {