forked from loafle/openapi-generator-original
[Rust Server] Allow configuration of multipart/form attachment size limit (#19371)
* [Rust Server] Allow configuration of multipart/form attachment size limit multipart 0.14+ imposes a 8MB size limit on multipart/form bodies. This allows that limit to be configured. The default is left as is. This also improves error messages produced when handling multipart/form bodies. * Update samples
This commit is contained in:
parent
bb831dad9a
commit
0a5c99739a
@ -19,7 +19,7 @@ use mime_multipart::{read_multipart_body, Node, Part};
|
||||
{{/apiUsesMultipartRelated}}
|
||||
{{#apiUsesMultipartFormData}}
|
||||
use multipart::server::Multipart;
|
||||
use multipart::server::save::SaveResult;
|
||||
use multipart::server::save::{PartialReason, SaveResult};
|
||||
{{/apiUsesMultipartFormData}}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
|
@ -4,6 +4,9 @@ pub struct MakeService<T, C> where
|
||||
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<Authorization>>{{/hasAuthMethods}} + Send + Sync + 'static
|
||||
{
|
||||
api_impl: T,
|
||||
{{#apiUsesMultipartFormData}}
|
||||
multipart_form_size_limit: Option<u64>,
|
||||
{{/apiUsesMultipartFormData}}
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
@ -14,11 +17,25 @@ impl<T, C> MakeService<T, C> where
|
||||
pub fn new(api_impl: T) -> Self {
|
||||
MakeService {
|
||||
api_impl,
|
||||
{{#apiUsesMultipartFormData}}
|
||||
multipart_form_size_limit: Some(8 * 1024 * 1024),
|
||||
{{/apiUsesMultipartFormData}}
|
||||
marker: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
{{#apiUsesMultipartFormData}}
|
||||
|
||||
/// Configure size limit when inspecting a multipart/form body.
|
||||
///
|
||||
/// Default is 8 MiB.
|
||||
///
|
||||
/// Set to None for no size limit, which presents a Denial of Service attack risk.
|
||||
pub fn multipart_form_size_limit(mut self, multipart_form_size_limit: Option<u64>) -> Self {
|
||||
self.multipart_form_size_limit = multipart_form_size_limit;
|
||||
self
|
||||
}
|
||||
{{/apiUsesMultipartFormData}}
|
||||
}
|
||||
|
||||
impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
@ -33,8 +50,11 @@ impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
}
|
||||
|
||||
fn call(&mut self, target: Target) -> Self::Future {
|
||||
future::ok(Service::new(
|
||||
self.api_impl.clone(),
|
||||
))
|
||||
let service = Service::new(self.api_impl.clone()){{^apiUsesMultipartFormData}};{{/apiUsesMultipartFormData}}
|
||||
{{#apiUsesMultipartFormData}}
|
||||
.multipart_form_size_limit(self.multipart_form_size_limit);
|
||||
{{/apiUsesMultipartFormData}}
|
||||
|
||||
future::ok(service)
|
||||
}
|
||||
}
|
||||
|
@ -9,15 +9,43 @@
|
||||
use std::io::Read;
|
||||
|
||||
// Read Form Parameters from body
|
||||
let mut entries = match Multipart::with_body(&body.to_vec()[..], boundary).save().temp() {
|
||||
let mut entries = match Multipart::with_body(&body.to_vec()[..], boundary)
|
||||
.save()
|
||||
.size_limit(multipart_form_size_limit)
|
||||
.temp()
|
||||
{
|
||||
SaveResult::Full(entries) => {
|
||||
entries
|
||||
},
|
||||
_ => {
|
||||
SaveResult::Partial(_, PartialReason::CountLimit) => {
|
||||
return Ok(Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from("Unable to process all message parts".to_string()))
|
||||
.expect("Unable to create Bad Request response due to failure to process all message"))
|
||||
.body(Body::from("Unable to process message part due to excessive parts".to_string()))
|
||||
.expect("Unable to create Bad Request response due to excessive parts"))
|
||||
},
|
||||
SaveResult::Partial(_, PartialReason::SizeLimit) => {
|
||||
return Ok(Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from("Unable to process message part due to excessive data".to_string()))
|
||||
.expect("Unable to create Bad Request response due to excessive data"))
|
||||
},
|
||||
SaveResult::Partial(_, PartialReason::Utf8Error(_)) => {
|
||||
return Ok(Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from("Unable to process message part due to invalid data".to_string()))
|
||||
.expect("Unable to create Bad Request response due to invalid data"))
|
||||
},
|
||||
SaveResult::Partial(_, PartialReason::IoError(_)) => {
|
||||
return Ok(Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from("Failed to process message part due an internal error".to_string()))
|
||||
.expect("Unable to create Internal Server Error response due to an internal errror"))
|
||||
},
|
||||
SaveResult::Error(e) => {
|
||||
return Ok(Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from("Failed to process all message parts due to an internal error".to_string()))
|
||||
.expect("Unable to create Internal Server Error response due to an internal error"))
|
||||
},
|
||||
};
|
||||
{{#formParams}}
|
||||
|
@ -2,5 +2,13 @@
|
||||
.body(Body::empty())
|
||||
.expect("Unable to create Not Found response"))
|
||||
}
|
||||
} Box::pin(run(self.api_impl.clone(), req)) }
|
||||
}
|
||||
Box::pin(run(
|
||||
self.api_impl.clone(),
|
||||
req,
|
||||
{{#apiUsesMultipartFormData}}
|
||||
self.multipart_form_size_limit,
|
||||
{{/apiUsesMultipartFormData}}
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,9 @@ pub struct Service<T, C> where
|
||||
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<Authorization>>{{/hasAuthMethods}} + Send + Sync + 'static
|
||||
{
|
||||
api_impl: T,
|
||||
{{#apiUsesMultipart}}
|
||||
multipart_form_size_limit: Option<u64>,
|
||||
{{/apiUsesMultipart}}
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
@ -21,9 +24,24 @@ impl<T, C> Service<T, C> where
|
||||
pub fn new(api_impl: T) -> Self {
|
||||
Service {
|
||||
api_impl,
|
||||
{{#apiUsesMultipart}}
|
||||
multipart_form_size_limit: Some(8 * 1024 * 1024),
|
||||
{{/apiUsesMultipart}}
|
||||
marker: PhantomData
|
||||
}
|
||||
}
|
||||
{{#apiUsesMultipart}}
|
||||
|
||||
/// Configure size limit when extracting a multipart/form body.
|
||||
///
|
||||
/// Default is 8 MiB.
|
||||
///
|
||||
/// Set to None for no size limit, which presents a Denial of Service attack risk.
|
||||
pub fn multipart_form_size_limit(mut self, multipart_form_size_limit: Option<u64>) -> Self {
|
||||
self.multipart_form_size_limit = multipart_form_size_limit;
|
||||
self
|
||||
}
|
||||
{{/apiUsesMultipart}}
|
||||
}
|
||||
|
||||
impl<T, C> Clone for Service<T, C> where
|
||||
@ -33,6 +51,9 @@ impl<T, C> Clone for Service<T, C> where
|
||||
fn clone(&self) -> Self {
|
||||
Service {
|
||||
api_impl: self.api_impl.clone(),
|
||||
{{#apiUsesMultipart}}
|
||||
multipart_form_size_limit: Some(8 * 1024 * 1024),
|
||||
{{/apiUsesMultipart}}
|
||||
marker: self.marker,
|
||||
}
|
||||
}
|
||||
@ -50,7 +71,14 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
self.api_impl.poll_ready(cx)
|
||||
}
|
||||
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future { async fn run<T, C>(mut api_impl: T, req: (Request<Body>, C)) -> Result<Response<Body>, crate::ServiceError> where
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future {
|
||||
async fn run<T, C>(
|
||||
mut api_impl: T,
|
||||
req: (Request<Body>, C),
|
||||
{{#apiUsesMultipartFormData}}
|
||||
multipart_form_size_limit: Option<u64>,
|
||||
{{/apiUsesMultipartFormData}}
|
||||
) -> Result<Response<Body>, crate::ServiceError> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<Authorization>>{{/hasAuthMethods}} + Send + Sync + 'static
|
||||
{
|
||||
|
@ -16,7 +16,7 @@ use hyper_0_10::header::{Headers, ContentType};
|
||||
use mime_0_2::{TopLevel, SubLevel, Mime as Mime2};
|
||||
use mime_multipart::{read_multipart_body, Node, Part};
|
||||
use multipart::server::Multipart;
|
||||
use multipart::server::save::SaveResult;
|
||||
use multipart::server::save::{PartialReason, SaveResult};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use crate::{models, header, AuthenticationApi};
|
||||
@ -55,6 +55,7 @@ pub struct MakeService<T, C> where
|
||||
C: Has<XSpanIdString> + Send + Sync + 'static
|
||||
{
|
||||
api_impl: T,
|
||||
multipart_form_size_limit: Option<u64>,
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
@ -65,11 +66,21 @@ impl<T, C> MakeService<T, C> where
|
||||
pub fn new(api_impl: T) -> Self {
|
||||
MakeService {
|
||||
api_impl,
|
||||
multipart_form_size_limit: Some(8 * 1024 * 1024),
|
||||
marker: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Configure size limit when inspecting a multipart/form body.
|
||||
///
|
||||
/// Default is 8 MiB.
|
||||
///
|
||||
/// Set to None for no size limit, which presents a Denial of Service attack risk.
|
||||
pub fn multipart_form_size_limit(mut self, multipart_form_size_limit: Option<u64>) -> Self {
|
||||
self.multipart_form_size_limit = multipart_form_size_limit;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
@ -84,9 +95,10 @@ impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
}
|
||||
|
||||
fn call(&mut self, target: Target) -> Self::Future {
|
||||
future::ok(Service::new(
|
||||
self.api_impl.clone(),
|
||||
))
|
||||
let service = Service::new(self.api_impl.clone())
|
||||
.multipart_form_size_limit(self.multipart_form_size_limit);
|
||||
|
||||
future::ok(service)
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,6 +115,7 @@ pub struct Service<T, C> where
|
||||
C: Has<XSpanIdString> + Send + Sync + 'static
|
||||
{
|
||||
api_impl: T,
|
||||
multipart_form_size_limit: Option<u64>,
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
@ -113,9 +126,20 @@ impl<T, C> Service<T, C> where
|
||||
pub fn new(api_impl: T) -> Self {
|
||||
Service {
|
||||
api_impl,
|
||||
multipart_form_size_limit: Some(8 * 1024 * 1024),
|
||||
marker: PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
/// Configure size limit when extracting a multipart/form body.
|
||||
///
|
||||
/// Default is 8 MiB.
|
||||
///
|
||||
/// Set to None for no size limit, which presents a Denial of Service attack risk.
|
||||
pub fn multipart_form_size_limit(mut self, multipart_form_size_limit: Option<u64>) -> Self {
|
||||
self.multipart_form_size_limit = multipart_form_size_limit;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C> Clone for Service<T, C> where
|
||||
@ -125,6 +149,7 @@ impl<T, C> Clone for Service<T, C> where
|
||||
fn clone(&self) -> Self {
|
||||
Service {
|
||||
api_impl: self.api_impl.clone(),
|
||||
multipart_form_size_limit: Some(8 * 1024 * 1024),
|
||||
marker: self.marker,
|
||||
}
|
||||
}
|
||||
@ -142,7 +167,12 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
self.api_impl.poll_ready(cx)
|
||||
}
|
||||
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future { async fn run<T, C>(mut api_impl: T, req: (Request<Body>, C)) -> Result<Response<Body>, crate::ServiceError> where
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future {
|
||||
async fn run<T, C>(
|
||||
mut api_impl: T,
|
||||
req: (Request<Body>, C),
|
||||
multipart_form_size_limit: Option<u64>,
|
||||
) -> Result<Response<Body>, crate::ServiceError> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
C: Has<XSpanIdString> + Send + Sync + 'static
|
||||
{
|
||||
@ -303,15 +333,43 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
use std::io::Read;
|
||||
|
||||
// Read Form Parameters from body
|
||||
let mut entries = match Multipart::with_body(&body.to_vec()[..], boundary).save().temp() {
|
||||
let mut entries = match Multipart::with_body(&body.to_vec()[..], boundary)
|
||||
.save()
|
||||
.size_limit(multipart_form_size_limit)
|
||||
.temp()
|
||||
{
|
||||
SaveResult::Full(entries) => {
|
||||
entries
|
||||
},
|
||||
_ => {
|
||||
SaveResult::Partial(_, PartialReason::CountLimit) => {
|
||||
return Ok(Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from("Unable to process all message parts".to_string()))
|
||||
.expect("Unable to create Bad Request response due to failure to process all message"))
|
||||
.body(Body::from("Unable to process message part due to excessive parts".to_string()))
|
||||
.expect("Unable to create Bad Request response due to excessive parts"))
|
||||
},
|
||||
SaveResult::Partial(_, PartialReason::SizeLimit) => {
|
||||
return Ok(Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from("Unable to process message part due to excessive data".to_string()))
|
||||
.expect("Unable to create Bad Request response due to excessive data"))
|
||||
},
|
||||
SaveResult::Partial(_, PartialReason::Utf8Error(_)) => {
|
||||
return Ok(Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from("Unable to process message part due to invalid data".to_string()))
|
||||
.expect("Unable to create Bad Request response due to invalid data"))
|
||||
},
|
||||
SaveResult::Partial(_, PartialReason::IoError(_)) => {
|
||||
return Ok(Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from("Failed to process message part due an internal error".to_string()))
|
||||
.expect("Unable to create Internal Server Error response due to an internal errror"))
|
||||
},
|
||||
SaveResult::Error(e) => {
|
||||
return Ok(Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from("Failed to process all message parts due to an internal error".to_string()))
|
||||
.expect("Unable to create Internal Server Error response due to an internal error"))
|
||||
},
|
||||
};
|
||||
let field_string_field = entries.fields.remove("string_field");
|
||||
@ -557,7 +615,13 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
.body(Body::empty())
|
||||
.expect("Unable to create Not Found response"))
|
||||
}
|
||||
} Box::pin(run(self.api_impl.clone(), req)) }
|
||||
}
|
||||
Box::pin(run(
|
||||
self.api_impl.clone(),
|
||||
req,
|
||||
self.multipart_form_size_limit,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Request parser for `Api`.
|
||||
|
@ -59,7 +59,6 @@ impl<T, C> MakeService<T, C> where
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
C: Has<XSpanIdString> + Send + Sync + 'static
|
||||
@ -73,9 +72,9 @@ impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
}
|
||||
|
||||
fn call(&mut self, target: Target) -> Self::Future {
|
||||
future::ok(Service::new(
|
||||
self.api_impl.clone(),
|
||||
))
|
||||
let service = Service::new(self.api_impl.clone());
|
||||
|
||||
future::ok(service)
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,7 +130,11 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
self.api_impl.poll_ready(cx)
|
||||
}
|
||||
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future { async fn run<T, C>(mut api_impl: T, req: (Request<Body>, C)) -> Result<Response<Body>, crate::ServiceError> where
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future {
|
||||
async fn run<T, C>(
|
||||
mut api_impl: T,
|
||||
req: (Request<Body>, C),
|
||||
) -> Result<Response<Body>, crate::ServiceError> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
C: Has<XSpanIdString> + Send + Sync + 'static
|
||||
{
|
||||
@ -221,7 +224,12 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
.body(Body::empty())
|
||||
.expect("Unable to create Not Found response"))
|
||||
}
|
||||
} Box::pin(run(self.api_impl.clone(), req)) }
|
||||
}
|
||||
Box::pin(run(
|
||||
self.api_impl.clone(),
|
||||
req,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Request parser for `Api`.
|
||||
|
@ -72,7 +72,6 @@ impl<T, C> MakeService<T, C> where
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
C: Has<XSpanIdString> + Has<Option<Authorization>> + Send + Sync + 'static
|
||||
@ -86,9 +85,9 @@ impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
}
|
||||
|
||||
fn call(&mut self, target: Target) -> Self::Future {
|
||||
future::ok(Service::new(
|
||||
self.api_impl.clone(),
|
||||
))
|
||||
let service = Service::new(self.api_impl.clone());
|
||||
|
||||
future::ok(service)
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,7 +144,11 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
self.api_impl.poll_ready(cx)
|
||||
}
|
||||
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future { async fn run<T, C>(mut api_impl: T, req: (Request<Body>, C)) -> Result<Response<Body>, crate::ServiceError> where
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future {
|
||||
async fn run<T, C>(
|
||||
mut api_impl: T,
|
||||
req: (Request<Body>, C),
|
||||
) -> Result<Response<Body>, crate::ServiceError> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
C: Has<XSpanIdString> + Has<Option<Authorization>> + Send + Sync + 'static
|
||||
{
|
||||
@ -265,7 +268,12 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
.body(Body::empty())
|
||||
.expect("Unable to create Not Found response"))
|
||||
}
|
||||
} Box::pin(run(self.api_impl.clone(), req)) }
|
||||
}
|
||||
Box::pin(run(
|
||||
self.api_impl.clone(),
|
||||
req,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Request parser for `Api`.
|
||||
|
@ -144,7 +144,6 @@ impl<T, C> MakeService<T, C> where
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
C: Has<XSpanIdString> + Has<Option<Authorization>> + Send + Sync + 'static
|
||||
@ -158,9 +157,9 @@ impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
}
|
||||
|
||||
fn call(&mut self, target: Target) -> Self::Future {
|
||||
future::ok(Service::new(
|
||||
self.api_impl.clone(),
|
||||
))
|
||||
let service = Service::new(self.api_impl.clone());
|
||||
|
||||
future::ok(service)
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,7 +215,11 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
self.api_impl.poll_ready(cx)
|
||||
}
|
||||
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future { async fn run<T, C>(mut api_impl: T, req: (Request<Body>, C)) -> Result<Response<Body>, crate::ServiceError> where
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future {
|
||||
async fn run<T, C>(
|
||||
mut api_impl: T,
|
||||
req: (Request<Body>, C),
|
||||
) -> Result<Response<Body>, crate::ServiceError> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
C: Has<XSpanIdString> + Has<Option<Authorization>> + Send + Sync + 'static
|
||||
{
|
||||
@ -1935,7 +1938,12 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
.body(Body::empty())
|
||||
.expect("Unable to create Not Found response"))
|
||||
}
|
||||
} Box::pin(run(self.api_impl.clone(), req)) }
|
||||
}
|
||||
Box::pin(run(
|
||||
self.api_impl.clone(),
|
||||
req,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Request parser for `Api`.
|
||||
|
@ -167,7 +167,6 @@ impl<T, C> MakeService<T, C> where
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
C: Has<XSpanIdString> + Send + Sync + 'static
|
||||
@ -181,9 +180,9 @@ impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
}
|
||||
|
||||
fn call(&mut self, target: Target) -> Self::Future {
|
||||
future::ok(Service::new(
|
||||
self.api_impl.clone(),
|
||||
))
|
||||
let service = Service::new(self.api_impl.clone());
|
||||
|
||||
future::ok(service)
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,7 +238,11 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
self.api_impl.poll_ready(cx)
|
||||
}
|
||||
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future { async fn run<T, C>(mut api_impl: T, req: (Request<Body>, C)) -> Result<Response<Body>, crate::ServiceError> where
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future {
|
||||
async fn run<T, C>(
|
||||
mut api_impl: T,
|
||||
req: (Request<Body>, C),
|
||||
) -> Result<Response<Body>, crate::ServiceError> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
C: Has<XSpanIdString> + Send + Sync + 'static
|
||||
{
|
||||
@ -1401,7 +1404,12 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
.body(Body::empty())
|
||||
.expect("Unable to create Not Found response"))
|
||||
}
|
||||
} Box::pin(run(self.api_impl.clone(), req)) }
|
||||
}
|
||||
Box::pin(run(
|
||||
self.api_impl.clone(),
|
||||
req,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Request parser for `Api`.
|
||||
|
@ -13,7 +13,7 @@ pub use swagger::auth::Authorization;
|
||||
use swagger::auth::Scopes;
|
||||
use url::form_urlencoded;
|
||||
use multipart::server::Multipart;
|
||||
use multipart::server::save::SaveResult;
|
||||
use multipart::server::save::{PartialReason, SaveResult};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use crate::{models, header, AuthenticationApi};
|
||||
@ -162,6 +162,7 @@ pub struct MakeService<T, C> where
|
||||
C: Has<XSpanIdString> + Has<Option<Authorization>> + Send + Sync + 'static
|
||||
{
|
||||
api_impl: T,
|
||||
multipart_form_size_limit: Option<u64>,
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
@ -172,11 +173,21 @@ impl<T, C> MakeService<T, C> where
|
||||
pub fn new(api_impl: T) -> Self {
|
||||
MakeService {
|
||||
api_impl,
|
||||
multipart_form_size_limit: Some(8 * 1024 * 1024),
|
||||
marker: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Configure size limit when inspecting a multipart/form body.
|
||||
///
|
||||
/// Default is 8 MiB.
|
||||
///
|
||||
/// Set to None for no size limit, which presents a Denial of Service attack risk.
|
||||
pub fn multipart_form_size_limit(mut self, multipart_form_size_limit: Option<u64>) -> Self {
|
||||
self.multipart_form_size_limit = multipart_form_size_limit;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
@ -191,9 +202,10 @@ impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
}
|
||||
|
||||
fn call(&mut self, target: Target) -> Self::Future {
|
||||
future::ok(Service::new(
|
||||
self.api_impl.clone(),
|
||||
))
|
||||
let service = Service::new(self.api_impl.clone())
|
||||
.multipart_form_size_limit(self.multipart_form_size_limit);
|
||||
|
||||
future::ok(service)
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,6 +222,7 @@ pub struct Service<T, C> where
|
||||
C: Has<XSpanIdString> + Has<Option<Authorization>> + Send + Sync + 'static
|
||||
{
|
||||
api_impl: T,
|
||||
multipart_form_size_limit: Option<u64>,
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
@ -220,9 +233,20 @@ impl<T, C> Service<T, C> where
|
||||
pub fn new(api_impl: T) -> Self {
|
||||
Service {
|
||||
api_impl,
|
||||
multipart_form_size_limit: Some(8 * 1024 * 1024),
|
||||
marker: PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
/// Configure size limit when extracting a multipart/form body.
|
||||
///
|
||||
/// Default is 8 MiB.
|
||||
///
|
||||
/// Set to None for no size limit, which presents a Denial of Service attack risk.
|
||||
pub fn multipart_form_size_limit(mut self, multipart_form_size_limit: Option<u64>) -> Self {
|
||||
self.multipart_form_size_limit = multipart_form_size_limit;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C> Clone for Service<T, C> where
|
||||
@ -232,6 +256,7 @@ impl<T, C> Clone for Service<T, C> where
|
||||
fn clone(&self) -> Self {
|
||||
Service {
|
||||
api_impl: self.api_impl.clone(),
|
||||
multipart_form_size_limit: Some(8 * 1024 * 1024),
|
||||
marker: self.marker,
|
||||
}
|
||||
}
|
||||
@ -249,7 +274,12 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
self.api_impl.poll_ready(cx)
|
||||
}
|
||||
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future { async fn run<T, C>(mut api_impl: T, req: (Request<Body>, C)) -> Result<Response<Body>, crate::ServiceError> where
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future {
|
||||
async fn run<T, C>(
|
||||
mut api_impl: T,
|
||||
req: (Request<Body>, C),
|
||||
multipart_form_size_limit: Option<u64>,
|
||||
) -> Result<Response<Body>, crate::ServiceError> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
C: Has<XSpanIdString> + Has<Option<Authorization>> + Send + Sync + 'static
|
||||
{
|
||||
@ -2148,15 +2178,43 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
use std::io::Read;
|
||||
|
||||
// Read Form Parameters from body
|
||||
let mut entries = match Multipart::with_body(&body.to_vec()[..], boundary).save().temp() {
|
||||
let mut entries = match Multipart::with_body(&body.to_vec()[..], boundary)
|
||||
.save()
|
||||
.size_limit(multipart_form_size_limit)
|
||||
.temp()
|
||||
{
|
||||
SaveResult::Full(entries) => {
|
||||
entries
|
||||
},
|
||||
_ => {
|
||||
SaveResult::Partial(_, PartialReason::CountLimit) => {
|
||||
return Ok(Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from("Unable to process all message parts".to_string()))
|
||||
.expect("Unable to create Bad Request response due to failure to process all message"))
|
||||
.body(Body::from("Unable to process message part due to excessive parts".to_string()))
|
||||
.expect("Unable to create Bad Request response due to excessive parts"))
|
||||
},
|
||||
SaveResult::Partial(_, PartialReason::SizeLimit) => {
|
||||
return Ok(Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from("Unable to process message part due to excessive data".to_string()))
|
||||
.expect("Unable to create Bad Request response due to excessive data"))
|
||||
},
|
||||
SaveResult::Partial(_, PartialReason::Utf8Error(_)) => {
|
||||
return Ok(Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body(Body::from("Unable to process message part due to invalid data".to_string()))
|
||||
.expect("Unable to create Bad Request response due to invalid data"))
|
||||
},
|
||||
SaveResult::Partial(_, PartialReason::IoError(_)) => {
|
||||
return Ok(Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from("Failed to process message part due an internal error".to_string()))
|
||||
.expect("Unable to create Internal Server Error response due to an internal errror"))
|
||||
},
|
||||
SaveResult::Error(e) => {
|
||||
return Ok(Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from("Failed to process all message parts due to an internal error".to_string()))
|
||||
.expect("Unable to create Internal Server Error response due to an internal error"))
|
||||
},
|
||||
};
|
||||
let field_additional_metadata = entries.fields.remove("additional_metadata");
|
||||
@ -3171,7 +3229,13 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
.body(Body::empty())
|
||||
.expect("Unable to create Not Found response"))
|
||||
}
|
||||
} Box::pin(run(self.api_impl.clone(), req)) }
|
||||
}
|
||||
Box::pin(run(
|
||||
self.api_impl.clone(),
|
||||
req,
|
||||
self.multipart_form_size_limit,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Request parser for `Api`.
|
||||
|
@ -59,7 +59,6 @@ impl<T, C> MakeService<T, C> where
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
C: Has<XSpanIdString> + Has<Option<Authorization>> + Send + Sync + 'static
|
||||
@ -73,9 +72,9 @@ impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
}
|
||||
|
||||
fn call(&mut self, target: Target) -> Self::Future {
|
||||
future::ok(Service::new(
|
||||
self.api_impl.clone(),
|
||||
))
|
||||
let service = Service::new(self.api_impl.clone());
|
||||
|
||||
future::ok(service)
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,7 +130,11 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
self.api_impl.poll_ready(cx)
|
||||
}
|
||||
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future { async fn run<T, C>(mut api_impl: T, req: (Request<Body>, C)) -> Result<Response<Body>, crate::ServiceError> where
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future {
|
||||
async fn run<T, C>(
|
||||
mut api_impl: T,
|
||||
req: (Request<Body>, C),
|
||||
) -> Result<Response<Body>, crate::ServiceError> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
C: Has<XSpanIdString> + Has<Option<Authorization>> + Send + Sync + 'static
|
||||
{
|
||||
@ -187,7 +190,12 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
.body(Body::empty())
|
||||
.expect("Unable to create Not Found response"))
|
||||
}
|
||||
} Box::pin(run(self.api_impl.clone(), req)) }
|
||||
}
|
||||
Box::pin(run(
|
||||
self.api_impl.clone(),
|
||||
req,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Request parser for `Api`.
|
||||
|
@ -81,7 +81,6 @@ impl<T, C> MakeService<T, C> where
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
C: Has<XSpanIdString> + Send + Sync + 'static
|
||||
@ -95,9 +94,9 @@ impl<T, C, Target> hyper::service::Service<Target> for MakeService<T, C> where
|
||||
}
|
||||
|
||||
fn call(&mut self, target: Target) -> Self::Future {
|
||||
future::ok(Service::new(
|
||||
self.api_impl.clone(),
|
||||
))
|
||||
let service = Service::new(self.api_impl.clone());
|
||||
|
||||
future::ok(service)
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,7 +152,11 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
self.api_impl.poll_ready(cx)
|
||||
}
|
||||
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future { async fn run<T, C>(mut api_impl: T, req: (Request<Body>, C)) -> Result<Response<Body>, crate::ServiceError> where
|
||||
fn call(&mut self, req: (Request<Body>, C)) -> Self::Future {
|
||||
async fn run<T, C>(
|
||||
mut api_impl: T,
|
||||
req: (Request<Body>, C),
|
||||
) -> Result<Response<Body>, crate::ServiceError> where
|
||||
T: Api<C> + Clone + Send + 'static,
|
||||
C: Has<XSpanIdString> + Send + Sync + 'static
|
||||
{
|
||||
@ -640,7 +643,12 @@ impl<T, C> hyper::service::Service<(Request<Body>, C)> for Service<T, C> where
|
||||
.body(Body::empty())
|
||||
.expect("Unable to create Not Found response"))
|
||||
}
|
||||
} Box::pin(run(self.api_impl.clone(), req)) }
|
||||
}
|
||||
Box::pin(run(
|
||||
self.api_impl.clone(),
|
||||
req,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Request parser for `Api`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user