Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
D
dlib
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
钟尚武
dlib
Commits
1db057d6
Commit
1db057d6
authored
Nov 07, 2012
by
Davis King
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactored the code in the http server so that it will be more reusable
by other tools.
parent
05b1ba8b
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
183 additions
and
111 deletions
+183
-111
server_http_1.h
dlib/server/server_http_1.h
+181
-110
server_http_abstract.h
dlib/server/server_http_abstract.h
+2
-1
No files found.
dlib/server/server_http_1.h
View file @
1db057d6
...
...
@@ -25,34 +25,18 @@
namespace
dlib
{
template
<
typename
server_base
>
class
server_http_1
:
public
server_base
{
/*!
CONVENTION
this extension doesn't add any new state to this object.
!*/
// ----------------------------------------------------------------------------------------
public
:
server_http_1
()
class
http_parse_error
:
public
error
{
max_content_length
=
10
*
1024
*
1024
;
// 10MB
}
public
:
http_parse_error
(
const
std
::
string
&
str
,
int
http_error_code_
)
:
error
(
str
),
http_error_code
(
http_error_code_
)
{}
unsigned
long
get_max_content_length
(
)
const
{
return
max_content_length
;
}
const
int
http_error_code
;
};
void
set_max_content_length
(
unsigned
long
max_length
)
{
max_content_length
=
max_length
;
}
// ----------------------------------------------------------------------------------------
template
<
typename
Key
,
typename
Value
>
class
constmap
:
public
std
::
map
<
Key
,
Value
>
...
...
@@ -78,10 +62,20 @@ namespace dlib
typedef
constmap
<
std
::
string
,
std
::
string
>
key_value_map
;
struct
incoming_things
{
incoming_things
()
:
foreign_port
(
0
),
local_port
(
0
)
{}
incoming_things
(
const
std
::
string
&
foreign_ip_
,
const
std
::
string
&
local_ip_
,
unsigned
short
foreign_port_
,
unsigned
short
local_port_
)
:
foreign_ip
(
foreign_ip_
),
foreign_port
(
foreign_port_
),
local_ip
(
local_ip_
),
local_port
(
local_port_
)
{}
std
::
string
path
;
std
::
string
request_type
;
...
...
@@ -101,7 +95,7 @@ namespace dlib
struct
outgoing_things
{
outgoing_things
()
:
http_return
(
200
)
{
}
outgoing_things
()
:
http_return
(
200
),
http_return_status
(
"OK"
)
{
}
key_value_map
cookies
;
key_value_map
headers
;
...
...
@@ -109,19 +103,16 @@ namespace dlib
std
::
string
http_return_status
;
};
// ----------------------------------------------------------------------------------------
private
:
virtual
const
std
::
string
on_request
(
const
incoming_things
&
incoming
,
outgoing_things
&
outgoing
)
=
0
;
unsigned
char
to_hex
(
unsigned
char
x
)
const
namespace
http_impl
{
inline
unsigned
char
to_hex
(
unsigned
char
x
)
{
return
x
+
(
x
>
9
?
(
'A'
-
10
)
:
'0'
);
}
const
std
::
string
urlencode
(
const
std
::
string
&
s
)
const
inline
const
std
::
string
urlencode
(
const
std
::
string
&
s
)
{
std
::
ostringstream
os
;
...
...
@@ -146,9 +137,9 @@ namespace dlib
return
os
.
str
();
}
unsigned
char
from_hex
(
inline
unsigned
char
from_hex
(
unsigned
char
ch
)
const
)
{
if
(
ch
<=
'9'
&&
ch
>=
'0'
)
ch
-=
'0'
;
...
...
@@ -161,9 +152,9 @@ namespace dlib
return
ch
;
}
const
std
::
string
urldecode
(
inline
const
std
::
string
urldecode
(
const
std
::
string
&
str
)
const
)
{
using
namespace
std
;
string
result
;
...
...
@@ -190,7 +181,10 @@ namespace dlib
return
result
;
}
void
parse_url
(
std
::
string
word
,
key_value_map
&
queries
)
inline
void
parse_url
(
std
::
string
word
,
key_value_map
&
queries
)
/*!
Parses the query string of a URL. word should be the stuff that comes
after the ? in the query URL.
...
...
@@ -220,11 +214,11 @@ namespace dlib
}
}
void
read_with_limit
(
inline
void
read_with_limit
(
std
::
istream
&
in
,
std
::
string
&
buffer
,
int
delim
=
'\n'
)
const
)
{
using
namespace
std
;
const
size_t
max
=
16
*
1024
;
...
...
@@ -236,6 +230,10 @@ namespace dlib
buffer
+=
(
char
)
in
.
get
();
}
// if we quit the loop because the data is longer than expected or we hit EOF
if
(
in
.
peek
()
==
EOF
||
buffer
.
size
()
==
max
)
throw
http_parse_error
(
"HTTP field from client is too long"
,
414
);
// Make sure the last char is the delim.
if
(
in
.
get
()
!=
delim
)
{
...
...
@@ -252,31 +250,17 @@ namespace dlib
}
}
}
}
void
on_connect
(
inline
unsigned
long
parse_http_request
(
std
::
istream
&
in
,
std
::
ostream
&
out
,
const
std
::
string
&
foreign_ip
,
const
std
::
string
&
local_ip
,
unsigned
short
foreign_port
,
unsigned
short
local_port
,
uint64
incoming_things
&
incoming
,
unsigned
long
max_content_length
)
{
bool
my_fault
=
true
;
using
namespace
std
;
try
{
incoming_things
incoming
;
outgoing_things
outgoing
;
incoming
.
foreign_ip
=
foreign_ip
;
incoming
.
foreign_port
=
foreign_port
;
incoming
.
local_ip
=
local_ip
;
incoming
.
local_port
=
local_port
;
using
namespace
http_impl
;
read_with_limit
(
in
,
incoming
.
request_type
,
' '
);
// get the path
...
...
@@ -320,7 +304,16 @@ namespace dlib
istringstream
sin
(
line
.
substr
(
16
));
sin
>>
content_length
;
if
(
!
sin
)
content_length
=
0
;
{
throw
http_parse_error
(
"Invalid Content-Length of '"
+
line
.
substr
(
16
)
+
"'"
,
411
);
}
if
(
content_length
>
max_content_length
)
{
std
::
ostringstream
sout
;
sout
<<
"Content-Length of post back is too large. It must be less than "
<<
max_content_length
;
throw
http_parse_error
(
sout
.
str
(),
413
);
}
}
// look for any cookies
else
if
(
line
.
size
()
>
6
&&
strings_equal_ignore_case
(
line
,
"Cookie:"
,
7
))
...
...
@@ -375,18 +368,6 @@ namespace dlib
read_with_limit
(
in
,
line
);
}
// while (line.size() > 2 )
// If there is data being posted back to us then load it into the incoming.body
// string.
if
(
content_length
>
max_content_length
)
{
dlog
<<
LERROR
<<
"Request from: "
<<
foreign_ip
<<
" - body content length "
<<
content_length
<<
" exceeded max content length of "
<<
max_content_length
;
in
.
setstate
(
ios
::
badbit
);
}
else
if
(
content_length
>
0
)
{
incoming
.
body
.
resize
(
content_length
);
in
.
read
(
&
incoming
.
body
[
0
],
content_length
);
}
// If there is data being posted back to us as a query string then
// pick out the queries using parse_url.
...
...
@@ -394,6 +375,11 @@ namespace dlib
strings_equal_ignore_case
(
incoming
.
request_type
,
"PUT"
))
&&
strings_equal_ignore_case
(
left_substr
(
content_type
,
";"
),
"application/x-www-form-urlencoded"
))
{
if
(
content_length
>
0
)
{
incoming
.
body
.
resize
(
content_length
);
in
.
read
(
&
incoming
.
body
[
0
],
content_length
);
}
parse_url
(
incoming
.
body
,
incoming
.
queries
);
}
...
...
@@ -404,32 +390,43 @@ namespace dlib
}
my_fault
=
false
;
key_value_map
&
new_cookies
=
outgoing
.
cookies
;
key_value_map
&
response_headers
=
outgoing
.
headers
;
if
(
!
in
)
throw
http_parse_error
(
"Error parsing HTTP request"
,
500
);
// Set some defaults
outgoing
.
http_return
=
200
;
outgoing
.
http_return_status
=
"OK"
;
return
content_length
;
}
// if there wasn't a problem with the input stream at some point
// then lets trigger this request callback.
std
::
string
result
;
if
(
in
)
inline
void
read_body
(
std
::
istream
&
in
,
incoming_things
&
incoming
)
{
result
=
on_request
(
incoming
,
outgoing
);
}
else
// if the body hasn't already been loaded and there is data to load
if
(
incoming
.
body
.
size
()
==
0
&&
incoming
.
headers
.
count
(
"Content-Length"
)
!=
0
)
{
const
unsigned
long
content_length
=
string_cast
<
unsigned
long
>
(
incoming
.
headers
[
"Content-Length"
]);
incoming
.
body
.
resize
(
content_length
);
if
(
content_length
>
0
)
{
dlog
<<
LERROR
<<
"Request from: "
<<
foreign_ip
<<
" - Invalid request - Request Entity Too Large"
;
outgoing
.
http_return
=
413
;
outgoing
.
http_return_status
=
"Request Entity Too Large"
;
in
.
read
(
&
incoming
.
body
[
0
],
content_length
)
;
}
}
}
my_fault
=
true
;
inline
void
write_http_response
(
std
::
ostream
&
out
,
outgoing_things
outgoing
,
const
std
::
string
&
result
)
{
using
namespace
http_impl
;
key_value_map
&
new_cookies
=
outgoing
.
cookies
;
key_value_map
&
response_headers
=
outgoing
.
headers
;
// only send this header if the user hasn't told us to send another kind
bool
has_content_type
(
false
),
has_location
(
false
);
bool
has_content_type
=
false
,
has_location
=
false
;
for
(
typename
key_value_map
::
const_iterator
ci
=
response_headers
.
begin
();
ci
!=
response_headers
.
end
();
++
ci
)
{
if
(
!
has_content_type
&&
strings_equal_ignore_case
(
ci
->
first
,
"content-type"
)
)
...
...
@@ -452,12 +449,7 @@ namespace dlib
response_headers
[
"Content-Type"
]
=
"text/html"
;
}
{
ostringstream
os
;
os
<<
result
.
size
();
response_headers
[
"Content-Length"
]
=
os
.
str
();
}
response_headers
[
"Content-Length"
]
=
cast_to_string
(
result
.
size
());
out
<<
"HTTP/1.0 "
<<
outgoing
.
http_return
<<
" "
<<
outgoing
.
http_return_status
<<
"
\r\n
"
;
...
...
@@ -474,16 +466,98 @@ namespace dlib
}
out
<<
"
\r\n
"
<<
result
;
}
catch
(
std
::
bad_alloc
&
)
inline
void
write_http_response
(
std
::
ostream
&
out
,
const
http_parse_error
&
e
)
{
outgoing_things
outgoing
;
outgoing
.
http_return
=
e
.
http_error_code
;
outgoing
.
http_return_status
=
e
.
what
();
write_http_response
(
out
,
outgoing
,
std
::
string
(
"Error processing request: "
)
+
e
.
what
());
}
inline
void
write_http_response
(
std
::
ostream
&
out
,
const
std
::
exception
&
e
)
{
dlog
<<
LERROR
<<
"We ran out of memory in server_http::on_connect()"
;
// If this is an escaped exception from on_request then let it fly!
// Seriously though, this way it is obvious to the user that something bad happened
// since they probably won't have the dlib logger enabled.
if
(
!
my_fault
)
throw
;
outgoing_things
outgoing
;
outgoing
.
http_return
=
500
;
outgoing
.
http_return_status
=
e
.
what
();
write_http_response
(
out
,
outgoing
,
std
::
string
(
"Error processing request: "
)
+
e
.
what
());
}
// ----------------------------------------------------------------------------------------
template
<
typename
server_base
>
class
server_http_1
:
public
server_base
{
/*!
CONVENTION
this extension doesn't add any new state to this object.
!*/
public
:
server_http_1
()
{
max_content_length
=
10
*
1024
*
1024
;
// 10MB
}
unsigned
long
get_max_content_length
(
)
const
{
return
max_content_length
;
}
void
set_max_content_length
(
unsigned
long
max_length
)
{
max_content_length
=
max_length
;
}
private
:
virtual
const
std
::
string
on_request
(
const
incoming_things
&
incoming
,
outgoing_things
&
outgoing
)
=
0
;
void
on_connect
(
std
::
istream
&
in
,
std
::
ostream
&
out
,
const
std
::
string
&
foreign_ip
,
const
std
::
string
&
local_ip
,
unsigned
short
foreign_port
,
unsigned
short
local_port
,
uint64
)
{
try
{
incoming_things
incoming
(
foreign_ip
,
local_ip
,
foreign_port
,
local_port
);
outgoing_things
outgoing
;
parse_http_request
(
in
,
incoming
,
max_content_length
);
read_body
(
in
,
incoming
);
const
std
::
string
&
result
=
on_request
(
incoming
,
outgoing
);
write_http_response
(
out
,
outgoing
,
result
);
}
catch
(
http_parse_error
&
e
)
{
dlog
<<
LERROR
<<
"Error processing request from: "
<<
foreign_ip
<<
" - "
<<
e
.
what
();
write_http_response
(
out
,
e
);
}
catch
(
std
::
exception
&
e
)
{
dlog
<<
LERROR
<<
"Error processing request from: "
<<
foreign_ip
<<
" - "
<<
e
.
what
();
write_http_response
(
out
,
e
);
}
}
unsigned
long
max_content_length
;
...
...
@@ -498,6 +572,3 @@ namespace dlib
#endif // DLIB_SERVER_HTTp_1_
dlib/server/server_http_abstract.h
View file @
1db057d6
...
...
@@ -193,7 +193,8 @@ namespace dlib
- outgoing.http_return and outgoing.http_return_status may be set to override the
default HTTP return code of 200 OK
throws
- does not throw any exceptions
- throws only exceptions derived from std::exception. If an exception is thrown
then the error string from the exception is returned to the web browser.
!*/
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment