Skip to content

Commit a054ae4

Browse files
committed
Debugging
1 parent 43803ce commit a054ae4

15 files changed

+758
-310
lines changed

src/body_data_reader.rs

Lines changed: 75 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
use crate::{url_encoded_data::UrlEncodedData, HttpFailResult, JsonEncodedData};
1+
use crate::{
2+
url_encoded_data::UrlEncodedData, FileContent, FormDataReader, HttpFailResult, JsonEncodedData,
3+
};
24

3-
use super::ValueAsString;
5+
use super::InputParamValue;
46

5-
pub const BODY_SRC: &str = "body";
7+
pub const BODY_JSON_SRC: &str = "body json";
8+
pub const BODY_URL_SRC: &str = "body url/encoded";
9+
pub const FORM_DATA_SRC: &str = "body url/encoded";
610

711
pub enum BodyDataReaderInner<'s> {
812
UrlEncoded(UrlEncodedData<'s>),
913
JsonEncoded(JsonEncodedData<'s>),
14+
FormData(FormDataReader<'s>),
1015
}
1116
pub struct BodyDataReader<'s> {
1217
inner: BodyDataReaderInner<'s>,
@@ -25,41 +30,94 @@ impl<'s> BodyDataReader<'s> {
2530
}
2631
}
2732

28-
pub fn get_required(&'s self, name: &'s str) -> Result<ValueAsString<'s>, HttpFailResult> {
33+
pub fn get_required(&'s self, name: &'s str) -> Result<InputParamValue<'s>, HttpFailResult> {
2934
match &self.inner {
30-
BodyDataReaderInner::UrlEncoded(result) => {
31-
let value = result.get_required(name)?;
32-
Ok(ValueAsString::UrlEncodedValueAsStringRef {
35+
BodyDataReaderInner::UrlEncoded(src) => {
36+
let value = src.get_required(name)?;
37+
Ok(InputParamValue::UrlEncodedValueAsStringRef {
3338
value,
34-
src: BODY_SRC,
39+
src: BODY_URL_SRC,
3540
})
3641
}
37-
BodyDataReaderInner::JsonEncoded(result) => {
38-
let value = result.get_required(name)?;
39-
Ok(ValueAsString::JsonEncodedData {
42+
BodyDataReaderInner::JsonEncoded(src) => {
43+
let value = src.get_required(name)?;
44+
Ok(InputParamValue::JsonEncodedData {
4045
value,
41-
src: BODY_SRC,
46+
src: BODY_JSON_SRC,
4247
})
4348
}
49+
BodyDataReaderInner::FormData(src) => {
50+
let item = src.get_required(name)?;
51+
match item {
52+
crate::FormDataItem::ValueAsString { value, name: _ } => {
53+
return Ok(InputParamValue::Raw {
54+
value,
55+
src: "form data",
56+
})
57+
}
58+
crate::FormDataItem::File {
59+
name: _,
60+
file_name,
61+
content_type,
62+
content,
63+
} => {
64+
return Ok(InputParamValue::File {
65+
file: FileContent {
66+
content_type: content_type.to_string(),
67+
file_name: file_name.to_string(),
68+
content: content.to_vec(),
69+
},
70+
src: "form data",
71+
});
72+
}
73+
}
74+
}
4475
}
4576
}
4677

47-
pub fn get_optional(&'s self, name: &'s str) -> Option<ValueAsString<'s>> {
78+
pub fn get_optional(&'s self, name: &'s str) -> Option<InputParamValue<'s>> {
4879
match &self.inner {
4980
BodyDataReaderInner::UrlEncoded(result) => {
5081
let value = result.get_optional(name)?;
51-
Some(ValueAsString::UrlEncodedValueAsStringRef {
82+
Some(InputParamValue::UrlEncodedValueAsStringRef {
5283
value,
53-
src: BODY_SRC,
84+
src: BODY_URL_SRC,
5485
})
5586
}
5687
BodyDataReaderInner::JsonEncoded(result) => {
5788
let value = result.get_optional(name)?;
58-
Some(ValueAsString::JsonEncodedData {
89+
Some(InputParamValue::JsonEncodedData {
5990
value,
60-
src: BODY_SRC,
91+
src: BODY_JSON_SRC,
6192
})
6293
}
94+
BodyDataReaderInner::FormData(src) => {
95+
let item = src.get_optional(name)?;
96+
97+
match item {
98+
crate::FormDataItem::ValueAsString { value, name: _ } => {
99+
return Some(InputParamValue::Raw {
100+
value,
101+
src: "form data",
102+
})
103+
}
104+
crate::FormDataItem::File {
105+
name: _,
106+
file_name,
107+
content_type,
108+
content,
109+
} => {
110+
return Some(InputParamValue::File {
111+
file: FileContent {
112+
content_type: content_type.to_string(),
113+
file_name: file_name.to_string(),
114+
content: content.to_vec(),
115+
},
116+
src: "form data",
117+
});
118+
}
119+
}
120+
}
63121
}
64122
}
65123
}

src/file_content_input_data.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pub struct FileContent {
2+
pub content_type: String,
3+
pub file_name: String,
4+
pub content: Vec<u8>,
5+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#[derive(Debug)]
2+
pub struct KeyValue<'s> {
3+
pub key: &'s str,
4+
pub value: Option<&'s str>,
5+
}
6+
7+
pub struct ContentDispositionParser<'s> {
8+
content: &'s [u8],
9+
pos: usize,
10+
}
11+
12+
impl<'s> ContentDispositionParser<'s> {
13+
pub fn new(content: &'s [u8]) -> Self {
14+
Self { content, pos: 0 }
15+
}
16+
pub fn find_pos<TCondition: Fn(u8) -> bool>(&self, condition: TCondition) -> Option<usize> {
17+
for i in self.pos..self.content.len() {
18+
if condition(self.content[i]) {
19+
return Some(i);
20+
}
21+
}
22+
23+
None
24+
}
25+
}
26+
27+
impl<'s> Iterator for ContentDispositionParser<'s> {
28+
type Item = KeyValue<'s>;
29+
30+
fn next(&mut self) -> Option<Self::Item> {
31+
self.pos = self.find_pos(|b| b > 32)?;
32+
33+
let pos = self.find_pos(|b| b == b';' || b == b'=')?;
34+
35+
let b = self.content[pos];
36+
37+
let key = std::str::from_utf8(&self.content[self.pos..pos]).unwrap();
38+
self.pos = pos + 1;
39+
40+
if b == b';' {
41+
let result = KeyValue { key, value: None };
42+
return Some(result);
43+
}
44+
45+
let start_of_value = self.find_pos(|b| b == b'"')?;
46+
47+
self.pos = start_of_value + 1;
48+
49+
let end_of_value = self.find_pos(|b| b == b'"')?;
50+
51+
let value = if self.content[start_of_value] == b'"' {
52+
let result = &self.content[start_of_value + 1..end_of_value];
53+
self.pos = end_of_value + 2;
54+
result
55+
} else {
56+
let result = &self.content[start_of_value..end_of_value + 1];
57+
self.pos = end_of_value + 1;
58+
result
59+
};
60+
61+
Some(KeyValue {
62+
key,
63+
value: Some(std::str::from_utf8(value).unwrap()),
64+
})
65+
}
66+
}
67+
68+
#[cfg(test)]
69+
mod tests {
70+
71+
use super::*;
72+
73+
#[test]
74+
pub fn test_content_disposition_as_field() {
75+
let src: Vec<u8> = vec![
76+
32, 102, 111, 114, 109, 45, 100, 97, 116, 97, 59, 32, 110, 97, 109, 101, 61, 34, 100,
77+
116, 70, 114, 111, 109, 34, 13, 10,
78+
];
79+
80+
let result = ContentDispositionParser::new(&src).collect::<Vec<_>>();
81+
82+
{
83+
let first_item = result.get(0).unwrap();
84+
assert_eq!(first_item.key, "form-data");
85+
assert_eq!(first_item.value, None);
86+
}
87+
88+
{
89+
let first_item = result.get(1).unwrap();
90+
assert_eq!(first_item.key, "name");
91+
assert_eq!(first_item.value, Some("dtFrom"));
92+
}
93+
}
94+
95+
#[test]
96+
pub fn test_content_disposition_as_file() {
97+
let src: Vec<u8> = vec![
98+
32, 102, 111, 114, 109, 45, 100, 97, 116, 97, 59, 32, 110, 97, 109, 101, 61, 34, 102,
99+
105, 108, 101, 34, 59, 32, 102, 105, 108, 101, 110, 97, 109, 101, 61, 34, 116, 101,
100+
115, 116, 45, 112, 97, 121, 108, 111, 97, 100, 46, 116, 120, 116, 34, 13, 10, 67, 111,
101+
110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 32, 116, 101, 120, 116, 47, 112,
102+
108, 97, 105, 110, 13, 10, 13, 10, 49, 50, 51, 13, 10,
103+
];
104+
105+
let result = ContentDispositionParser::new(&src).collect::<Vec<_>>();
106+
107+
{
108+
let first_item = result.get(0).unwrap();
109+
assert_eq!(first_item.key, "form-data");
110+
assert_eq!(first_item.value, None);
111+
}
112+
113+
{
114+
let first_item = result.get(1).unwrap();
115+
assert_eq!(first_item.key, "name");
116+
assert_eq!(first_item.value, Some("file"));
117+
}
118+
119+
{
120+
let first_item = result.get(2).unwrap();
121+
assert_eq!(first_item.key, "filename");
122+
assert_eq!(first_item.value, Some("test-payload.txt"));
123+
}
124+
}
125+
}

src/form_data_reader/content_iterator.rs

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,39 @@
11
pub struct ContentIterator<'s> {
2-
boundary: &'s [u8],
2+
boundary_data: [u8; 255],
3+
boundary_len: usize,
34
payload: &'s [u8],
45
pos: usize,
56
}
67

78
impl<'s> ContentIterator<'s> {
8-
pub fn new(boundary: &'s [u8], payload: &'s [u8]) -> Self {
9-
Self {
10-
boundary,
9+
pub fn new(boundary: &[u8], payload: &'s [u8]) -> Self {
10+
let mut result = Self {
11+
boundary_data: [b'-'; 255],
12+
boundary_len: boundary.len() + 2,
1113
payload,
1214
pos: 0,
13-
}
15+
};
16+
17+
result.boundary_data[2..2 + boundary.len()].copy_from_slice(boundary);
18+
19+
result
20+
}
21+
22+
pub fn get_boundary(&'s self) -> &'s [u8] {
23+
&self.boundary_data[..self.boundary_len]
1424
}
1525
}
1626

1727
impl<'s> Iterator for ContentIterator<'s> {
1828
type Item = &'s [u8];
1929

2030
fn next(&mut self) -> Option<Self::Item> {
21-
self.pos += self.boundary.len();
31+
self.pos += self.boundary_len;
2232
self.pos = find_non_space(self.payload, self.pos)?;
2333

2434
let next_pos = rust_extensions::slice_of_u8_utils::find_sequence_pos(
2535
self.payload,
26-
self.boundary,
36+
self.get_boundary(),
2737
self.pos,
2838
)?;
2939

@@ -52,28 +62,37 @@ mod tests {
5262

5363
#[test]
5464
fn test_splitting() {
55-
let boundary = "------WebKitFormBoundaryvrDBuVcszaZRkg3v";
65+
let boundary = "----WebKitFormBoundaryu7oxE5T3UC2xY2Q9";
5666
let payload: Vec<u8> = vec![
5767
45, 45, 45, 45, 45, 45, 87, 101, 98, 75, 105, 116, 70, 111, 114, 109, 66, 111, 117,
58-
110, 100, 97, 114, 121, 118, 114, 68, 66, 117, 86, 99, 115, 122, 97, 90, 82, 107, 103,
59-
51, 118, 13, 10, // Boundary End
60-
// Payload ----------------------
68+
110, 100, 97, 114, 121, 117, 55, 111, 120, 69, 53, 84, 51, 85, 67, 50, 120, 89, 50, 81,
69+
57, 13, 10, //End of boundary
70+
//Message-0
6171
67, 111, 110, 116, 101, 110, 116, 45, 68, 105, 115, 112, 111, 115, 105, 116, 105, 111,
6272
110, 58, 32, 102, 111, 114, 109, 45, 100, 97, 116, 97, 59, 32, 110, 97, 109, 101, 61,
6373
34, 100, 116, 70, 114, 111, 109, 34, 13, 10, 13, 10, 50, 13, 10,
64-
// Next Boundary
74+
//Start of boundary
6575
45, 45, 45, 45, 45, 45, 87, 101, 98, 75, 105, 116, 70, 111, 114, 109, 66, 111, 117, 110,
66-
100, 97, 114, 121, 118, 114, 68, 66, 117, 86, 99, 115, 122, 97, 90, 82, 107, 103, 51,
67-
118, 13, 10, // Boundary End
68-
// Next Message
76+
100, 97, 114, 121, 117, 55, 111, 120, 69, 53, 84, 51, 85, 67, 50, 120, 89, 50, 81, 57,
77+
13, 10, //End of boundary
78+
//Message-1
6979
67, 111, 110, 116, 101, 110, 116, 45, 68, 105, 115, 112, 111, 115, 105, 116, 105, 111,
7080
110, 58, 32, 102, 111, 114, 109, 45, 100, 97, 116, 97, 59, 32, 110, 97, 109, 101, 61,
71-
34, 100, 116, 70, 114, 111, 109, 79, 112, 116, 34, 13, 10, 13, 10, 51, 13,
72-
10, //Message End
73-
// Next Boundary
81+
34, 100, 116, 70, 114, 111, 109, 79, 112, 116, 34, 13, 10, 13, 10, 51, 13, 10,
82+
//Start of boundary
7483
45, 45, 45, 45, 45, 45, 87, 101, 98, 75, 105, 116, 70, 111, 114, 109, 66, 111, 117, 110,
75-
100, 97, 114, 121, 118, 114, 68, 66, 117, 86, 99, 115, 122, 97, 90, 82, 107, 103, 51,
76-
118, 45, 45, 13, 10,
84+
100, 97, 114, 121, 117, 55, 111, 120, 69, 53, 84, 51, 85, 67, 50, 120, 89, 50, 81, 57,
85+
13, 10, //Message-2
86+
67, 111, 110, 116, 101, 110, 116, 45, 68, 105, 115, 112, 111, 115, 105, 116, 105, 111,
87+
110, 58, 32, 102, 111, 114, 109, 45, 100, 97, 116, 97, 59, 32, 110, 97, 109, 101, 61,
88+
34, 102, 105, 108, 101, 34, 59, 32, 102, 105, 108, 101, 110, 97, 109, 101, 61, 34, 116,
89+
101, 115, 116, 45, 112, 97, 121, 108, 111, 97, 100, 46, 116, 120, 116, 34, 13, 10, 67,
90+
111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 32, 116, 101, 120, 116, 47,
91+
112, 108, 97, 105, 110, 13, 10, 13, 10, 49, 50, 51, 13, 10,
92+
//Start of boundary
93+
45, 45, 45, 45, 45, 45, 87, 101, 98, 75, 105, 116, 70, 111, 114, 109, 66, 111, 117, 110,
94+
100, 97, 114, 121, 117, 55, 111, 120, 69, 53, 84, 51, 85, 67, 50, 120, 89, 50, 81, 57,
95+
45, 45, 13, 10,
7796
];
7897

7998
let result: Vec<&[u8]> =
@@ -91,7 +110,17 @@ mod tests {
91110
34, 100, 116, 70, 114, 111, 109, 79, 112, 116, 34, 13, 10, 13, 10, 51, 13, 10,
92111
];
93112

113+
let expected_payload_2: Vec<u8> = vec![
114+
67, 111, 110, 116, 101, 110, 116, 45, 68, 105, 115, 112, 111, 115, 105, 116, 105, 111,
115+
110, 58, 32, 102, 111, 114, 109, 45, 100, 97, 116, 97, 59, 32, 110, 97, 109, 101, 61,
116+
34, 102, 105, 108, 101, 34, 59, 32, 102, 105, 108, 101, 110, 97, 109, 101, 61, 34, 116,
117+
101, 115, 116, 45, 112, 97, 121, 108, 111, 97, 100, 46, 116, 120, 116, 34, 13, 10, 67,
118+
111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 32, 116, 101, 120, 116, 47,
119+
112, 108, 97, 105, 110, 13, 10, 13, 10, 49, 50, 51, 13, 10,
120+
];
121+
94122
assert_eq!(result.get(0).unwrap(), &expected_payload_0);
95123
assert_eq!(result.get(1).unwrap(), &expected_payload_1);
124+
assert_eq!(result.get(2).unwrap(), &expected_payload_2);
96125
}
97126
}

0 commit comments

Comments
 (0)