mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-27 17:52:56 +01:00
refactor(multipart): move lints to manifest
This commit is contained in:
parent
7326707599
commit
00c185f617
@ -69,3 +69,8 @@ futures-util = { version = "0.3.17", default-features = false, features = ["allo
|
|||||||
multer = "3"
|
multer = "3"
|
||||||
tokio = { version = "1.24.2", features = ["sync"] }
|
tokio = { version = "1.24.2", features = ["sync"] }
|
||||||
tokio-stream = "0.1"
|
tokio-stream = "0.1"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
future_incompatible = { level = "deny" }
|
||||||
|
rust_2018_idioms = { level = "deny" }
|
||||||
|
nonstandard_style = { level = "deny" }
|
||||||
|
@ -46,9 +46,6 @@
|
|||||||
//! -F file=@./Cargo.lock
|
//! -F file=@./Cargo.lock
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
|
||||||
#![warn(future_incompatible)]
|
|
||||||
#![allow(clippy::borrow_interior_mutable_const)]
|
|
||||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
cell::{RefCell, RefMut},
|
cell::{RefCell, RefMut},
|
||||||
|
cmp,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
@ -75,7 +76,7 @@ impl PayloadBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read exact number of bytes
|
/// Read exact number of bytes.
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) fn read_exact(&mut self, size: usize) -> Option<Bytes> {
|
pub(crate) fn read_exact(&mut self, size: usize) -> Option<Bytes> {
|
||||||
if size <= self.buf.len() {
|
if size <= self.buf.len() {
|
||||||
@ -87,7 +88,7 @@ impl PayloadBuffer {
|
|||||||
|
|
||||||
pub(crate) fn read_max(&mut self, size: u64) -> Result<Option<Bytes>, MultipartError> {
|
pub(crate) fn read_max(&mut self, size: u64) -> Result<Option<Bytes>, MultipartError> {
|
||||||
if !self.buf.is_empty() {
|
if !self.buf.is_empty() {
|
||||||
let size = std::cmp::min(self.buf.len() as u64, size) as usize;
|
let size = cmp::min(self.buf.len() as u64, size) as usize;
|
||||||
Ok(Some(self.buf.split_to(size).freeze()))
|
Ok(Some(self.buf.split_to(size).freeze()))
|
||||||
} else if self.eof {
|
} else if self.eof {
|
||||||
Err(MultipartError::Incomplete)
|
Err(MultipartError::Incomplete)
|
||||||
@ -96,7 +97,7 @@ impl PayloadBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read until specified ending
|
/// Read until specified ending.
|
||||||
pub(crate) fn read_until(&mut self, line: &[u8]) -> Result<Option<Bytes>, MultipartError> {
|
pub(crate) fn read_until(&mut self, line: &[u8]) -> Result<Option<Bytes>, MultipartError> {
|
||||||
let res = memchr::memmem::find(&self.buf, line)
|
let res = memchr::memmem::find(&self.buf, line)
|
||||||
.map(|idx| self.buf.split_to(idx + line.len()).freeze());
|
.map(|idx| self.buf.split_to(idx + line.len()).freeze());
|
||||||
@ -108,12 +109,12 @@ impl PayloadBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read bytes until new line delimiter
|
/// Read bytes until new line delimiter.
|
||||||
pub(crate) fn readline(&mut self) -> Result<Option<Bytes>, MultipartError> {
|
pub(crate) fn readline(&mut self) -> Result<Option<Bytes>, MultipartError> {
|
||||||
self.read_until(b"\n")
|
self.read_until(b"\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read bytes until new line delimiter or eof
|
/// Read bytes until new line delimiter or EOF.
|
||||||
pub(crate) fn readline_or_eof(&mut self) -> Result<Option<Bytes>, MultipartError> {
|
pub(crate) fn readline_or_eof(&mut self) -> Result<Option<Bytes>, MultipartError> {
|
||||||
match self.readline() {
|
match self.readline() {
|
||||||
Err(MultipartError::Incomplete) if self.eof => Ok(Some(self.buf.split().freeze())),
|
Err(MultipartError::Incomplete) if self.eof => Ok(Some(self.buf.split().freeze())),
|
||||||
@ -121,7 +122,7 @@ impl PayloadBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Put unprocessed data back to the buffer
|
/// Put unprocessed data back to the buffer.
|
||||||
pub(crate) fn unprocessed(&mut self, data: Bytes) {
|
pub(crate) fn unprocessed(&mut self, data: Bytes) {
|
||||||
let buf = BytesMut::from(data.as_ref());
|
let buf = BytesMut::from(data.as_ref());
|
||||||
let buf = std::mem::replace(&mut self.buf, buf);
|
let buf = std::mem::replace(&mut self.buf, buf);
|
||||||
|
@ -34,7 +34,7 @@ const MAX_HEADERS: usize = 32;
|
|||||||
/// used for nested multipart streams.
|
/// used for nested multipart streams.
|
||||||
pub struct Multipart {
|
pub struct Multipart {
|
||||||
safety: Safety,
|
safety: Safety,
|
||||||
inner: Option<InnerMultipart>,
|
inner: Option<Inner>,
|
||||||
error: Option<MultipartError>,
|
error: Option<MultipartError>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,12 +90,12 @@ impl Multipart {
|
|||||||
{
|
{
|
||||||
Multipart {
|
Multipart {
|
||||||
safety: Safety::new(),
|
safety: Safety::new(),
|
||||||
inner: Some(InnerMultipart {
|
inner: Some(Inner {
|
||||||
payload: PayloadRef::new(PayloadBuffer::new(stream)),
|
payload: PayloadRef::new(PayloadBuffer::new(stream)),
|
||||||
content_type: ct,
|
content_type: ct,
|
||||||
boundary,
|
boundary,
|
||||||
state: InnerState::FirstBoundary,
|
state: State::FirstBoundary,
|
||||||
item: InnerMultipartItem::None,
|
item: Item::None,
|
||||||
}),
|
}),
|
||||||
error: None,
|
error: None,
|
||||||
}
|
}
|
||||||
@ -155,10 +155,7 @@ impl Stream for Multipart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
enum InnerState {
|
enum State {
|
||||||
/// Stream EOF.
|
|
||||||
Eof,
|
|
||||||
|
|
||||||
/// Skip data until first boundary.
|
/// Skip data until first boundary.
|
||||||
FirstBoundary,
|
FirstBoundary,
|
||||||
|
|
||||||
@ -167,14 +164,17 @@ enum InnerState {
|
|||||||
|
|
||||||
/// Reading Headers.
|
/// Reading Headers.
|
||||||
Headers,
|
Headers,
|
||||||
|
|
||||||
|
/// Stream EOF.
|
||||||
|
Eof,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum InnerMultipartItem {
|
enum Item {
|
||||||
None,
|
None,
|
||||||
Field(Rc<RefCell<InnerField>>),
|
Field(Rc<RefCell<InnerField>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InnerMultipart {
|
struct Inner {
|
||||||
/// Request's payload stream & buffer.
|
/// Request's payload stream & buffer.
|
||||||
payload: PayloadRef,
|
payload: PayloadRef,
|
||||||
|
|
||||||
@ -186,11 +186,11 @@ struct InnerMultipart {
|
|||||||
/// Field boundary.
|
/// Field boundary.
|
||||||
boundary: String,
|
boundary: String,
|
||||||
|
|
||||||
state: InnerState,
|
state: State,
|
||||||
item: InnerMultipartItem,
|
item: Item,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InnerMultipart {
|
impl Inner {
|
||||||
fn read_field_headers(
|
fn read_field_headers(
|
||||||
payload: &mut PayloadBuffer,
|
payload: &mut PayloadBuffer,
|
||||||
) -> Result<Option<HeaderMap>, MultipartError> {
|
) -> Result<Option<HeaderMap>, MultipartError> {
|
||||||
@ -265,6 +265,7 @@ impl InnerMultipart {
|
|||||||
boundary: &str,
|
boundary: &str,
|
||||||
) -> Result<Option<bool>, MultipartError> {
|
) -> Result<Option<bool>, MultipartError> {
|
||||||
let mut eof = false;
|
let mut eof = false;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match payload.readline()? {
|
match payload.readline()? {
|
||||||
Some(chunk) => {
|
Some(chunk) => {
|
||||||
@ -306,7 +307,7 @@ impl InnerMultipart {
|
|||||||
safety: &Safety,
|
safety: &Safety,
|
||||||
cx: &Context<'_>,
|
cx: &Context<'_>,
|
||||||
) -> Poll<Option<Result<Field, MultipartError>>> {
|
) -> Poll<Option<Result<Field, MultipartError>>> {
|
||||||
if self.state == InnerState::Eof {
|
if self.state == State::Eof {
|
||||||
Poll::Ready(None)
|
Poll::Ready(None)
|
||||||
} else {
|
} else {
|
||||||
// release field
|
// release field
|
||||||
@ -315,20 +316,18 @@ impl InnerMultipart {
|
|||||||
// before switching to next
|
// before switching to next
|
||||||
if safety.current() {
|
if safety.current() {
|
||||||
let stop = match self.item {
|
let stop = match self.item {
|
||||||
InnerMultipartItem::Field(ref mut field) => {
|
Item::Field(ref mut field) => match field.borrow_mut().poll(safety) {
|
||||||
match field.borrow_mut().poll(safety) {
|
Poll::Pending => return Poll::Pending,
|
||||||
Poll::Pending => return Poll::Pending,
|
Poll::Ready(Some(Ok(_))) => continue,
|
||||||
Poll::Ready(Some(Ok(_))) => continue,
|
Poll::Ready(Some(Err(err))) => return Poll::Ready(Some(Err(err))),
|
||||||
Poll::Ready(Some(Err(err))) => return Poll::Ready(Some(Err(err))),
|
Poll::Ready(None) => true,
|
||||||
Poll::Ready(None) => true,
|
},
|
||||||
}
|
Item::None => false,
|
||||||
}
|
|
||||||
InnerMultipartItem::None => false,
|
|
||||||
};
|
};
|
||||||
if stop {
|
if stop {
|
||||||
self.item = InnerMultipartItem::None;
|
self.item = Item::None;
|
||||||
}
|
}
|
||||||
if let InnerMultipartItem::None = self.item {
|
if let Item::None = self.item {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -337,40 +336,40 @@ impl InnerMultipart {
|
|||||||
let field_headers = if let Some(mut payload) = self.payload.get_mut(safety) {
|
let field_headers = if let Some(mut payload) = self.payload.get_mut(safety) {
|
||||||
match self.state {
|
match self.state {
|
||||||
// read until first boundary
|
// read until first boundary
|
||||||
InnerState::FirstBoundary => {
|
State::FirstBoundary => {
|
||||||
match InnerMultipart::skip_until_boundary(&mut payload, &self.boundary)? {
|
match Inner::skip_until_boundary(&mut payload, &self.boundary)? {
|
||||||
Some(eof) => {
|
Some(eof) => {
|
||||||
if eof {
|
if eof {
|
||||||
self.state = InnerState::Eof;
|
self.state = State::Eof;
|
||||||
return Poll::Ready(None);
|
return Poll::Ready(None);
|
||||||
} else {
|
} else {
|
||||||
self.state = InnerState::Headers;
|
self.state = State::Headers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => return Poll::Pending,
|
None => return Poll::Pending,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// read boundary
|
// read boundary
|
||||||
InnerState::Boundary => {
|
State::Boundary => match Inner::read_boundary(&mut payload, &self.boundary)? {
|
||||||
match InnerMultipart::read_boundary(&mut payload, &self.boundary)? {
|
None => return Poll::Pending,
|
||||||
None => return Poll::Pending,
|
Some(eof) => {
|
||||||
Some(eof) => {
|
if eof {
|
||||||
if eof {
|
self.state = State::Eof;
|
||||||
self.state = InnerState::Eof;
|
return Poll::Ready(None);
|
||||||
return Poll::Ready(None);
|
} else {
|
||||||
} else {
|
self.state = State::Headers;
|
||||||
self.state = InnerState::Headers;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// read field headers for next field
|
// read field headers for next field
|
||||||
if self.state == InnerState::Headers {
|
if self.state == State::Headers {
|
||||||
if let Some(headers) = InnerMultipart::read_field_headers(&mut payload)? {
|
if let Some(headers) = Inner::read_field_headers(&mut payload)? {
|
||||||
self.state = InnerState::Boundary;
|
self.state = State::Boundary;
|
||||||
headers
|
headers
|
||||||
} else {
|
} else {
|
||||||
return Poll::Pending;
|
return Poll::Pending;
|
||||||
@ -418,7 +417,7 @@ impl InnerMultipart {
|
|||||||
.and_then(|ct| ct.to_str().ok())
|
.and_then(|ct| ct.to_str().ok())
|
||||||
.and_then(|ct| ct.parse().ok());
|
.and_then(|ct| ct.parse().ok());
|
||||||
|
|
||||||
self.state = InnerState::Boundary;
|
self.state = State::Boundary;
|
||||||
|
|
||||||
// nested multipart stream is not supported
|
// nested multipart stream is not supported
|
||||||
if let Some(mime) = &field_content_type {
|
if let Some(mime) = &field_content_type {
|
||||||
@ -430,7 +429,7 @@ impl InnerMultipart {
|
|||||||
let field_inner =
|
let field_inner =
|
||||||
InnerField::new_in_rc(self.payload.clone(), self.boundary.clone(), &field_headers)?;
|
InnerField::new_in_rc(self.payload.clone(), self.boundary.clone(), &field_headers)?;
|
||||||
|
|
||||||
self.item = InnerMultipartItem::Field(Rc::clone(&field_inner));
|
self.item = Item::Field(Rc::clone(&field_inner));
|
||||||
|
|
||||||
Poll::Ready(Some(Ok(Field::new(
|
Poll::Ready(Some(Ok(Field::new(
|
||||||
field_content_type,
|
field_content_type,
|
||||||
@ -444,10 +443,10 @@ impl InnerMultipart {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for InnerMultipart {
|
impl Drop for Inner {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// InnerMultipartItem::Field has to be dropped first because of Safety.
|
// InnerMultipartItem::Field has to be dropped first because of Safety.
|
||||||
self.item = InnerMultipartItem::None;
|
self.item = Item::None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -772,7 +771,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_readmax() {
|
async fn read_max() {
|
||||||
let (mut sender, payload) = h1::Payload::create(false);
|
let (mut sender, payload) = h1::Payload::create(false);
|
||||||
let mut payload = PayloadBuffer::new(payload);
|
let mut payload = PayloadBuffer::new(payload);
|
||||||
|
|
||||||
@ -789,7 +788,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_readexactly() {
|
async fn read_exactly() {
|
||||||
let (mut sender, payload) = h1::Payload::create(false);
|
let (mut sender, payload) = h1::Payload::create(false);
|
||||||
let mut payload = PayloadBuffer::new(payload);
|
let mut payload = PayloadBuffer::new(payload);
|
||||||
|
|
||||||
@ -807,7 +806,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_readuntil() {
|
async fn read_until() {
|
||||||
let (mut sender, payload) = h1::Payload::create(false);
|
let (mut sender, payload) = h1::Payload::create(false);
|
||||||
let mut payload = PayloadBuffer::new(payload);
|
let mut payload = PayloadBuffer::new(payload);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user