1
0
mirror of https://github.com/actix/examples synced 2024-12-02 18:02:22 +01:00
examples/basics/todo/src/api.rs

149 lines
4.2 KiB
Rust
Raw Normal View History

2019-12-07 18:59:24 +01:00
use actix_files::NamedFile;
use actix_session::Session;
2022-02-06 08:55:51 +01:00
use actix_web::{
2023-03-14 03:40:02 +01:00
dev, error, http::StatusCode, middleware::ErrorHandlerResponse, web, Error, HttpResponse,
Responder, Result,
2022-02-06 08:55:51 +01:00
};
use serde::Deserialize;
2022-02-06 08:55:51 +01:00
use sqlx::SqlitePool;
2019-12-07 18:59:24 +01:00
use tera::{Context, Tera};
use crate::{
db,
session::{self, FlashMessage},
};
2019-12-07 18:59:24 +01:00
pub async fn index(
2022-02-06 08:55:51 +01:00
pool: web::Data<SqlitePool>,
2019-12-07 18:59:24 +01:00
tmpl: web::Data<Tera>,
session: Session,
) -> Result<HttpResponse, Error> {
2022-02-05 18:34:43 +01:00
let tasks = db::get_all_tasks(&pool)
.await
.map_err(error::ErrorInternalServerError)?;
2019-12-07 18:59:24 +01:00
let mut context = Context::new();
context.insert("tasks", &tasks);
2022-07-09 22:05:06 +02:00
// Session is set during operations on other endpoints that can redirect to index
2019-12-07 18:59:24 +01:00
if let Some(flash) = session::get_flash(&session)? {
context.insert("msg", &(flash.kind, flash.message));
session::clear_flash(&session);
}
let rendered = tmpl
.render("index.html.tera", &context)
2020-04-03 09:14:30 +02:00
.map_err(error::ErrorInternalServerError)?;
2019-12-07 18:59:24 +01:00
Ok(HttpResponse::Ok().body(rendered))
}
2022-07-09 22:05:06 +02:00
#[derive(Debug, Deserialize)]
2019-12-07 18:59:24 +01:00
pub struct CreateForm {
description: String,
}
pub async fn create(
params: web::Form<CreateForm>,
2022-02-06 08:55:51 +01:00
pool: web::Data<SqlitePool>,
2019-12-07 18:59:24 +01:00
session: Session,
2022-07-09 22:05:06 +02:00
) -> Result<impl Responder, Error> {
2019-12-07 18:59:24 +01:00
if params.description.is_empty() {
2022-02-18 03:44:02 +01:00
session::set_flash(&session, FlashMessage::error("Description cannot be empty"))?;
2023-03-14 03:40:02 +01:00
Ok(web::Redirect::to("/").using_status_code(StatusCode::FOUND))
2019-12-07 18:59:24 +01:00
} else {
2022-02-05 18:34:43 +01:00
db::create_task(params.into_inner().description, &pool)
.await
.map_err(error::ErrorInternalServerError)?;
2022-07-09 22:05:06 +02:00
2019-12-07 18:59:24 +01:00
session::set_flash(&session, FlashMessage::success("Task successfully added"))?;
2022-07-09 22:05:06 +02:00
2023-03-14 03:40:02 +01:00
Ok(web::Redirect::to("/").using_status_code(StatusCode::FOUND))
2019-12-07 18:59:24 +01:00
}
}
2022-07-09 22:05:06 +02:00
#[derive(Debug, Deserialize)]
2019-12-07 18:59:24 +01:00
pub struct UpdateParams {
id: i32,
}
2022-07-09 22:05:06 +02:00
#[derive(Debug, Deserialize)]
2019-12-07 18:59:24 +01:00
pub struct UpdateForm {
_method: String,
}
pub async fn update(
2022-02-06 08:55:51 +01:00
db: web::Data<SqlitePool>,
2019-12-07 18:59:24 +01:00
params: web::Path<UpdateParams>,
form: web::Form<UpdateForm>,
session: Session,
2022-07-09 22:05:06 +02:00
) -> Result<impl Responder, Error> {
2023-03-14 03:40:02 +01:00
Ok(web::Redirect::to(match form._method.as_ref() {
2022-07-09 22:05:06 +02:00
"put" => toggle(db, params).await?,
"delete" => delete(db, params, session).await?,
2019-12-07 18:59:24 +01:00
unsupported_method => {
let msg = format!("Unsupported HTTP method: {unsupported_method}");
2022-07-09 22:05:06 +02:00
return Err(error::ErrorBadRequest(msg));
2019-12-07 18:59:24 +01:00
}
})
.using_status_code(StatusCode::FOUND))
2019-12-07 18:59:24 +01:00
}
async fn toggle(
2022-02-06 08:55:51 +01:00
pool: web::Data<SqlitePool>,
2019-12-07 18:59:24 +01:00
params: web::Path<UpdateParams>,
2022-07-09 22:05:06 +02:00
) -> Result<&'static str, Error> {
2022-02-05 18:34:43 +01:00
db::toggle_task(params.id, &pool)
.await
.map_err(error::ErrorInternalServerError)?;
2022-07-09 22:05:06 +02:00
Ok("/")
2019-12-07 18:59:24 +01:00
}
async fn delete(
2022-02-06 08:55:51 +01:00
pool: web::Data<SqlitePool>,
2019-12-07 18:59:24 +01:00
params: web::Path<UpdateParams>,
session: Session,
2022-07-09 22:05:06 +02:00
) -> Result<&'static str, Error> {
2022-02-05 18:34:43 +01:00
db::delete_task(params.id, &pool)
.await
.map_err(error::ErrorInternalServerError)?;
2022-07-09 22:05:06 +02:00
2019-12-07 18:59:24 +01:00
session::set_flash(&session, FlashMessage::success("Task was deleted."))?;
2022-07-09 22:05:06 +02:00
Ok("/")
2019-12-07 18:59:24 +01:00
}
pub fn bad_request<B>(res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
let new_resp = NamedFile::open("static/errors/400.html")?
2022-07-09 22:05:06 +02:00
.customize()
.with_status(res.status())
.respond_to(res.request())
.map_into_boxed_body()
.map_into_right_body();
2022-07-09 22:05:06 +02:00
Ok(ErrorHandlerResponse::Response(res.into_response(new_resp)))
2019-12-07 18:59:24 +01:00
}
pub fn not_found<B>(res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
let new_resp = NamedFile::open("static/errors/404.html")?
2022-07-09 22:05:06 +02:00
.customize()
.with_status(res.status())
.respond_to(res.request())
.map_into_boxed_body()
.map_into_right_body();
2022-07-09 22:05:06 +02:00
Ok(ErrorHandlerResponse::Response(res.into_response(new_resp)))
2019-12-07 18:59:24 +01:00
}
2022-02-18 03:44:02 +01:00
pub fn internal_server_error<B>(res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
2019-12-07 18:59:24 +01:00
let new_resp = NamedFile::open("static/errors/500.html")?
2022-07-09 22:05:06 +02:00
.customize()
.with_status(res.status())
.respond_to(res.request())
.map_into_boxed_body()
.map_into_right_body();
2022-07-09 22:05:06 +02:00
Ok(ErrorHandlerResponse::Response(res.into_response(new_resp)))
2019-12-07 18:59:24 +01:00
}