2
2
//!
3
3
//! Filters that extract a multipart body for a route.
4
4
5
+ use std:: error:: Error as StdError ;
6
+ use std:: fmt:: { Display , Formatter } ;
5
7
use std:: future:: Future ;
6
8
use std:: pin:: Pin ;
7
9
use std:: task:: { Context , Poll } ;
@@ -12,8 +14,7 @@ use futures_util::{future, Stream};
12
14
use headers:: ContentType ;
13
15
use hyper:: Body ;
14
16
use mime:: Mime ;
15
- use multiparty:: headers:: Headers ;
16
- use multiparty:: server:: owned_futures03:: { FormData as FormDataInner , Part as PartInner } ;
17
+ use multer:: { Field as PartInner , Multipart as FormDataInner } ;
17
18
18
19
use crate :: filter:: { Filter , FilterBase , Internal } ;
19
20
use crate :: reject:: { self , Rejection } ;
@@ -33,15 +34,14 @@ pub struct FormOptions {
33
34
///
34
35
/// Extracted with a `warp::multipart::form` filter.
35
36
pub struct FormData {
36
- inner : FormDataInner < BodyIoError > ,
37
+ inner : FormDataInner < ' static > ,
37
38
}
38
39
39
40
/// A single "part" of a multipart/form-data body.
40
41
///
41
42
/// Yielded from the `FormData` stream.
42
43
pub struct Part {
43
- headers : Headers ,
44
- part : PartInner < BodyIoError > ,
44
+ part : PartInner < ' static > ,
45
45
}
46
46
47
47
/// Create a `Filter` to extract a `multipart/form-data` body from a request.
@@ -111,17 +111,17 @@ impl Stream for FormData {
111
111
type Item = Result < Part , crate :: Error > ;
112
112
113
113
fn poll_next ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Option < Self :: Item > > {
114
- match Pin :: new ( & mut self . inner ) . poll_next ( cx) {
114
+ match self . inner . poll_next_field ( cx) {
115
115
Poll :: Pending => Poll :: Pending ,
116
- Poll :: Ready ( Some ( Ok ( part) ) ) => {
117
- let headers = match part. raw_headers ( ) . parse ( ) {
118
- Ok ( headers ) => headers ,
119
- Err ( err ) => return Poll :: Ready ( Some ( Err ( crate :: Error :: new ( err ) ) ) ) ,
120
- } ;
121
- Poll :: Ready ( Some ( Ok ( Part { part , headers } ) ) )
116
+ Poll :: Ready ( Ok ( Some ( part) ) ) => {
117
+ if part. name ( ) . is_some ( ) {
118
+ Poll :: Ready ( Some ( Ok ( Part { part } ) ) )
119
+ } else {
120
+ Poll :: Ready ( Some ( Err ( crate :: Error :: new ( MultipartFieldMissingName ) ) ) )
121
+ }
122
122
}
123
- Poll :: Ready ( None ) => Poll :: Ready ( None ) ,
124
- Poll :: Ready ( Some ( Err ( err) ) ) => Poll :: Ready ( Some ( Err ( crate :: Error :: new ( err) ) ) ) ,
123
+ Poll :: Ready ( Ok ( None ) ) => Poll :: Ready ( None ) ,
124
+ Poll :: Ready ( Err ( err) ) => Poll :: Ready ( Some ( Err ( crate :: Error :: new ( err) ) ) ) ,
125
125
}
126
126
}
127
127
}
@@ -131,17 +131,18 @@ impl Stream for FormData {
131
131
impl Part {
132
132
/// Get the name of this part.
133
133
pub fn name ( & self ) -> & str {
134
- & self . headers . name
134
+ self . part . name ( ) . expect ( "checked for name previously" )
135
135
}
136
136
137
137
/// Get the filename of this part, if present.
138
138
pub fn filename ( & self ) -> Option < & str > {
139
- self . headers . filename . as_deref ( )
139
+ self . part . file_name ( )
140
140
}
141
141
142
142
/// Get the content-type of this part, if present.
143
143
pub fn content_type ( & self ) -> Option < & str > {
144
- self . headers . content_type . as_deref ( )
144
+ let content_type = self . part . content_type ( ) ;
145
+ content_type. map ( |t| t. type_ ( ) . as_str ( ) )
145
146
}
146
147
147
148
/// Asynchronously get some of the data for this `Part`.
@@ -167,13 +168,13 @@ impl Part {
167
168
impl fmt:: Debug for Part {
168
169
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
169
170
let mut builder = f. debug_struct ( "Part" ) ;
170
- builder. field ( "name" , & self . headers . name ) ;
171
+ builder. field ( "name" , & self . part . name ( ) ) ;
171
172
172
- if let Some ( ref filename) = self . headers . filename {
173
+ if let Some ( ref filename) = self . part . file_name ( ) {
173
174
builder. field ( "filename" , filename) ;
174
175
}
175
176
176
- if let Some ( ref mime) = self . headers . content_type {
177
+ if let Some ( ref mime) = self . part . content_type ( ) {
177
178
builder. field ( "content_type" , mime) ;
178
179
}
179
180
@@ -207,3 +208,15 @@ impl Stream for BodyIoError {
207
208
}
208
209
}
209
210
}
211
+
212
+ /// An error used when a multipart field is missing a name.
213
+ #[ derive( Debug ) ]
214
+ struct MultipartFieldMissingName ;
215
+
216
+ impl Display for MultipartFieldMissingName {
217
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
218
+ write ! ( f, "Multipart field is missing a name" )
219
+ }
220
+ }
221
+
222
+ impl StdError for MultipartFieldMissingName { }
0 commit comments