1+ #include < string_view>
2+ #include < vector>
13#include < http.h>
24#include " doctest.h"
35
6+ struct url_parsing_test_data
7+ {
8+ std::string_view url;
9+ std::string_view target_expected;
10+ std::vector<std::pair<std::string_view, std::string_view>> query_params_expected;
11+ };
12+
13+ static const url_parsing_test_data test_data[] = {
14+ {
15+ " /search?q=hello+world&lang=en" ,
16+ " /search" ,
17+ {{" q" , " hello world" }, {" lang" , " en" }}
18+ },
19+ {
20+ " /api/data?weird=%26%25%3F&empty=&plus=1%2B1%3D2" ,
21+ " /api/data" ,
22+ {{" weird" , " &%?" }, {" empty" , " " }, {" plus" , " 1+1=2" }}
23+ },
24+ {
25+ " /docs/space+test?file=name%20with%20spaces.txt&x=1" ,
26+ " /docs/space+test" ,
27+ {{" file" , " name with spaces.txt" }, {" x" , " 1" }}
28+ },
29+ {
30+ " /multi?key=value1&key=value2&key=value3" ,
31+ " /multi" ,
32+ {{" key" , " value1" }, {" key" , " value2" }, {" key" , " value3" }}
33+ },
34+ {
35+ " /equals?x=1%3D2%3D3" ,
36+ " /equals" ,
37+ {{" x" , " 1=2=3" }}
38+ },
39+ {
40+ " /onlypath" ,
41+ " /onlypath" ,
42+ {}
43+ },
44+ {
45+ " /weird?%3Fkey=%3Fvalue&key2=%26%3D" ,
46+ " /weird" ,
47+ {{" ?key" , " ?value" }, {" key2" , " &=" }}
48+ },
49+ {
50+ " /complex+path/with%2Fslashes?q=%2Fthis%2Fis%2Fa%2Ftest" ,
51+ " /complex+path/with%2Fslashes" ,
52+ {{" q" , " /this/is/a/test" }}
53+ },
54+ {
55+ " /emptykey?=novalue&foo=bar" ,
56+ " /emptykey" ,
57+ {{" " , " novalue" }, {" foo" , " bar" }}
58+ },
59+ {
60+ " /plus+in+path?plus=1+2" ,
61+ " /plus+in+path" ,
62+ {{" plus" , " 1 2" }}
63+ }
64+ };
65+
466TEST_SUITE (" [MESSAGE]" )
567{
68+ TEST_CASE (" url parsing" )
69+ {
70+ for (auto data : test_data)
71+ {
72+ std::error_code ec{};
73+ std::string target;
74+ std::vector<http::query_param> params;
75+ http::parse_url (data.url , target, params, ec);
76+ REQUIRE (!bool (ec));
77+ REQUIRE (target == data.target_expected );
78+ REQUIRE (params.size () == data.query_params_expected .size ());
79+ for (size_t i = 0 ; i < params.size () ; ++i)
80+ {
81+ REQUIRE (params[i].key == data.query_params_expected [i].first );
82+ REQUIRE (params[i].val == data.query_params_expected [i].second );
83+ }
84+ }
85+ }
86+
687 TEST_CASE (" serialise & parse bad requests" )
788 {
889 http::request req;
@@ -47,7 +128,7 @@ TEST_SUITE("[MESSAGE]")
47128 {
48129 http::request req0;
49130 req0.verb = http::GET;
50- req0.uri = " /path/to/resource/with%20spaces?q=search+term&empty=&weird=%26%25%3F " ;
131+ req0.uri = " /path/to/resource/with+spaces " ;
51132 req0.http_version_minor = 1 ;
52133 req0.add_header (http::host, " www.example.com:8080" );
53134 req0.add_header (http::user_agent, " CustomTestAgent/7.4.2 (compatible; FancyBot/1.0; +https://example.com/bot)" );
@@ -62,6 +143,9 @@ TEST_SUITE("[MESSAGE]")
62143 req0.add_header (http::pragma, " no-cache" );
63144 req0.add_header (http::content_type, " application/json; charset=\" utf-8\" " );
64145 req0.content = " {\" message\" : \" This is a test body with some content.\" }" ;
146+ req0.params .push_back ({" q" , " search term" });
147+ req0.params .push_back ({" empty" , " " });
148+ req0.params .push_back ({" weird" , " &%?" });
65149 REQUIRE (req0.keep_alive ());
66150 REQUIRE (req0.is_websocket_req ());
67151
@@ -112,6 +196,12 @@ TEST_SUITE("[MESSAGE]")
112196 REQUIRE (req0.verb == req1.verb );
113197 REQUIRE (req0.http_version_minor == req1.http_version_minor );
114198 REQUIRE (req0.uri == req1.uri );
199+ REQUIRE (req0.params .size () == req1.params .size ());
200+ for (size_t i = 0 ; i < req0.params .size () ; ++i)
201+ {
202+ REQUIRE (req0.params [i].key == req1.params [i].key );
203+ REQUIRE (req0.params [i].val == req1.params [i].val );
204+ }
115205 REQUIRE (req0.headers .size () == req1.headers .size ());
116206 for (size_t i = 0 ; i < req0.headers .size () ; ++i)
117207 {
0 commit comments