Skip to content

Commit ceb1eb2

Browse files
author
Rudolfs Bundulis
committed
Support Utf8 characters in the asynchronous connection http header name/value parser grammar
1 parent c96464d commit ceb1eb2

File tree

3 files changed

+68
-3
lines changed

3 files changed

+68
-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: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2010 Dean Michael Berris.
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+
#include <string>
11+
#include <iostream>
12+
13+
/** Synopsis
14+
*
15+
* Test for Utf8 support in the asynchronous connection header parser
16+
* --------------------------------------------
17+
*
18+
* This test checks for Utf8 support in the header parser
19+
* for asynchronous connection
20+
*
21+
*/
22+
23+
namespace tags = boost::network::tags;
24+
namespace logic = boost::logic;
25+
namespace fusion = boost::fusion;
26+
using namespace boost::network::http;
27+
28+
BOOST_AUTO_TEST_CASE(async_connection_parse_headers) {
29+
request_header_narrow utf8_header = { "X-Utf8-Test-Header", "R\uc5abdolfs" };
30+
std::string valid_http_request;
31+
valid_http_request.append(utf8_header.name).append(": ").append(utf8_header.value).append("\r\n\r\n");
32+
std::vector<request_header_narrow> headers;
33+
parse_headers(valid_http_request, headers);
34+
std::vector<request_header_narrow>::iterator utf8_header_iterator = std::find_if(headers.begin(), headers.end(), [&utf8_header, &utf8_header_iterator](request_header_narrow& header)
35+
{
36+
if (header.name == utf8_header.name && header.value == utf8_header.value)
37+
return true;
38+
return false;
39+
});
40+
BOOST_CHECK(utf8_header_iterator != headers.end());
41+
std::cout << "utf8 header parsed, name: " << utf8_header_iterator->name << ", value: " << utf8_header_iterator->value << std::endl;
42+
}

0 commit comments

Comments
 (0)