Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
W
WebServer
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Package Registry
Model registry
Operate
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
diufeYmike
WebServer
Commits
f85cfb4d
Commit
f85cfb4d
authored
2 years ago
by
codecraft
Browse files
Options
Downloads
Patches
Plain Diff
Complete `get_post_data()` implementation
set maximum post body size to 4196 bytes
parent
66349541
No related branches found
No related tags found
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
core/http/src/handlers/handlers.rs
+6
-3
6 additions, 3 deletions
core/http/src/handlers/handlers.rs
core/http/src/handling/request.rs
+94
-68
94 additions, 68 deletions
core/http/src/handling/request.rs
site/404.html
+1
-1
1 addition, 1 deletion
site/404.html
site/src/main.rs
+5
-6
5 additions, 6 deletions
site/src/main.rs
with
106 additions
and
78 deletions
core/http/src/handlers/handlers.rs
+
6
−
3
View file @
f85cfb4d
...
@@ -10,6 +10,8 @@ use crate::handling::{
...
@@ -10,6 +10,8 @@ use crate::handling::{
};
};
use
crate
::
setup
::
MountPoint
;
use
crate
::
setup
::
MountPoint
;
static
MAX_HTTPMESSAGE_SIZE
:
u16
=
4196
;
pub
async
fn
handle_connection
(
mut
stream
:
TcpStream
,
mountpoints
:
Vec
<
MountPoint
<
'_
>>
)
{
pub
async
fn
handle_connection
(
mut
stream
:
TcpStream
,
mountpoints
:
Vec
<
MountPoint
<
'_
>>
)
{
let
mut
buf_reader
=
BufReader
::
new
(
&
mut
stream
);
let
mut
buf_reader
=
BufReader
::
new
(
&
mut
stream
);
let
mut
http_request
:
Vec
<
String
>
=
Vec
::
with_capacity
(
30
);
let
mut
http_request
:
Vec
<
String
>
=
Vec
::
with_capacity
(
30
);
...
@@ -61,6 +63,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
...
@@ -61,6 +63,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
buffer
:
vec!
[],
buffer
:
vec!
[],
};
};
if
request
.can_have_body
()
{
if
request
.can_have_body
()
{
println!
(
"{:#?}"
,
request
.headers
);
let
length
=
if
let
Some
(
len
)
=
request
let
length
=
if
let
Some
(
len
)
=
request
.headers
.headers
.iter
()
.iter
()
...
@@ -87,9 +90,9 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
...
@@ -87,9 +90,9 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
0
0
};
};
if
length
!=
0
{
if
length
!=
0
{
let
mut
buffer
:
Vec
<
u8
>
=
vec!
[
];
let
mut
buffer
=
vec!
[
0u8
;
MAX_HTTPMESSAGE_SIZE
.into
()
];
buf_reader
.read
_buf
(
&
mut
buffer
)
.await
.unwrap
();
let
read
=
buf_reader
.read
(
&
mut
buffer
)
.await
.unwrap
();
if
buffer
.len
()
!=
length
{
if
read
!=
length
{
len_not_defined
(
stream
,
Status
::
LengthRequired
)
.await
;
len_not_defined
(
stream
,
Status
::
LengthRequired
)
.await
;
return
;
return
;
}
}
...
...
This diff is collapsed.
Click to expand it.
core/http/src/handling/request.rs
+
94
−
68
View file @
f85cfb4d
...
@@ -4,6 +4,8 @@ use std::{collections::HashMap, error::Error, fmt::Display};
...
@@ -4,6 +4,8 @@ use std::{collections::HashMap, error::Error, fmt::Display};
use
crate
::
utils
::
mime
::
mime_enum
::
Mime
;
use
crate
::
utils
::
mime
::
mime_enum
::
Mime
;
static
TWO_NEWLINES
:
u8
=
3
;
use
super
::{
use
super
::{
methods
::
Method
,
methods
::
Method
,
routes
::{
Data
,
Uri
},
routes
::{
Data
,
Uri
},
...
@@ -125,9 +127,13 @@ impl Request<'_> {
...
@@ -125,9 +127,13 @@ impl Request<'_> {
let
content_type
=
val
.trim
()
.strip_prefix
(
"Content-Type: "
)
.unwrap
();
let
content_type
=
val
.trim
()
.strip_prefix
(
"Content-Type: "
)
.unwrap
();
let
type_vec
=
content_type
.split
(
';'
)
.collect
::
<
Vec
<&
str
>>
();
let
type_vec
=
content_type
.split
(
';'
)
.collect
::
<
Vec
<&
str
>>
();
boundary
=
if
let
Some
(
bound
)
=
type_vec
.iter
()
.find
(|
part
|
part
.contains
(
"boundary="
))
boundary
=
if
let
Some
(
bound
)
=
type_vec
.iter
()
.find
(|
part
|
part
.contains
(
"
boundary="
))
{
{
bound
.strip_prefix
(
"boundary="
)
.unwrap
()
.trim_matches
(
'"'
)
bound
.strip_prefix
(
" boundary="
)
.unwrap
()
.trim_end
()
.trim_matches
(
'"'
)
}
else
{
}
else
{
""
""
};
};
...
@@ -192,62 +198,10 @@ impl Request<'_> {
...
@@ -192,62 +198,10 @@ impl Request<'_> {
Mime
::
MultipartFormData
=>
{
Mime
::
MultipartFormData
=>
{
let
mut
temp_bound
=
"--"
.to_string
();
let
mut
temp_bound
=
"--"
.to_string
();
temp_bound
.push_str
(
&
format!
(
"{boundary}"
));
temp_bound
.push_str
(
&
format!
(
"{boundary}"
));
let
end_boundary
=
format!
(
"{temp_bound}--"
)
.as_bytes
()
.to_owned
();
let
end_boundary
=
format!
(
"{temp_bound}--
\r
"
)
.as_bytes
()
.to_owned
();
temp_bound
.push
(
'\r'
);
let
boundary
=
temp_bound
.as_bytes
();
let
boundary
=
temp_bound
.as_bytes
();
let
parts
=
data
.split
(|
byte
|
byte
==
&
b'\n'
)
.collect
::
<
Vec
<&
[
u8
]
>>
();
Request
::
get_multipart
(
data
,
boundary
,
&
end_boundary
,
&
mut
keymap
);
let
mut
current_key
:
Option
<
String
>
=
None
;
let
mut
boundary_found
=
true
;
for
part
in
parts
{
if
part
==
[]
{
continue
;
}
if
part
==
end_boundary
{
break
;
}
if
!
boundary_found
&&
part
==
boundary
{
boundary_found
=
true
;
current_key
=
None
;
continue
;
}
if
part
.starts_with
(
b"Content-Disposition: form-data; name="
)
{
let
headers
=
part
.split
(|
byte
|
byte
==
&
b';'
)
.filter
(|
header
|
!
header
.is_empty
())
.collect
::
<
Vec
<
_
>>
();
if
headers
.len
()
<
2
{
continue
;
}
let
name
=
headers
[
1
]
.split
(|
byte
|
byte
==
&
b'='
)
.collect
::
<
Vec
<
_
>>
();
if
name
.len
()
!=
2
{
continue
;
}
let
mkey
=
String
::
from_utf8_lossy
(
name
[
1
])
.as_ref
()
.trim_end
()
.trim_matches
(
'"'
)
.to_owned
();
if
keymap
.contains_key
::
<
str
>
(
&
mkey
)
{
current_key
=
Some
(
mkey
.to_owned
());
}
boundary_found
=
false
;
continue
;
}
else
if
let
Some
(
key
)
=
&
current_key
{
if
let
Some
(
val
)
=
keymap
.get
::
<
str
>
(
&
key
)
{
if
let
Err
(
_
)
=
val
{
keymap
.insert
(
key
.to_string
(),
Ok
(
part
.to_vec
()));
continue
;
}
keymap
.get_mut
(
key
)
.unwrap
()
.as_mut
()
.unwrap
()
.extend_from_slice
(
part
);
}
}
}
}
}
_
=>
{
_
=>
{
return
Err
(
ParseFormError
{
return
Err
(
ParseFormError
{
...
@@ -257,6 +211,77 @@ impl Request<'_> {
...
@@ -257,6 +211,77 @@ impl Request<'_> {
};
};
Ok
(
keymap
)
Ok
(
keymap
)
}
}
fn
get_multipart
(
data
:
&
[
u8
],
boundary
:
&
[
u8
],
end_boundary
:
&
[
u8
],
map
:
&
mut
HashMap
<
String
,
Result
<
Vec
<
u8
>
,
ParseFormError
>>
,
)
{
let
parts
=
data
.split
(|
byte
|
byte
==
&
b'\n'
)
.collect
::
<
Vec
<&
[
u8
]
>>
();
let
mut
current_part
:
Vec
<&
[
u8
]
>
=
vec!
[];
let
mut
current_key
:
Option
<
String
>
=
None
;
let
mut
ignore_line
=
0
;
for
part
in
parts
{
if
part
==
&
[
b'\r'
]
{
if
let
Some
(
_
)
=
current_key
{
if
ignore_line
>=
TWO_NEWLINES
{
current_part
.push
(
&
[
b'\n'
]);
continue
;
}
ignore_line
+=
1
;
}
continue
;
}
if
part
==
end_boundary
{
if
let
Some
(
key
)
=
&
current_key
{
let
mut
part
=
current_part
.join
(
&
b'\n'
);
if
part
.ends_with
(
&
[
b'\r'
])
{
part
.pop
();
}
map
.insert
(
key
.to_string
(),
Ok
(
part
));
}
break
;
}
if
part
==
boundary
{
if
let
Some
(
key
)
=
&
current_key
{
let
mut
part
=
current_part
.join
(
&
b'\n'
);
if
part
.ends_with
(
&
[
b'\r'
])
{
part
.pop
();
}
map
.insert
(
key
.to_string
(),
Ok
(
part
));
}
current_part
=
vec!
[];
current_key
=
None
;
ignore_line
=
0
;
continue
;
}
if
part
.starts_with
(
b"Content-Disposition: form-data; name="
)
{
let
headers
=
part
.split
(|
byte
|
byte
==
&
b';'
)
.filter
(|
header
|
!
header
.is_empty
())
.collect
::
<
Vec
<
_
>>
();
if
headers
.len
()
<
2
{
continue
;
}
let
name
=
headers
[
1
]
.split
(|
byte
|
byte
==
&
b'='
)
.collect
::
<
Vec
<
_
>>
();
if
name
.len
()
!=
2
{
continue
;
}
let
mkey
=
String
::
from_utf8_lossy
(
name
[
1
])
.as_ref
()
.trim_end
()
.trim_matches
(
'"'
)
.to_owned
();
if
map
.contains_key
::
<
str
>
(
&
mkey
)
{
current_key
=
Some
(
mkey
.to_owned
());
}
continue
;
}
else
if
let
Some
(
_
)
=
&
current_key
{
current_part
.push
(
part
);
}
}
}
}
}
#[cfg(test)]
#[cfg(test)]
...
@@ -287,30 +312,31 @@ mod test {
...
@@ -287,30 +312,31 @@ mod test {
);
);
let
req
=
Request
{
let
req
=
Request
{
uri
:
""
,
uri
:
""
,
headers
:
vec!
[
"Content-Type: multipart/form-data;boundary=
\"
boundary
\"
"
.to_string
()],
headers
:
vec!
[
"Content-Type: multipart/form-data;
boundary=
\"
boundary
\"
"
.to_string
()],
method
:
crate
::
handling
::
methods
::
Method
::
Post
,
method
:
crate
::
handling
::
methods
::
Method
::
Post
,
};
};
let
data
=
Data
{
let
data
=
Data
{
buffer
:
b"--boundary
buffer
:
b"--boundary
\r
Content-Disposition: form-data; name=
\"
field1
\"
Content-Disposition: form-data; name=
\"
field1
\"
\r
\r
value1
value1
\r
--boundary
--boundary
\r
Content-Disposition: form-data; name=
\"
field2
\"
; filename=
\"
example.txt
\"
Content-Disposition: form-data; name=
\"
field2
\"
; filename=
\"
example.txt
\"
\r
\r
value2
\
n
va
\n
lue2
\
r
--boundary--
--boundary--
\r
"
"
.to_vec
(),
.to_vec
(),
is_complete
:
true
,
is_complete
:
true
,
};
};
let
map
=
req
.get_post_data
(
&
[
"field1"
,
"field2"
],
&
data
)
.unwrap
();
let
map
=
req
.get_post_data
(
&
[
"field1"
,
"field2"
],
&
data
)
.unwrap
();
assert_eq!
(
assert_eq!
(
&
b"value1"
.to_vec
(),
&
b"value1"
.to_vec
(),
map
.get
(
"field1"
)
.unwrap
()
.as_ref
()
.unwrap
()
map
.get
(
"field1"
)
.unwrap
()
.as_ref
()
.unwrap
()
);
);
assert_eq!
(
assert_eq!
(
&
b"value2
\n
"
.to_vec
(),
&
b"va
\n
lue2"
.to_vec
(),
map
.get
(
"field2"
)
.unwrap
()
.as_ref
()
.unwrap
()
map
.get
(
"field2"
)
.unwrap
()
.as_ref
()
.unwrap
()
);
);
}
}
...
...
This diff is collapsed.
Click to expand it.
site/404.html
+
1
−
1
View file @
f85cfb4d
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
<body>
<body>
<h1>
404
</h1>
<h1>
404
</h1>
<p>
Hi from Rust
</p>
<p>
Hi from Rust
</p>
<form
action=
"/post/post"
method=
"post"
>
<form
action=
"/post/post"
method=
"post"
enctype=
"multipart/form-data"
>
<label
for=
"message"
>
Enter your message:
</label>
<label
for=
"message"
>
Enter your message:
</label>
<input
type=
"text"
id=
"message"
name=
"message"
/>
<input
type=
"text"
id=
"message"
name=
"message"
/>
<button
type=
"submit"
>
Send
</button>
<button
type=
"submit"
>
Send
</button>
...
...
This diff is collapsed.
Click to expand it.
site/src/main.rs
+
5
−
6
View file @
f85cfb4d
...
@@ -62,12 +62,11 @@ fn post_hi_handler(request: Request, data: Data) -> Outcome<Response, Status, Da
...
@@ -62,12 +62,11 @@ fn post_hi_handler(request: Request, data: Data) -> Outcome<Response, Status, Da
if
data
.is_empty
()
{
if
data
.is_empty
()
{
return
Outcome
::
Forward
(
data
);
return
Outcome
::
Forward
(
data
);
}
}
// let data = if let Ok(val) = request.get_post_text_form_key("message", &data) {
let
dat
=
if
let
Ok
(
val
)
=
request
.get_post_data
(
&
[
"message"
],
&
data
)
{
// val
post_hi
(
String
::
from_utf8_lossy
(
val
.get
(
"message"
)
.unwrap
()
.as_ref
()
.unwrap
())
.to_string
())
// } else {
}
else
{
// return Outcome::Failure(Status::BadRequest);
return
Outcome
::
Failure
(
Status
::
BadRequest
);
// };
};
let
dat
=
post_hi
(
String
::
from_utf8
(
data
.buffer
)
.unwrap
());
Outcome
::
Success
(
Response
{
Outcome
::
Success
(
Response
{
headers
:
vec!
[
headers
:
vec!
[
format!
(
"Content-Length: {}"
,
dat
.len
()),
format!
(
"Content-Length: {}"
,
dat
.len
()),
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment