mirror of
				https://gitlab.com/comunic/comunicapiv3
				synced 2025-10-31 07:34:45 +00:00 
			
		
		
		
	Handle multipart requests
This commit is contained in:
		
							
								
								
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -529,6 +529,7 @@ dependencies = [ | ||||
|  "actix-multipart", | ||||
|  "actix-rt", | ||||
|  "actix-web", | ||||
|  "bytes", | ||||
|  "chrono", | ||||
|  "encoding_rs", | ||||
|  "futures", | ||||
|   | ||||
| @@ -20,4 +20,5 @@ percent-encoding = "2.1.0" | ||||
| mailchecker = "3.3.6" | ||||
| sha1 = "0.6.0" | ||||
| rand = "0.7.3" | ||||
| chrono = "0.4.11" | ||||
| chrono = "0.4.11" | ||||
| bytes = "0.5.4" | ||||
| @@ -3,8 +3,9 @@ use std::pin::Pin; | ||||
|  | ||||
| use actix_web::{App, FromRequest, http, HttpMessage, HttpRequest, HttpResponse, HttpServer, web}; | ||||
| use actix_web::dev::{Decompress, Payload, PayloadStream}; | ||||
| use actix_web::error::{ErrorBadRequest, PayloadError}; | ||||
| use actix_web::error::{ErrorBadRequest, ErrorInternalServerError, PayloadError}; | ||||
| use actix_web::web::{Bytes, BytesMut}; | ||||
| use bytes::{Buf, BufMut}; | ||||
| use encoding_rs::UTF_8; | ||||
| use futures::{FutureExt, Stream, StreamExt}; | ||||
| use futures::future::LocalBoxFuture; | ||||
| @@ -133,18 +134,51 @@ impl FromRequest for CustomRequest { | ||||
|                         // Add the value to the body | ||||
|                         body_args.insert( | ||||
|                             percent_decode_str(args[0]).decode_utf8_lossy().to_string(), | ||||
|                             RequestValue::string(percent_decode_str(args[1]).decode_utf8_lossy().to_string()), | ||||
|                             RequestValue::String(percent_decode_str(args[1]).decode_utf8_lossy().to_string()), | ||||
|                         ); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|  | ||||
|             // Process "multipart/form-data" request | ||||
|             else if req.content_type().starts_with("multipart/form-data") { | ||||
|                 let mut req = actix_multipart::Multipart::new(req.headers(), payload); | ||||
|  | ||||
|                 // Process the list of arguments | ||||
|                 while let Some(el) = req.next().await { | ||||
|                     let mut field = el?; | ||||
|  | ||||
|                     let content_type = field.content_disposition().ok_or( | ||||
|                         ErrorInternalServerError("F1"))?; | ||||
|                     let name = content_type.get_name().ok_or( | ||||
|                         ErrorInternalServerError("Missing field name!"))?; | ||||
|  | ||||
|                     // Handle file upload | ||||
|                     if content_type.get_filename().is_some() && name.eq("file") { | ||||
|                         let filename = content_type.get_filename().unwrap(); | ||||
|                         let mut buf = BytesMut::new(); | ||||
|  | ||||
|                         while let Some(chunk) = field.next().await { | ||||
|                             let data = chunk.unwrap(); | ||||
|                             buf.put(data); | ||||
|                         } | ||||
|  | ||||
|                         body_args.insert(name.to_string(), | ||||
|                                          RequestValue::File(filename.to_string(), buf.to_bytes())); | ||||
|                     } | ||||
|  | ||||
|                     // It is a simple field | ||||
|                     else { | ||||
|                         let mut content = String::new(); | ||||
|  | ||||
|                         // Get content | ||||
|                         while let Some(chunk) = field.next().await { | ||||
|                             content = format!("{}{}", content, String::from_utf8_lossy(chunk?.bytes())); | ||||
|                         } | ||||
|  | ||||
|                         body_args.insert(name.to_string(), RequestValue::String(content)); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -14,23 +14,16 @@ use crate::data::error::{ExecError, ResultBoxError}; | ||||
| use crate::data::user::UserID; | ||||
| use crate::helpers::{account_helper, api_helper, user_helper, conversations_helper}; | ||||
| use crate::utils::virtual_directories_utils::check_virtual_directory; | ||||
| use bytes::Bytes; | ||||
|  | ||||
| /// Http request handler | ||||
| /// | ||||
| /// @author Pierre Hubert | ||||
|  | ||||
| /// Single request body  value | ||||
| pub struct RequestValue { | ||||
|     pub string: Option<String> | ||||
| } | ||||
|  | ||||
| impl RequestValue { | ||||
|     /// Build a string value | ||||
|     pub fn string(s: String) -> RequestValue { | ||||
|         RequestValue { | ||||
|             string: Some(s) | ||||
|         } | ||||
|     } | ||||
| pub enum RequestValue { | ||||
|     String(String), | ||||
|     File(String, Bytes), | ||||
| } | ||||
|  | ||||
| #[derive(Serialize)] | ||||
| @@ -187,19 +180,19 @@ impl HttpRequestHandler { | ||||
|                            -> ResultBoxError<String> { | ||||
|         let param = self.post_parameter(name)?; | ||||
|  | ||||
|         match (¶m.string, required) { | ||||
|             (None, true) => | ||||
|                 Err(self.bad_request(format!("'{}' is not a string!", name)).unwrap_err()), | ||||
|  | ||||
|             (None, false) => Ok(String::new()), | ||||
|  | ||||
|             (Some(s), _) => { | ||||
|         match (¶m, required) { | ||||
|             (RequestValue::String(s), _) => { | ||||
|                 if s.len() >= min_length { | ||||
|                     Ok(s.to_string()) | ||||
|                 } else { | ||||
|                     Err(self.bad_request(format!("'{}' is too short!", name)).unwrap_err()) | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             (_, false) => Ok(String::new()), | ||||
|  | ||||
|             (_, true) => | ||||
|                 Err(self.bad_request(format!("'{}' is not a string!", name)).unwrap_err()), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user