mirror of
https://gitlab.com/comunic/comunicapiv3
synced 2024-11-22 13:29:21 +00:00
Handle multipart requests
This commit is contained in:
parent
bab1fe8272
commit
25a368fd98
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -529,6 +529,7 @@ dependencies = [
|
|||||||
"actix-multipart",
|
"actix-multipart",
|
||||||
"actix-rt",
|
"actix-rt",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
|
"bytes",
|
||||||
"chrono",
|
"chrono",
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"futures",
|
"futures",
|
||||||
|
@ -20,4 +20,5 @@ percent-encoding = "2.1.0"
|
|||||||
mailchecker = "3.3.6"
|
mailchecker = "3.3.6"
|
||||||
sha1 = "0.6.0"
|
sha1 = "0.6.0"
|
||||||
rand = "0.7.3"
|
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::{App, FromRequest, http, HttpMessage, HttpRequest, HttpResponse, HttpServer, web};
|
||||||
use actix_web::dev::{Decompress, Payload, PayloadStream};
|
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 actix_web::web::{Bytes, BytesMut};
|
||||||
|
use bytes::{Buf, BufMut};
|
||||||
use encoding_rs::UTF_8;
|
use encoding_rs::UTF_8;
|
||||||
use futures::{FutureExt, Stream, StreamExt};
|
use futures::{FutureExt, Stream, StreamExt};
|
||||||
use futures::future::LocalBoxFuture;
|
use futures::future::LocalBoxFuture;
|
||||||
@ -133,18 +134,51 @@ impl FromRequest for CustomRequest {
|
|||||||
// Add the value to the body
|
// Add the value to the body
|
||||||
body_args.insert(
|
body_args.insert(
|
||||||
percent_decode_str(args[0]).decode_utf8_lossy().to_string(),
|
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
|
// Process "multipart/form-data" request
|
||||||
else if req.content_type().starts_with("multipart/form-data") {
|
else if req.content_type().starts_with("multipart/form-data") {
|
||||||
let mut req = actix_multipart::Multipart::new(req.headers(), payload);
|
let mut req = actix_multipart::Multipart::new(req.headers(), payload);
|
||||||
|
|
||||||
|
// Process the list of arguments
|
||||||
while let Some(el) = req.next().await {
|
while let Some(el) = req.next().await {
|
||||||
let mut field = el?;
|
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::data::user::UserID;
|
||||||
use crate::helpers::{account_helper, api_helper, user_helper, conversations_helper};
|
use crate::helpers::{account_helper, api_helper, user_helper, conversations_helper};
|
||||||
use crate::utils::virtual_directories_utils::check_virtual_directory;
|
use crate::utils::virtual_directories_utils::check_virtual_directory;
|
||||||
|
use bytes::Bytes;
|
||||||
|
|
||||||
/// Http request handler
|
/// Http request handler
|
||||||
///
|
///
|
||||||
/// @author Pierre Hubert
|
/// @author Pierre Hubert
|
||||||
|
|
||||||
/// Single request body value
|
/// Single request body value
|
||||||
pub struct RequestValue {
|
pub enum RequestValue {
|
||||||
pub string: Option<String>
|
String(String),
|
||||||
}
|
File(String, Bytes),
|
||||||
|
|
||||||
impl RequestValue {
|
|
||||||
/// Build a string value
|
|
||||||
pub fn string(s: String) -> RequestValue {
|
|
||||||
RequestValue {
|
|
||||||
string: Some(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
@ -187,19 +180,19 @@ impl HttpRequestHandler {
|
|||||||
-> ResultBoxError<String> {
|
-> ResultBoxError<String> {
|
||||||
let param = self.post_parameter(name)?;
|
let param = self.post_parameter(name)?;
|
||||||
|
|
||||||
match (¶m.string, required) {
|
match (¶m, required) {
|
||||||
(None, true) =>
|
(RequestValue::String(s), _) => {
|
||||||
Err(self.bad_request(format!("'{}' is not a string!", name)).unwrap_err()),
|
|
||||||
|
|
||||||
(None, false) => Ok(String::new()),
|
|
||||||
|
|
||||||
(Some(s), _) => {
|
|
||||||
if s.len() >= min_length {
|
if s.len() >= min_length {
|
||||||
Ok(s.to_string())
|
Ok(s.to_string())
|
||||||
} else {
|
} else {
|
||||||
Err(self.bad_request(format!("'{}' is too short!", name)).unwrap_err())
|
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()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user