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
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
356 additions
and
284 deletions
+356
-284
server_http_1.h
dlib/server/server_http_1.h
+354
-283
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,103 +25,94 @@
namespace
dlib
{
template
<
typename
server_base
>
class
server_http_1
:
public
server_base
// ----------------------------------------------------------------------------------------
class
http_parse_error
:
public
error
{
public
:
http_parse_error
(
const
std
::
string
&
str
,
int
http_error_code_
)
:
error
(
str
),
http_error_code
(
http_error_code_
)
{}
/*!
CONVENTION
this extension doesn't add any new state to this object.
!*/
const
int
http_error_code
;
};
// ----------------------------------------------------------------------------------------
template
<
typename
Key
,
typename
Value
>
class
constmap
:
public
std
::
map
<
Key
,
Value
>
{
public
:
server_http_1
()
const
Value
&
operator
[](
const
Key
&
k
)
const
{
max_content_length
=
10
*
1024
*
1024
;
// 10MB
}
static
const
Value
dummy
=
Value
();
unsigned
long
get_max_content_length
(
)
const
{
return
max_content_length
;
}
typename
std
::
map
<
Key
,
Value
>::
const_iterator
ci
=
std
::
map
<
Key
,
Value
>::
find
(
k
);
void
set_max_content_length
(
unsigned
long
max_length
)
{
max_content_length
=
max_length
;
if
(
ci
==
this
->
end
()
)
return
dummy
;
else
return
ci
->
second
;
}
template
<
typename
Key
,
typename
Value
>
class
constmap
:
public
std
::
map
<
Key
,
Value
>
{
public
:
const
Value
&
operator
[](
const
Key
&
k
)
const
{
static
const
Value
dummy
=
Value
();
typename
std
::
map
<
Key
,
Value
>::
const_iterator
ci
=
std
::
map
<
Key
,
Value
>::
find
(
k
);
if
(
ci
==
this
->
end
()
)
return
dummy
;
else
return
ci
->
second
;
}
Value
&
operator
[](
const
Key
&
k
)
{
return
std
::
map
<
Key
,
Value
>::
operator
[](
k
);
}
};
typedef
constmap
<
std
::
string
,
std
::
string
>
key_value_map
;
struct
incoming_things
Value
&
operator
[](
const
Key
&
k
)
{
incoming_things
()
:
foreign_port
(
0
),
local_port
(
0
)
{}
std
::
string
path
;
std
::
string
request_type
;
std
::
string
content_type
;
std
::
string
protocol
;
std
::
string
body
;
key_value_map
queries
;
key_value_map
cookies
;
key_value_map
headers
;
return
std
::
map
<
Key
,
Value
>::
operator
[](
k
);
}
};
std
::
string
foreign_ip
;
unsigned
short
foreign_port
;
std
::
string
local_ip
;
unsigned
short
local_port
;
};
typedef
constmap
<
std
::
string
,
std
::
string
>
key_value_map
;
struct
outgoing_things
{
outgoing_things
()
:
http_return
(
200
)
{
}
struct
incoming_things
{
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
;
std
::
string
content_type
;
std
::
string
protocol
;
std
::
string
body
;
key_value_map
queries
;
key_value_map
cookies
;
key_value_map
headers
;
std
::
string
foreign_ip
;
unsigned
short
foreign_port
;
std
::
string
local_ip
;
unsigned
short
local_port
;
};
key_value_map
cookies
;
key_value_map
headers
;
unsigned
short
http_return
;
std
::
string
http_return_status
;
};
struct
outgoing_things
{
outgoing_things
()
:
http_return
(
200
),
http_return_status
(
"OK"
)
{
}
key_value_map
cookies
;
key_value_map
headers
;
unsigned
short
http_return
;
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,238 +250,314 @@ namespace dlib
}
}
}
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
)
{
bool
my_fault
=
true
;
}
using
namespace
std
;
try
inline
unsigned
long
parse_http_request
(
std
::
istream
&
in
,
incoming_things
&
incoming
,
unsigned
long
max_content_length
)
{
using
namespace
std
;
using
namespace
http_impl
;
read_with_limit
(
in
,
incoming
.
request_type
,
' '
);
// get the path
read_with_limit
(
in
,
incoming
.
path
,
' '
);
// Get the HTTP/1.1 - Ignore for now...
read_with_limit
(
in
,
incoming
.
protocol
);
key_value_map
&
incoming_headers
=
incoming
.
headers
;
key_value_map
&
cookies
=
incoming
.
cookies
;
std
::
string
&
path
=
incoming
.
path
;
std
::
string
&
content_type
=
incoming
.
content_type
;
unsigned
long
content_length
=
0
;
string
line
;
read_with_limit
(
in
,
line
);
string
first_part_of_header
;
string
::
size_type
position_of_double_point
;
// now loop over all the incoming_headers
while
(
line
.
size
()
>
2
)
{
position_of_double_point
=
line
.
find_first_of
(
':'
);
if
(
position_of_double_point
!=
string
::
npos
)
{
incoming_things
incoming
;
outgoing_things
outgoing
;
first_part_of_header
=
dlib
::
trim
(
line
.
substr
(
0
,
position_of_double_point
));
if
(
!
incoming_headers
[
first_part_of_header
].
empty
()
)
incoming_headers
[
first_part_of_header
]
+=
" "
;
incoming_headers
[
first_part_of_header
]
+=
dlib
::
trim
(
line
.
substr
(
position_of_double_point
+
1
));
incoming
.
foreign_ip
=
foreign_ip
;
incoming
.
foreign_port
=
foreign_port
;
incoming
.
local_ip
=
local_ip
;
incoming
.
local_port
=
local_port
;
read_with_limit
(
in
,
incoming
.
request_type
,
' '
);
// get the path
read_with_limit
(
in
,
incoming
.
path
,
' '
);
// Get the HTTP/1.1 - Ignore for now...
read_with_limit
(
in
,
incoming
.
protocol
);
key_value_map
&
incoming_headers
=
incoming
.
headers
;
key_value_map
&
cookies
=
incoming
.
cookies
;
std
::
string
&
path
=
incoming
.
path
;
std
::
string
&
content_type
=
incoming
.
content_type
;
unsigned
long
content_length
=
0
;
string
line
;
read_with_limit
(
in
,
line
);
string
first_part_of_header
;
string
::
size_type
position_of_double_point
;
// now loop over all the incoming_headers
while
(
line
.
size
()
>
2
)
// look for Content-Type:
if
(
line
.
size
()
>
14
&&
strings_equal_ignore_case
(
line
,
"Content-Type:"
,
13
))
{
position_of_double_point
=
line
.
find_first_of
(
':'
);
if
(
position_of_double_point
!=
string
::
npos
)
content_type
=
line
.
substr
(
14
);
if
(
content_type
[
content_type
.
size
()
-
1
]
==
'\r'
)
content_type
.
erase
(
content_type
.
size
()
-
1
);
}
// look for Content-Length:
else
if
(
line
.
size
()
>
16
&&
strings_equal_ignore_case
(
line
,
"Content-Length:"
,
15
))
{
istringstream
sin
(
line
.
substr
(
16
));
sin
>>
content_length
;
if
(
!
sin
)
{
first_part_of_header
=
dlib
::
trim
(
line
.
substr
(
0
,
position_of_double_point
));
throw
http_parse_error
(
"Invalid Content-Length of '"
+
line
.
substr
(
16
)
+
"'"
,
411
);
}
if
(
!
incoming_headers
[
first_part_of_header
].
empty
()
)
incoming_headers
[
first_part_of_header
]
+=
" "
;
incoming_headers
[
first_part_of_header
]
+=
dlib
::
trim
(
line
.
substr
(
position_of_double_point
+
1
));
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
))
{
string
::
size_type
pos
=
6
;
string
key
,
value
;
bool
seen_key_start
=
false
;
bool
seen_equal_sign
=
false
;
while
(
pos
+
1
<
line
.
size
())
{
++
pos
;
// ignore whitespace between cookies
if
(
!
seen_key_start
&&
line
[
pos
]
==
' '
)
continue
;
// look for Content-Type:
if
(
line
.
size
()
>
14
&&
strings_equal_ignore_case
(
line
,
"Content-Type:"
,
13
))
{
content_type
=
line
.
substr
(
14
);
if
(
content_type
[
content_type
.
size
()
-
1
]
==
'\r'
)
content_type
.
erase
(
content_type
.
size
()
-
1
);
}
// look for Content-Length:
else
if
(
line
.
size
()
>
16
&&
strings_equal_ignore_case
(
line
,
"Content-Length:"
,
15
))
{
istringstream
sin
(
line
.
substr
(
16
));
sin
>>
content_length
;
if
(
!
sin
)
content_length
=
0
;
}
// look for any cookies
else
if
(
line
.
size
()
>
6
&&
strings_equal_ignore_case
(
line
,
"Cookie:"
,
7
))
seen_key_start
=
true
;
if
(
!
seen_equal_sign
)
{
string
::
size_type
pos
=
6
;
string
key
,
value
;
bool
seen_key_start
=
false
;
bool
seen_equal_sign
=
false
;
while
(
pos
+
1
<
line
.
size
())
if
(
line
[
pos
]
==
'='
)
{
++
pos
;
// ignore whitespace between cookies
if
(
!
seen_key_start
&&
line
[
pos
]
==
' '
)
continue
;
seen_key_start
=
true
;
if
(
!
seen_equal_sign
)
{
if
(
line
[
pos
]
==
'='
)
{
seen_equal_sign
=
true
;
}
else
{
key
+=
line
[
pos
];
}
}
else
{
if
(
line
[
pos
]
==
';'
)
{
cookies
[
urldecode
(
key
)]
=
urldecode
(
value
);
seen_equal_sign
=
false
;
seen_key_start
=
false
;
key
.
clear
();
value
.
clear
();
}
else
{
value
+=
line
[
pos
];
}
}
seen_equal_sign
=
true
;
}
if
(
key
.
size
()
>
0
)
else
{
key
+=
line
[
pos
];
}
}
else
{
if
(
line
[
pos
]
==
';'
)
{
cookies
[
urldecode
(
key
)]
=
urldecode
(
value
);
seen_equal_sign
=
false
;
seen_key_start
=
false
;
key
.
clear
();
value
.
clear
();
}
else
{
value
+=
line
[
pos
];
}
}
}
// no ':' in it!
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
(
key
.
size
()
>
0
)
{
cookies
[
urldecode
(
key
)]
=
urldecode
(
value
);
key
.
clear
();
value
.
clear
();
}
}
}
// no ':' in it!
read_with_limit
(
in
,
line
);
}
// while (line.size() > 2 )
// If there is data being posted back to us as a query string then
// pick out the queries using parse_url.
if
((
strings_equal_ignore_case
(
incoming
.
request_type
,
"POST"
)
||
strings_equal_ignore_case
(
incoming
.
request_type
,
"PUT"
))
&&
strings_equal_ignore_case
(
left_substr
(
content_type
,
";"
),
"application/x-www-form-urlencoded"
))
{
parse_url
(
incoming
.
body
,
incoming
.
queries
);
}
string
::
size_type
pos
=
path
.
find_first_of
(
"?"
);
if
(
pos
!=
string
::
npos
)
{
parse_url
(
path
.
substr
(
pos
+
1
),
incoming
.
queries
);
}
// If there is data being posted back to us as a query string then
// pick out the queries using parse_url.
if
((
strings_equal_ignore_case
(
incoming
.
request_type
,
"POST"
)
||
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
);
}
string
::
size_type
pos
=
path
.
find_first_of
(
"?"
);
if
(
pos
!=
string
::
npos
)
{
parse_url
(
path
.
substr
(
pos
+
1
),
incoming
.
queries
);
}
my_fault
=
false
;
key_value_map
&
new_cookies
=
outgoing
.
cookies
;
key_value_map
&
response_headers
=
outgoing
.
headers
;
// Set some defaults
outgoing
.
http_return
=
200
;
outgoing
.
http_return_status
=
"OK"
;
if
(
!
in
)
throw
http_parse_error
(
"Error parsing HTTP request"
,
500
);
// if there wasn't a problem with the input stream at some point
// then lets trigger this request callback.
std
::
string
result
;
if
(
in
)
{
result
=
on_request
(
incoming
,
outgoing
);
}
else
{
dlog
<<
LERROR
<<
"Request from: "
<<
foreign_ip
<<
" - Invalid request - Request Entity Too Large"
;
outgoing
.
http_return
=
413
;
outgoing
.
http_return_status
=
"Request Entity Too Large"
;
}
my_fault
=
true
;
return
content_length
;
}
// only send this header if the user hasn't told us to send another kind
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"
)
)
{
has_content_type
=
true
;
}
else
if
(
!
has_location
&&
strings_equal_ignore_case
(
ci
->
first
,
"location"
)
)
{
has_location
=
true
;
}
}
inline
void
read_body
(
std
::
istream
&
in
,
incoming_things
&
incoming
)
{
// 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"
]);
if
(
has_location
)
{
outgoing
.
http_return
=
302
;
}
incoming
.
body
.
resize
(
content_length
);
if
(
content_length
>
0
)
{
in
.
read
(
&
incoming
.
body
[
0
],
content_length
);
}
}
}
if
(
!
has_content_type
)
{
response_headers
[
"Content-Type"
]
=
"text/html"
;
}
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
;
{
ostringstream
os
;
os
<<
result
.
size
();
// only send this header if the user hasn't told us to send another kind
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"
)
)
{
has_content_type
=
true
;
}
else
if
(
!
has_location
&&
strings_equal_ignore_case
(
ci
->
first
,
"location"
)
)
{
has_location
=
true
;
}
}
response_headers
[
"Content-Length"
]
=
os
.
str
();
}
if
(
has_location
)
{
outgoing
.
http_return
=
302
;
}
out
<<
"HTTP/1.0 "
<<
outgoing
.
http_return
<<
" "
<<
outgoing
.
http_return_status
<<
"
\r\n
"
;
if
(
!
has_content_type
)
{
response_headers
[
"Content-Type"
]
=
"text/html"
;
}
// Set any new headers
for
(
typename
key_value_map
::
const_iterator
ci
=
response_headers
.
begin
();
ci
!=
response_headers
.
end
();
++
ci
)
{
out
<<
ci
->
first
<<
": "
<<
ci
->
second
<<
"
\r\n
"
;
}
response_headers
[
"Content-Length"
]
=
cast_to_string
(
result
.
size
());
// set any cookies
for
(
typename
key_value_map
::
const_iterator
ci
=
new_cookies
.
begin
();
ci
!=
new_cookies
.
end
();
++
ci
)
{
out
<<
"Set-Cookie: "
<<
urlencode
(
ci
->
first
)
<<
'='
<<
urlencode
(
ci
->
second
)
<<
"
\r\n
"
;
}
out
<<
"
\r\n
"
<<
result
;
out
<<
"HTTP/1.0 "
<<
outgoing
.
http_return
<<
" "
<<
outgoing
.
http_return_status
<<
"
\r\n
"
;
// Set any new headers
for
(
typename
key_value_map
::
const_iterator
ci
=
response_headers
.
begin
();
ci
!=
response_headers
.
end
();
++
ci
)
{
out
<<
ci
->
first
<<
": "
<<
ci
->
second
<<
"
\r\n
"
;
}
// set any cookies
for
(
typename
key_value_map
::
const_iterator
ci
=
new_cookies
.
begin
();
ci
!=
new_cookies
.
end
();
++
ci
)
{
out
<<
"Set-Cookie: "
<<
urlencode
(
ci
->
first
)
<<
'='
<<
urlencode
(
ci
->
second
)
<<
"
\r\n
"
;
}
out
<<
"
\r\n
"
<<
result
;
}
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
)
{
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
(
std
::
bad_alloc
&
)
catch
(
http_parse_error
&
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
;
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