1use Request;
105
106use std::borrow::Cow;
107use std::error;
108use std::fmt;
109use std::io::BufRead;
110use std::io::Error as IoError;
111use std::io::Read;
112use std::num;
113
114#[doc(hidden)]
116pub use url::form_urlencoded;
117
118#[derive(Debug)]
120pub enum PostError {
121 WrongContentType,
123
124 BodyAlreadyExtracted,
126
127 IoError(IoError),
129
130 NotUtf8(String),
132
133 Field {
135 field: Cow<'static, str>,
136 error: PostFieldError,
137 },
138}
139
140impl From<IoError> for PostError {
141 #[inline]
142 fn from(err: IoError) -> PostError {
143 PostError::IoError(err)
144 }
145}
146
147impl error::Error for PostError {
148 #[inline]
149 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
150 match *self {
151 PostError::IoError(ref e) => Some(e),
152 PostError::Field { ref error, .. } => Some(error),
153 _ => None,
154 }
155 }
156}
157
158impl fmt::Display for PostError {
159 #[inline]
160 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
161 let description = match *self {
162 PostError::BodyAlreadyExtracted => "the body of the request was already extracted",
163 PostError::WrongContentType => "the request didn't have a post content type",
164 PostError::IoError(_) => {
165 "could not read the body from the request, or could not execute the CGI program"
166 }
167 PostError::NotUtf8(_) => {
168 "the content-type encoding is not ASCII or UTF-8, or the body is not valid UTF-8"
169 }
170 PostError::Field { .. } => "failed to parse a requested field",
171 };
172
173 write!(fmt, "{}", description)
174 }
175}
176
177#[derive(Debug)]
179pub enum PostFieldError {
180 IoError(IoError),
182
183 MissingField,
185
186 WrongFieldType,
188
189 UnexpectedMultipleValues,
191
192 WrongDataTypeInt(num::ParseIntError),
194
195 WrongDataTypeFloat(num::ParseFloatError),
197}
198
199impl From<IoError> for PostFieldError {
200 #[inline]
201 fn from(err: IoError) -> PostFieldError {
202 PostFieldError::IoError(err)
203 }
204}
205
206impl From<num::ParseIntError> for PostFieldError {
207 #[inline]
208 fn from(err: num::ParseIntError) -> PostFieldError {
209 PostFieldError::WrongDataTypeInt(err)
210 }
211}
212
213impl From<num::ParseFloatError> for PostFieldError {
214 #[inline]
215 fn from(err: num::ParseFloatError) -> PostFieldError {
216 PostFieldError::WrongDataTypeFloat(err)
217 }
218}
219
220impl error::Error for PostFieldError {
221 #[inline]
222 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
223 match *self {
224 PostFieldError::IoError(ref e) => Some(e),
225 PostFieldError::WrongDataTypeInt(ref e) => Some(e),
226 PostFieldError::WrongDataTypeFloat(ref e) => Some(e),
227 _ => None,
228 }
229 }
230}
231
232impl fmt::Display for PostFieldError {
233 #[inline]
234 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
235 let description = match *self {
236 PostFieldError::IoError(_) => {
237 "could not read the body from the request, or could not execute the CGI program"
238 }
239 PostFieldError::MissingField => "the field is missing from the request's client",
240 PostFieldError::WrongFieldType => "expected a file but got a field, or vice versa",
241 PostFieldError::UnexpectedMultipleValues => {
242 "got multiple values for the same field while only one was expected"
243 }
244 PostFieldError::WrongDataTypeInt(_) => "failed to parse an integer field",
245 PostFieldError::WrongDataTypeFloat(_) => "failed to parse a floating-point field",
246 };
247
248 write!(fmt, "{}", description)
249 }
250}
251
252pub trait DecodePostField<Config>: fmt::Debug {
258 fn from_field(config: Config, content: &str) -> Result<Self, PostFieldError>
264 where
265 Self: Sized;
266
267 fn from_file<R>(
283 config: Config,
284 file: R,
285 filename: Option<&str>,
286 mime: &str,
287 ) -> Result<Self, PostFieldError>
288 where
289 Self: Sized,
290 R: BufRead;
291
292 fn merge_multiple(self, _existing: Self) -> Result<Self, PostFieldError>
297 where
298 Self: Sized,
299 {
300 Err(PostFieldError::UnexpectedMultipleValues)
301 }
302
303 #[inline]
307 fn not_found(_: Config) -> Result<Self, PostFieldError>
308 where
309 Self: Sized,
310 {
311 Err(PostFieldError::MissingField)
312 }
313}
314
315macro_rules! impl_decode_post_field_decode {
316 ($t:ident) => {
317 impl DecodePostField<()> for $t {
318 fn from_field(_: (), content: &str) -> Result<Self, PostFieldError> {
319 Ok(match content.parse() {
320 Ok(v) => v,
321 Err(err) => return Err(err.into()),
322 })
323 }
324
325 fn from_file<R>(_: (), _: R, _: Option<&str>, _: &str) -> Result<Self, PostFieldError>
326 where
327 R: BufRead,
328 {
329 Err(PostFieldError::WrongFieldType)
330 }
331 }
332 };
333}
334
335impl_decode_post_field_decode!(u8);
336impl_decode_post_field_decode!(i8);
337impl_decode_post_field_decode!(u16);
338impl_decode_post_field_decode!(i16);
339impl_decode_post_field_decode!(u32);
340impl_decode_post_field_decode!(i32);
341impl_decode_post_field_decode!(u64);
342impl_decode_post_field_decode!(i64);
343impl_decode_post_field_decode!(usize);
344impl_decode_post_field_decode!(isize);
345impl_decode_post_field_decode!(f32);
346impl_decode_post_field_decode!(f64);
347
348impl DecodePostField<()> for String {
349 fn from_field(_: (), content: &str) -> Result<Self, PostFieldError> {
350 Ok(content.to_owned())
351 }
352
353 fn from_file<R>(_: (), _: R, _: Option<&str>, _: &str) -> Result<Self, PostFieldError>
354 where
355 R: BufRead,
356 {
357 Err(PostFieldError::WrongFieldType)
358 }
359}
360
361impl<T, C> DecodePostField<C> for Option<T>
362where
363 T: DecodePostField<C>,
364{
365 fn from_field(config: C, content: &str) -> Result<Self, PostFieldError> {
366 match DecodePostField::from_field(config, content) {
367 Ok(val) => Ok(Some(val)),
368 Err(_) => Ok(None),
369 }
370 }
371
372 fn from_file<R>(
373 config: C,
374 file: R,
375 filename: Option<&str>,
376 mime: &str,
377 ) -> Result<Self, PostFieldError>
378 where
379 R: BufRead,
380 {
381 match DecodePostField::from_file(config, file, filename, mime) {
382 Ok(val) => Ok(Some(val)),
383 Err(_) => Ok(None),
384 }
385 }
386
387 #[inline]
388 fn not_found(_: C) -> Result<Self, PostFieldError> {
389 Ok(None)
390 }
391}
392
393impl DecodePostField<()> for bool {
394 #[inline]
395 fn from_field(_: (), _: &str) -> Result<Self, PostFieldError> {
396 Ok(true)
397 }
398
399 #[inline]
400 fn from_file<R>(_: (), _: R, _: Option<&str>, _: &str) -> Result<Self, PostFieldError>
401 where
402 R: BufRead,
403 {
404 Ok(true)
405 }
406
407 #[inline]
408 fn merge_multiple(self, existing: bool) -> Result<bool, PostFieldError> {
409 Ok(self || existing)
410 }
411
412 #[inline]
413 fn not_found(_: ()) -> Result<Self, PostFieldError> {
414 Ok(false)
415 }
416}
417
418impl<T, C> DecodePostField<C> for Vec<T>
419where
420 T: DecodePostField<C>,
421{
422 fn from_field(config: C, content: &str) -> Result<Self, PostFieldError> {
423 Ok(vec![DecodePostField::from_field(config, content)?])
424 }
425
426 fn from_file<R>(
427 config: C,
428 file: R,
429 filename: Option<&str>,
430 mime: &str,
431 ) -> Result<Self, PostFieldError>
432 where
433 R: BufRead,
434 {
435 Ok(vec![DecodePostField::from_file(
436 config, file, filename, mime,
437 )?])
438 }
439
440 fn merge_multiple(mut self, mut existing: Vec<T>) -> Result<Vec<T>, PostFieldError> {
441 self.append(&mut existing);
442 Ok(self)
443 }
444
445 #[inline]
446 fn not_found(_: C) -> Result<Self, PostFieldError> {
447 Ok(Vec::new())
448 }
449}
450
451#[derive(Clone)]
453pub struct BufferedFile {
454 pub data: Vec<u8>,
456 pub mime: String,
458 pub filename: Option<String>,
460}
461
462impl fmt::Debug for BufferedFile {
463 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
464 fmt.debug_struct("BufferedFile")
465 .field("data", &format!("<{} bytes>", self.data.len()))
466 .field("mime", &self.mime)
467 .field("filename", &self.filename)
468 .finish()
469 }
470}
471
472impl DecodePostField<()> for BufferedFile {
473 fn from_field(_: (), _: &str) -> Result<Self, PostFieldError> {
474 Err(PostFieldError::WrongFieldType)
475 }
476
477 fn from_file<R>(
478 _: (),
479 mut file: R,
480 filename: Option<&str>,
481 mime: &str,
482 ) -> Result<Self, PostFieldError>
483 where
484 R: BufRead,
485 {
486 let mut out = Vec::new();
487 file.read_to_end(&mut out)?;
488
489 Ok(BufferedFile {
490 data: out,
491 mime: mime.to_owned(),
492 filename: filename.map(|n| n.to_owned()),
493 })
494 }
495}
496
497#[macro_export]
500macro_rules! post_input {
501 ($request:expr, {$($field:ident: $ty:ty $({$config:expr})*),*$(,)*}) => ({
502 use std::io::Read;
503 use std::result::Result;
504 use $crate::Request;
505 use $crate::input::post::DecodePostField;
506 use $crate::input::post::PostFieldError;
507 use $crate::input::post::PostError;
508 use $crate::input::post::form_urlencoded;
509 use $crate::input::multipart;
510
511 #[derive(Debug)]
512 struct PostInput {
513 $(
514 $field: $ty,
515 )*
516 }
517
518 fn merge<C, T: DecodePostField<C>>(existing: &mut Option<T>, new: T)
519 -> Result<(), PostFieldError>
520 {
521 match existing {
522 a @ &mut Some(_) => {
523 let extracted = a.take().unwrap();
524 let merged = extracted.merge_multiple(new)?;
525 *a = Some(merged);
526 },
527 a @ &mut None => *a = Some(new),
528 };
529
530 Ok(())
531 }
532
533 fn go(request: &Request) -> Result<PostInput, PostError> {
534 $(
535 let mut $field: Option<$ty> = None;
536 )*
537
538 if request.header("Content-Type").map(|ct| ct.starts_with("application/x-www-form-urlencoded")).unwrap_or(false) {
541 let body = {
542 let mut out = Vec::new(); if let Some(mut b) = request.data() {
545 b.read_to_end(&mut out)?;
546 } else {
547 return Err(PostError::BodyAlreadyExtracted);
548 }
549 out
550 };
551
552 for (field, value) in form_urlencoded::parse(&body) {
553 $(
554 if field == stringify!($field) {
555 let config = ();
556 $(
557 let config = $config;
558 )*
559
560 let decoded = match DecodePostField::from_field(config, &value) {
561 Ok(d) => d,
562 Err(err) => return Err(PostError::Field {
563 field: stringify!($field).into(),
564 error: err,
565 }),
566 };
567
568 match merge(&mut $field, decoded) {
569 Ok(d) => d,
570 Err(err) => return Err(PostError::Field {
571 field: stringify!($field).into(),
572 error: err,
573 }),
574 };
575 continue;
576 }
577 )*
578 }
579
580 } else {
581 let mut multipart = match multipart::get_multipart_input(request) {
582 Ok(m) => m,
583 Err(multipart::MultipartError::WrongContentType) => {
584 return Err(PostError::WrongContentType);
585 },
586 Err(multipart::MultipartError::BodyAlreadyExtracted) => {
587 return Err(PostError::BodyAlreadyExtracted);
588 },
589 };
590
591 while let Some(mut multipart_entry) = multipart.next() {
592 $(
593 if multipart_entry.headers.name.as_ref() == stringify!($field) {
594 let config = ();
595 $(
596 let config = $config;
597 )*
598
599 if multipart_entry.is_text() {
600 let mut text = String::new();
601 multipart_entry.data.read_to_string(&mut text)?;
602 let decoded = match DecodePostField::from_field(config, &text) {
603 Ok(d) => d,
604 Err(err) => return Err(PostError::Field {
605 field: stringify!($field).into(),
606 error: err,
607 }),
608 };
609 match merge(&mut $field, decoded) {
610 Ok(d) => d,
611 Err(err) => return Err(PostError::Field {
612 field: stringify!($field).into(),
613 error: err,
614 }),
615 };
616 } else {
617 let name = multipart_entry.headers.filename.as_ref().map(|n| n.to_owned());
618 let name = name.as_ref().map(|n| &n[..]);
619 let mime = multipart_entry.headers.content_type
620 .map(|m| m.to_string())
621 .unwrap_or_else(String::new);
622 let decoded = match DecodePostField::from_file(config, multipart_entry.data, name, &mime) {
623 Ok(d) => d,
624 Err(err) => return Err(PostError::Field {
625 field: stringify!($field).into(),
626 error: err,
627 }),
628 };
629 match merge(&mut $field, decoded) {
630 Ok(d) => d,
631 Err(err) => return Err(PostError::Field {
632 field: stringify!($field).into(),
633 error: err,
634 }),
635 };
636 }
637 continue;
638 }
639 )*
640 }
641 }
642
643 Ok(PostInput {
644 $(
645 $field: match $field {
646 Some(v) => v,
647 None => {
648 let config = ();
649 $(
650 let config = $config;
651 )*
652
653 match DecodePostField::not_found(config) {
654 Ok(d) => d,
655 Err(err) => return Err(PostError::Field {
656 field: stringify!($field).into(),
657 error: err,
658 }),
659 }
660 }
661 },
662 )*
663 })
664 }
665
666 go($request)
667 });
668}
669
670pub fn raw_urlencoded_post_input(request: &Request) -> Result<Vec<(String, String)>, PostError> {
677 if request
678 .header("Content-Type")
679 .map(|ct| !ct.starts_with("application/x-www-form-urlencoded"))
680 .unwrap_or(true)
681 {
682 return Err(PostError::WrongContentType);
683 }
684
685 let body = {
686 let mut out = Vec::new(); if let Some(mut b) = request.data() {
689 b.read_to_end(&mut out)?;
690 } else {
691 return Err(PostError::BodyAlreadyExtracted);
692 }
693 out
694 };
695
696 Ok(form_urlencoded::parse(&body).into_owned().collect()) }
698
699#[cfg(test)]
700mod tests {
701 use input::post::PostError;
702 use input::post::PostFieldError;
703 use Request;
704
705 #[test]
706 fn basic_int() {
707 let request = Request::fake_http(
708 "GET",
709 "/",
710 vec![
711 ("Host".to_owned(), "localhost".to_owned()),
712 (
713 "Content-Type".to_owned(),
714 "application/x-www-form-urlencoded".to_owned(),
715 ),
716 ],
717 b"field=12".to_vec(),
718 );
719
720 let input = post_input!(&request, { field: u32 }).unwrap();
721
722 assert_eq!(input.field, 12);
723 }
724
725 #[test]
726 fn basic_float() {
727 let request = Request::fake_http(
728 "GET",
729 "/",
730 vec![
731 ("Host".to_owned(), "localhost".to_owned()),
732 (
733 "Content-Type".to_owned(),
734 "application/x-www-form-urlencoded".to_owned(),
735 ),
736 ],
737 b"field=12.8".to_vec(),
738 );
739
740 let input = post_input!(&request, { field: f32 }).unwrap();
741
742 assert_eq!(input.field, 12.8);
743 }
744
745 #[test]
746 fn basic_string() {
747 let request = Request::fake_http(
748 "GET",
749 "/",
750 vec![
751 ("Host".to_owned(), "localhost".to_owned()),
752 (
753 "Content-Type".to_owned(),
754 "application/x-www-form-urlencoded".to_owned(),
755 ),
756 ],
757 b"field=value".to_vec(),
758 );
759
760 let input = post_input!(&request, { field: String }).unwrap();
761
762 assert_eq!(input.field, "value");
763 }
764
765 #[test]
766 fn basic_option_string() {
767 let request = Request::fake_http(
768 "GET",
769 "/",
770 vec![
771 ("Host".to_owned(), "localhost".to_owned()),
772 (
773 "Content-Type".to_owned(),
774 "application/x-www-form-urlencoded".to_owned(),
775 ),
776 ],
777 b"field=value".to_vec(),
778 );
779
780 let input = post_input!(&request, {
781 field: Option<String>
782 })
783 .unwrap();
784
785 assert_eq!(input.field.unwrap(), "value");
786 }
787
788 #[test]
789 fn basic_bool() {
790 let request = Request::fake_http(
791 "GET",
792 "/",
793 vec![
794 ("Host".to_owned(), "localhost".to_owned()),
795 (
796 "Content-Type".to_owned(),
797 "application/x-www-form-urlencoded".to_owned(),
798 ),
799 ],
800 b"field=value".to_vec(),
801 );
802
803 let input = post_input!(&request, { field: bool }).unwrap();
804
805 assert_eq!(input.field, true);
806 }
807
808 #[test]
809 fn weird_stuff() {
810 let request = Request::fake_http(
811 "GET",
812 "/",
813 vec![
814 ("Host".to_owned(), "localhost".to_owned()),
815 (
816 "Content-Type".to_owned(),
817 "application/x-www-form-urlencoded".to_owned(),
818 ),
819 ],
820 b"&=&aa&b=&c=c=c&field=value&".to_vec(),
821 );
822
823 let input = post_input!(&request, { field: String }).unwrap();
824
825 assert_eq!(input.field, "value");
826 }
827
828 #[test]
829 fn wrong_content_type() {
830 let request = Request::fake_http(
831 "GET",
832 "/",
833 vec![
834 ("Host".to_owned(), "localhost".to_owned()),
835 ("Content-Type".to_owned(), "wrong".to_owned()),
836 ],
837 b"field=value".to_vec(),
838 );
839
840 let input = post_input!(&request, { field: String });
841
842 match input {
843 Err(PostError::WrongContentType) => (),
844 _ => panic!(),
845 }
846 }
847
848 #[test]
849 fn too_many_fields() {
850 let request = Request::fake_http(
851 "GET",
852 "/",
853 vec![
854 ("Host".to_owned(), "localhost".to_owned()),
855 (
856 "Content-Type".to_owned(),
857 "application/x-www-form-urlencoded".to_owned(),
858 ),
859 ],
860 b"field=12&field2=58".to_vec(),
861 );
862
863 let input = post_input!(&request, { field: u32 }).unwrap();
864
865 assert_eq!(input.field, 12);
866 }
867
868 #[test]
869 fn multiple_values() {
870 let request = Request::fake_http(
871 "GET",
872 "/",
873 vec![
874 ("Host".to_owned(), "localhost".to_owned()),
875 (
876 "Content-Type".to_owned(),
877 "application/x-www-form-urlencoded".to_owned(),
878 ),
879 ],
880 b"field=12&field=58".to_vec(),
881 );
882
883 let input = post_input!(&request, { field: u32 });
884
885 match input {
886 Err(PostError::Field {
887 ref field,
888 error: PostFieldError::UnexpectedMultipleValues,
889 }) if field == "field" => (),
890 _ => panic!(),
891 }
892 }
893
894 #[test]
895 fn multiple_values_bool() {
896 let request = Request::fake_http(
897 "GET",
898 "/",
899 vec![
900 ("Host".to_owned(), "localhost".to_owned()),
901 (
902 "Content-Type".to_owned(),
903 "application/x-www-form-urlencoded".to_owned(),
904 ),
905 ],
906 b"field=12&field=58".to_vec(),
907 );
908
909 let input = post_input!(&request, { field: bool }).unwrap();
910
911 assert_eq!(input.field, true);
912 }
913
914 #[test]
915 fn multiple_values_vec() {
916 let request = Request::fake_http(
917 "GET",
918 "/",
919 vec![
920 ("Host".to_owned(), "localhost".to_owned()),
921 (
922 "Content-Type".to_owned(),
923 "application/x-www-form-urlencoded".to_owned(),
924 ),
925 ],
926 b"field=12&field=58".to_vec(),
927 );
928
929 let input = post_input!(&request, {
930 field: Vec<u32>
931 })
932 .unwrap();
933
934 assert_eq!(input.field, &[12, 58]);
935 }
936
937 #[test]
938 fn multiple_values_vec_parse_failure() {
939 let request = Request::fake_http(
940 "GET",
941 "/",
942 vec![
943 ("Host".to_owned(), "localhost".to_owned()),
944 (
945 "Content-Type".to_owned(),
946 "application/x-www-form-urlencoded".to_owned(),
947 ),
948 ],
949 b"field=12&field=800".to_vec(),
950 );
951
952 let input = post_input!(&request, {
953 field: Vec<u8>
954 });
955
956 match input {
957 Err(PostError::Field {
958 ref field,
959 error: PostFieldError::WrongDataTypeInt(_),
960 }) if field == "field" => (),
961 _ => panic!(),
962 }
963 }
964
965 #[test]
966 fn multiple_values_vec_option_parse_failure() {
967 let request = Request::fake_http(
968 "GET",
969 "/",
970 vec![
971 ("Host".to_owned(), "localhost".to_owned()),
972 (
973 "Content-Type".to_owned(),
974 "application/x-www-form-urlencoded".to_owned(),
975 ),
976 ],
977 b"field=12&field=800".to_vec(),
978 );
979
980 let input = post_input!(&request, {
981 field: Vec<Option<u8>>
982 })
983 .unwrap();
984
985 assert_eq!(input.field, &[Some(12), None]);
986 }
987
988 #[test]
989 fn missing_field() {
990 let request = Request::fake_http(
991 "GET",
992 "/",
993 vec![
994 ("Host".to_owned(), "localhost".to_owned()),
995 (
996 "Content-Type".to_owned(),
997 "application/x-www-form-urlencoded".to_owned(),
998 ),
999 ],
1000 b"wrong_field=value".to_vec(),
1001 );
1002
1003 let input = post_input!(&request, { field: String });
1004
1005 match input {
1006 Err(PostError::Field {
1007 ref field,
1008 error: PostFieldError::MissingField,
1009 }) if field == "field" => (),
1010 _ => panic!(),
1011 }
1012 }
1013
1014 #[test]
1015 fn missing_field_option() {
1016 let request = Request::fake_http(
1017 "GET",
1018 "/",
1019 vec![
1020 ("Host".to_owned(), "localhost".to_owned()),
1021 (
1022 "Content-Type".to_owned(),
1023 "application/x-www-form-urlencoded".to_owned(),
1024 ),
1025 ],
1026 b"wrong=value".to_vec(),
1027 );
1028
1029 let input = post_input!(&request, {
1030 field: Option<String>
1031 })
1032 .unwrap();
1033
1034 assert_eq!(input.field, None);
1035 }
1036
1037 #[test]
1038 fn missing_field_bool() {
1039 let request = Request::fake_http(
1040 "GET",
1041 "/",
1042 vec![
1043 ("Host".to_owned(), "localhost".to_owned()),
1044 (
1045 "Content-Type".to_owned(),
1046 "application/x-www-form-urlencoded".to_owned(),
1047 ),
1048 ],
1049 b"wrong=value".to_vec(),
1050 );
1051
1052 let input = post_input!(&request, { field: bool }).unwrap();
1053
1054 assert_eq!(input.field, false);
1055 }
1056
1057 #[test]
1058 fn missing_field_vec() {
1059 let request = Request::fake_http(
1060 "GET",
1061 "/",
1062 vec![
1063 ("Host".to_owned(), "localhost".to_owned()),
1064 (
1065 "Content-Type".to_owned(),
1066 "application/x-www-form-urlencoded".to_owned(),
1067 ),
1068 ],
1069 b"wrong=value".to_vec(),
1070 );
1071
1072 let input = post_input!(&request, {
1073 field: Vec<String>
1074 })
1075 .unwrap();
1076
1077 assert!(input.field.is_empty());
1078 }
1079
1080 #[test]
1081 fn num_parse_error() {
1082 let request = Request::fake_http(
1083 "GET",
1084 "/",
1085 vec![
1086 ("Host".to_owned(), "localhost".to_owned()),
1087 (
1088 "Content-Type".to_owned(),
1089 "application/x-www-form-urlencoded".to_owned(),
1090 ),
1091 ],
1092 b"field=12foo".to_vec(),
1093 );
1094
1095 let input = post_input!(&request, { field: u32 });
1096
1097 match input {
1098 Err(PostError::Field {
1099 ref field,
1100 error: PostFieldError::WrongDataTypeInt(_),
1101 }) if field == "field" => (),
1102 _ => panic!(),
1103 }
1104 }
1105
1106 #[test]
1107 fn num_parse_error_option() {
1108 let request = Request::fake_http(
1109 "GET",
1110 "/",
1111 vec![
1112 ("Host".to_owned(), "localhost".to_owned()),
1113 (
1114 "Content-Type".to_owned(),
1115 "application/x-www-form-urlencoded".to_owned(),
1116 ),
1117 ],
1118 b"field=12foo".to_vec(),
1119 );
1120
1121 let input = post_input!(&request, {
1122 field: Option<u32>
1123 })
1124 .unwrap();
1125
1126 assert_eq!(input.field, None);
1127 }
1128
1129 #[test]
1130 fn num_overflow() {
1131 let request = Request::fake_http(
1132 "GET",
1133 "/",
1134 vec![
1135 ("Host".to_owned(), "localhost".to_owned()),
1136 (
1137 "Content-Type".to_owned(),
1138 "application/x-www-form-urlencoded".to_owned(),
1139 ),
1140 ],
1141 b"field=800".to_vec(),
1142 );
1143
1144 let input = post_input!(&request, { field: u8 });
1145
1146 match input {
1147 Err(PostError::Field {
1148 ref field,
1149 error: PostFieldError::WrongDataTypeInt(_),
1150 }) if field == "field" => (),
1151 _ => panic!(),
1152 }
1153 }
1154
1155 #[test]
1156 fn body_extracted() {
1157 let request = Request::fake_http(
1158 "GET",
1159 "/",
1160 vec![
1161 ("Host".to_owned(), "localhost".to_owned()),
1162 (
1163 "Content-Type".to_owned(),
1164 "application/x-www-form-urlencoded".to_owned(),
1165 ),
1166 ],
1167 b"field=800".to_vec(),
1168 );
1169
1170 let _ = request.data();
1171
1172 let input = post_input!(&request, { field: u8 });
1173
1174 match input {
1175 Err(PostError::BodyAlreadyExtracted) => (),
1176 _ => panic!(),
1177 }
1178 }
1179
1180 #[test]
1181 #[ignore] fn not_utf8() {
1183 let request = Request::fake_http(
1184 "GET",
1185 "/",
1186 vec![
1187 ("Host".to_owned(), "localhost".to_owned()),
1188 (
1189 "Content-Type".to_owned(),
1190 "application/x-www-form-urlencoded".to_owned(),
1191 ),
1192 ],
1193 b"field=\xc3\x28".to_vec(),
1194 );
1195
1196 let input = post_input!(&request, { field: String });
1197
1198 match input {
1199 Err(PostError::NotUtf8(_)) => (),
1200 v => panic!("{:?}", v),
1201 }
1202 }
1203
1204 }