diff options
author | Adam T. Carpenter <atc@53hor.net> | 2020-11-02 20:36:18 -0500 |
---|---|---|
committer | Adam T. Carpenter <atc@53hor.net> | 2020-11-02 20:36:18 -0500 |
commit | dcc96d0b349583e5d6a0f25ae1f7a3ffa3769788 (patch) | |
tree | 98a9cc9d322e309c05db400f4c536164bee4daac /dichroism/src/handlers.rs | |
parent | 9480317011b57d3be7b903048f4a85d02979c7c7 (diff) | |
download | theglassyladies-dcc96d0b349583e5d6a0f25ae1f7a3ffa3769788.tar.xz theglassyladies-dcc96d0b349583e5d6a0f25ae1f7a3ffa3769788.zip |
swapped json payload url encoded images for multipart form data
Diffstat (limited to 'dichroism/src/handlers.rs')
-rw-r--r-- | dichroism/src/handlers.rs | 99 |
1 files changed, 61 insertions, 38 deletions
diff --git a/dichroism/src/handlers.rs b/dichroism/src/handlers.rs index 5d678f5..43c11d2 100644 --- a/dichroism/src/handlers.rs +++ b/dichroism/src/handlers.rs @@ -1,9 +1,11 @@ use crate::dtos::*; use crate::image_service; use crate::models::Product; -use crate::repo; +use crate::repo::{photo_set_repo, product_repo}; use crate::types::DbPool; +use actix_multipart::Multipart; use actix_web::{get, patch, post, web, Error, HttpResponse, Responder}; +use futures::{StreamExt, TryStreamExt}; fn to_internal_error(e: impl std::error::Error) -> HttpResponse { eprintln!("{}", e); @@ -18,7 +20,7 @@ async fn hello() -> impl Responder { #[get("/products")] async fn get_products(pool: web::Data<DbPool>) -> Result<HttpResponse, Error> { let conn = pool.get().map_err(to_internal_error)?; - let products: Vec<ProductGet> = web::block(move || repo::find_all(&conn)) + let products: Vec<ProductGet> = web::block(move || product_repo::find_all(&conn)) .await .map_err(to_internal_error)? .into_iter() @@ -30,43 +32,33 @@ async fn get_products(pool: web::Data<DbPool>) -> Result<HttpResponse, Error> { #[patch("/products")] async fn patch_product( pool: web::Data<DbPool>, - patch: web::Json<ProductPatch>, + web::Json(patch): web::Json<ProductPatch>, ) -> Result<HttpResponse, Error> { - let patch = patch.into_inner(); let id = patch.id; + // get product referenced by patch let conn = pool.get().map_err(to_internal_error)?; - let mut product = web::block(move || repo::find(&conn, id)) + let mut product = web::block(move || product_repo::find(&conn, id)) .await .map_err(to_internal_error)? .ok_or_else(|| HttpResponse::NotFound().finish())?; - if let Some(data_uri) = patch.photo_data { - // create new photo_set - let photo_set = web::block(move || image_service::generate_photo_set(&data_uri)) - .await - .map_err(|e| { - eprintln!("{}", e.to_string()); - HttpResponse::InternalServerError().body(e.to_string()) - })?; + // get photo set referenced by patch + if let Some(id) = patch.photo_set { let conn = pool.get().map_err(to_internal_error)?; - let photo_set = web::block(move || repo::store_photo_set(&conn, photo_set)) + let photo_set = web::block(move || photo_set_repo::find(&conn, id)) .await - .map_err(to_internal_error)?; + .map_err(to_internal_error)? + .ok_or_else(|| HttpResponse::NotFound().body("Photo set not found"))?; product.photo_set = photo_set; } - // patch the rest of the product - product.name = patch.name.unwrap_or(product.name); - product.quantity = patch.quantity.unwrap_or(product.quantity); - product.cents = patch.cents.unwrap_or(product.cents); - product.description = patch.description.unwrap_or(product.description); - product.featured = patch.featured.unwrap_or(product.featured); - product.category = patch.category_path.unwrap_or(product.category); + // update product fields + patch.patch(&mut product); // store the updated product let conn = pool.get().map_err(to_internal_error)?; - let product = web::block(move || repo::store_product(&conn, product)) + let product = web::block(move || product_repo::store(&conn, product)) .await .map_err(to_internal_error)?; @@ -76,24 +68,17 @@ async fn patch_product( #[post("/products")] async fn post_product( pool: web::Data<DbPool>, - post: web::Json<ProductPost>, + web::Json(post): web::Json<ProductPost>, ) -> Result<HttpResponse, Error> { - let post = post.into_inner(); - dbg!(&post); - - // create new photo_set - let data_uri = post.photo_data; - let photo_set = web::block(move || image_service::generate_photo_set(&data_uri)) - .await - .map_err(|e| { - eprintln!("{}", e.to_string()); - HttpResponse::InternalServerError().body(e.to_string()) - })?; + // find associated photo set + let photo_set = post.photo_set; let conn = pool.get().map_err(to_internal_error)?; - let photo_set = web::block(move || repo::store_photo_set(&conn, photo_set)) + let photo_set = web::block(move || photo_set_repo::find(&conn, photo_set)) .await - .map_err(to_internal_error)?; + .map_err(to_internal_error)? + .ok_or_else(|| HttpResponse::NotFound().body("Photo set not found."))?; + // create new product let product = Product { id: None, name: post.name, @@ -105,10 +90,48 @@ async fn post_product( photo_set, }; + // store product let conn = pool.get().map_err(to_internal_error)?; - let product = web::block(move || repo::store_product(&conn, product)) + let product = web::block(move || product_repo::store(&conn, product)) .await .map_err(to_internal_error)?; Ok(HttpResponse::Ok().json::<ProductGet>(product.into())) } + +#[post("/photos")] +async fn post_photo( + pool: web::Data<DbPool>, + mut payload: Multipart, +) -> Result<HttpResponse, Error> { + let mut responses: Vec<PhotoSetGet> = Vec::new(); + + if let Ok(Some(mut field)) = payload.try_next().await { + // bail if a non-JPEG file was going to be uploaded + if field.content_type() != &mime::IMAGE_JPEG { + return Ok(HttpResponse::BadRequest().body("File must be a JPEG image.")); + } + + // grab all bytes + let mut data: Vec<u8> = Vec::new(); + while let Some(chunk) = field.next().await { + let chunk = chunk?; + data.extend(chunk); + } + + // create new photo_set + let photo_set = web::block(move || image_service::generate_photo_set(&data)) + .await + .map_err(|e| { + eprintln!("{}", e.to_string()); + HttpResponse::InternalServerError().body(e.to_string()) + })?; + let conn = pool.get().map_err(to_internal_error)?; + let photo_set = web::block(move || photo_set_repo::store(&conn, photo_set)) + .await + .map_err(to_internal_error)?; + responses.push(photo_set.into()); + } + + Ok(HttpResponse::Ok().json(responses)) +} |