Skip to content

Commit 21c518d

Browse files
committed
Merge pull request #341 from rubu/0.11-devel
Support Utf8 characters in the asynchronous connection header parser
2 parents 172cf88 + 9d9ab23 commit 21c518d

File tree

3 files changed

+73
-3
lines changed

3 files changed

+73
-3
lines changed

boost/network/protocol/http/server/impl/parsers.ipp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6
22
#define SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6
33

4+
#define BOOST_SPIRIT_UNICODE
45
#include <boost/spirit/include/qi.hpp>
56

67
// Copyright 2010 Dean Michael Berris.
@@ -20,6 +21,26 @@
2021
#endif
2122
#include <vector>
2223

24+
namespace boost { namespace spirit { namespace traits {
25+
26+
typedef std::basic_string<uint32_t> u32_string;
27+
28+
template <> // <typename Attrib, typename T, typename Enable>
29+
struct assign_to_container_from_value<std::string, u32_string, void>
30+
{
31+
static void call(u32_string const& val, std::string& attr) {
32+
u32_to_u8_iterator<u32_string::const_iterator> begin(val.begin()), end(val.end());
33+
for(; begin != end; ++begin)
34+
attr += *begin;
35+
}
36+
};
37+
38+
} // namespace traits
39+
40+
} // namespace spirit
41+
42+
} // namespace boost
43+
2344
namespace boost { namespace network { namespace http {
2445

2546
BOOST_NETWORK_INLINE void parse_version(std::string const & partial_parsed, fusion::tuple<uint8_t,uint8_t> & version_pair) {
@@ -37,12 +58,13 @@ namespace boost { namespace network { namespace http {
3758

3859
BOOST_NETWORK_INLINE void parse_headers(std::string const & input, std::vector<request_header_narrow> & container) {
3960
using namespace boost::spirit::qi;
61+
u8_to_u32_iterator<std::string::const_iterator> begin(input.begin()), end(input.end());
4062
parse(
41-
input.begin(), input.end(),
63+
begin, end,
4264
*(
43-
+(alnum|(punct-':'))
65+
as<boost::spirit::traits::u32_string>()[+(alnum|(punct-':'))]
4466
>> lit(": ")
45-
>> +((alnum|space|punct) - '\r' - '\n')
67+
>> as<boost::spirit::traits::u32_string>()[+((unicode::alnum|space|punct) - '\r' - '\n')]
4668
>> lit("\r\n")
4769
)
4870
>> lit("\r\n")

libs/network/test/http/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ if (Boost_FOUND)
6262
set ( SERVER_API_TESTS
6363
server_constructor_test
6464
server_async_run_stop_concurrency
65+
server_header_parser_test
6566
)
6667
foreach ( test ${SERVER_API_TESTS} )
6768
add_executable(cpp-netlib-http-${test} ${test}.cpp)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2013 Rudolfs Bundulis
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// (See accompanying file LICENSE_1_0.txt or copy at
4+
// http://www.boost.org/LICENSE_1_0.txt)
5+
6+
#define BOOST_TEST_MODULE HTTP Server Header Parser Test
7+
#include <boost/network/protocol/http/server.hpp>
8+
#include <boost/config/warning_disable.hpp>
9+
#include <boost/test/unit_test.hpp>
10+
#define BOOST_LOCALE_NO_LIB
11+
#include <boost/locale/encoding.hpp>
12+
#include <string>
13+
#include <iostream>
14+
15+
/** Synopsis
16+
*
17+
* Test for Utf8 support in the asynchronous connection header parser
18+
* --------------------------------------------
19+
*
20+
* This test checks for Utf8 support in the header parser
21+
* for asynchronous connection
22+
*
23+
*/
24+
25+
namespace tags = boost::network::tags;
26+
namespace logic = boost::logic;
27+
namespace fusion = boost::fusion;
28+
using namespace boost::network::http;
29+
30+
BOOST_AUTO_TEST_CASE(async_connection_parse_headers) {
31+
std::wstring utf16_test_name = L"R\u016bdolfs";
32+
request_header_narrow utf8_header = { "X-Utf8-Test-Header", boost::locale::conv::utf_to_utf<char>(utf16_test_name) };
33+
std::string valid_http_request;
34+
valid_http_request.append(utf8_header.name).append(": ").append(utf8_header.value).append("\r\n\r\n");
35+
std::vector<request_header_narrow> headers;
36+
parse_headers(valid_http_request, headers);
37+
std::vector<request_header_narrow>::iterator header_iterator = headers.begin();
38+
for(; header_iterator != headers.end(); ++ header_iterator)
39+
{
40+
if (header_iterator->name == utf8_header.name && header_iterator->value == utf8_header.value)
41+
break;
42+
}
43+
std::wstring utf16_test_name_from_header = boost::locale::conv::utf_to_utf<wchar_t>(header_iterator->value);
44+
BOOST_CHECK(header_iterator != headers.end());
45+
BOOST_CHECK(utf16_test_name_from_header == utf16_test_name);
46+
std::cout << "utf8 header parsed, name: " << header_iterator->name << ", value: " << header_iterator->value;
47+
}

0 commit comments

Comments
 (0)