• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "assert.hpp"
2 #include "client_http.hpp"
3 #include "server_http.hpp"
4 #include <iostream>
5 
6 using namespace std;
7 using namespace SimpleWeb;
8 
9 class ServerTest : public ServerBase<HTTP> {
10 public:
ServerTest()11   ServerTest() : ServerBase<HTTP>::ServerBase(8080) {}
12 
accept()13   void accept() noexcept override {}
14 
parse_request_test()15   void parse_request_test() {
16     auto session = std::make_shared<Session>(static_cast<size_t>(-1), create_connection(*io_service));
17 
18     std::ostream stream(&session->request->content.streambuf);
19     stream << "GET /test/ HTTP/1.1\r\n";
20     stream << "TestHeader: test\r\n";
21     stream << "TestHeader2:test2\r\n";
22     stream << "TestHeader3:test3a\r\n";
23     stream << "TestHeader3:test3b\r\n";
24     stream << "\r\n";
25 
26     ASSERT(RequestMessage::parse(session->request->content, session->request->method, session->request->path,
27                                  session->request->query_string, session->request->http_version, session->request->header));
28 
29     ASSERT(session->request->method == "GET");
30     ASSERT(session->request->path == "/test/");
31     ASSERT(session->request->http_version == "1.1");
32 
33     ASSERT(session->request->header.size() == 4);
34     auto header_it = session->request->header.find("TestHeader");
35     ASSERT(header_it != session->request->header.end() && header_it->second == "test");
36     header_it = session->request->header.find("TestHeader2");
37     ASSERT(header_it != session->request->header.end() && header_it->second == "test2");
38 
39     header_it = session->request->header.find("testheader");
40     ASSERT(header_it != session->request->header.end() && header_it->second == "test");
41     header_it = session->request->header.find("testheader2");
42     ASSERT(header_it != session->request->header.end() && header_it->second == "test2");
43 
44     auto range = session->request->header.equal_range("testheader3");
45     auto first = range.first;
46     auto second = first;
47     ++second;
48     ASSERT(range.first != session->request->header.end() && range.second != session->request->header.end() &&
49            ((first->second == "test3a" && second->second == "test3b") ||
50             (first->second == "test3b" && second->second == "test3a")));
51   }
52 };
53 
54 class ClientTest : public ClientBase<HTTP> {
55 public:
ClientTest(const std::string & server_port_path)56   ClientTest(const std::string &server_port_path) : ClientBase<HTTP>::ClientBase(server_port_path, 80) {}
57 
create_connection()58   std::shared_ptr<Connection> create_connection() noexcept override {
59     return nullptr;
60   }
61 
connect(const std::shared_ptr<Session> &)62   void connect(const std::shared_ptr<Session> &) noexcept override {}
63 
parse_response_header_test()64   void parse_response_header_test() {
65     std::shared_ptr<Response> response(new Response(static_cast<size_t>(-1), nullptr));
66 
67     ostream stream(&response->streambuf);
68     stream << "HTTP/1.1 200 OK\r\n";
69     stream << "TestHeader: test\r\n";
70     stream << "TestHeader2:  test2\r\n";
71     stream << "TestHeader3:test3a\r\n";
72     stream << "TestHeader3:test3b\r\n";
73     stream << "TestHeader4:\r\n";
74     stream << "TestHeader5: \r\n";
75     stream << "TestHeader6:  \r\n";
76     stream << "\r\n";
77 
78     ASSERT(ResponseMessage::parse(response->content, response->http_version, response->status_code, response->header));
79 
80     ASSERT(response->http_version == "1.1");
81     ASSERT(response->status_code == "200 OK");
82 
83     ASSERT(response->header.size() == 7);
84     auto header_it = response->header.find("TestHeader");
85     ASSERT(header_it != response->header.end() && header_it->second == "test");
86     header_it = response->header.find("TestHeader2");
87     ASSERT(header_it != response->header.end() && header_it->second == "test2");
88 
89     header_it = response->header.find("testheader");
90     ASSERT(header_it != response->header.end() && header_it->second == "test");
91     header_it = response->header.find("testheader2");
92     ASSERT(header_it != response->header.end() && header_it->second == "test2");
93 
94     auto range = response->header.equal_range("testheader3");
95     auto first = range.first;
96     auto second = first;
97     ++second;
98     ASSERT(range.first != response->header.end() && range.second != response->header.end() &&
99            ((first->second == "test3a" && second->second == "test3b") ||
100             (first->second == "test3b" && second->second == "test3a")));
101 
102     header_it = response->header.find("TestHeader4");
103     ASSERT(header_it != response->header.end() && header_it->second == "");
104     header_it = response->header.find("TestHeader5");
105     ASSERT(header_it != response->header.end() && header_it->second == "");
106     header_it = response->header.find("TestHeader6");
107     ASSERT(header_it != response->header.end() && header_it->second == "");
108   }
109 };
110 
main()111 int main() {
112   ASSERT(case_insensitive_equal("Test", "tesT"));
113   ASSERT(case_insensitive_equal("tesT", "test"));
114   ASSERT(!case_insensitive_equal("test", "tseT"));
115   CaseInsensitiveEqual equal;
116   ASSERT(equal("Test", "tesT"));
117   ASSERT(equal("tesT", "test"));
118   ASSERT(!equal("test", "tset"));
119   CaseInsensitiveHash hash;
120   ASSERT(hash("Test") == hash("tesT"));
121   ASSERT(hash("tesT") == hash("test"));
122   ASSERT(hash("test") != hash("tset"));
123 
124   auto percent_decoded = "testing æøå !#$&'()*+,/:;=?@[]123-._~\r\n";
125   auto percent_encoded = "testing%20%C3%A6%C3%B8%C3%A5%20%21%23%24%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D123-._~%0D%0A";
126   ASSERT(Percent::encode(percent_decoded) == percent_encoded);
127   ASSERT(Percent::decode(percent_encoded) == percent_decoded);
128   ASSERT(Percent::decode(Percent::encode(percent_decoded)) == percent_decoded);
129 
130   SimpleWeb::CaseInsensitiveMultimap fields = {{"test1", "æøå"}, {"test2", "!#$&'()*+,/:;=?@[]"}};
131   auto query_string1 = "test1=%C3%A6%C3%B8%C3%A5&test2=%21%23%24%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D";
132   auto query_string2 = "test2=%21%23%24%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D&test1=%C3%A6%C3%B8%C3%A5";
133   auto query_string_result = QueryString::create(fields);
134   ASSERT(query_string_result == query_string1 || query_string_result == query_string2);
135   auto fields_result1 = QueryString::parse(query_string1);
136   auto fields_result2 = QueryString::parse(query_string2);
137   ASSERT(fields_result1 == fields_result2 && fields_result1 == fields);
138 
139   auto serverTest = make_shared<ServerTest>();
140   serverTest->io_service = std::make_shared<io_context>();
141 
142   serverTest->parse_request_test();
143 
144   {
145     ClientTest clientTest("test.org");
146     ASSERT(clientTest.host == "test.org");
147     ASSERT(clientTest.port == 80);
148     clientTest.parse_response_header_test();
149   }
150 
151   {
152     ClientTest clientTest("test.org:8080");
153     ASSERT(clientTest.host == "test.org");
154     ASSERT(clientTest.port == 8080);
155   }
156 
157   {
158     ClientTest clientTest("test.org:test");
159     ASSERT(clientTest.host == "test.org");
160     ASSERT(clientTest.port == 80);
161   }
162 
163   {
164     ClientTest clientTest("[::1]");
165     ASSERT(clientTest.host == "::1");
166     ASSERT(clientTest.port == 80);
167   }
168 
169   {
170     ClientTest clientTest("[::1]:8080");
171     ASSERT(clientTest.host == "::1");
172     ASSERT(clientTest.port == 8080);
173   }
174 
175 
176   io_context io_service;
177   asio::ip::tcp::socket socket(io_service);
178   SimpleWeb::Server<HTTP>::Request request(static_cast<size_t>(-1), nullptr);
179   {
180     request.query_string = "";
181     auto queries = request.parse_query_string();
182     ASSERT(queries.empty());
183   }
184   {
185     request.query_string = "=";
186     auto queries = request.parse_query_string();
187     ASSERT(queries.empty());
188   }
189   {
190     request.query_string = "=test";
191     auto queries = request.parse_query_string();
192     ASSERT(queries.empty());
193   }
194   {
195     request.query_string = "a=1%202%20%203&b=3+4&c&d=æ%25ø%26å%3F";
196     auto queries = request.parse_query_string();
197     {
198       auto range = queries.equal_range("a");
199       ASSERT(range.first != range.second);
200       ASSERT(range.first->second == "1 2  3");
201     }
202     {
203       auto range = queries.equal_range("b");
204       ASSERT(range.first != range.second);
205       ASSERT(range.first->second == "3 4");
206     }
207     {
208       auto range = queries.equal_range("c");
209       ASSERT(range.first != range.second);
210       ASSERT(range.first->second == "");
211     }
212     {
213       auto range = queries.equal_range("d");
214       ASSERT(range.first != range.second);
215       ASSERT(range.first->second == "æ%ø&å?");
216     }
217   }
218 
219   {
220     SimpleWeb::CaseInsensitiveMultimap solution;
221     std::stringstream header;
222     auto parsed = SimpleWeb::HttpHeader::parse(header);
223     ASSERT(parsed == solution);
224   }
225   {
226     SimpleWeb::CaseInsensitiveMultimap solution = {{"Content-Type", "application/json"}};
227     std::stringstream header("Content-Type: application/json");
228     auto parsed = SimpleWeb::HttpHeader::parse(header);
229     ASSERT(parsed == solution);
230   }
231   {
232     SimpleWeb::CaseInsensitiveMultimap solution = {{"Content-Type", "application/json"}};
233     std::stringstream header("Content-Type: application/json\r");
234     auto parsed = SimpleWeb::HttpHeader::parse(header);
235     ASSERT(parsed == solution);
236   }
237   {
238     SimpleWeb::CaseInsensitiveMultimap solution = {{"Content-Type", "application/json"}};
239     std::stringstream header("Content-Type: application/json\r\n");
240     auto parsed = SimpleWeb::HttpHeader::parse(header);
241     ASSERT(parsed == solution);
242   }
243 
244   {
245     {
246       SimpleWeb::CaseInsensitiveMultimap solution;
247       auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("");
248       ASSERT(parsed == solution);
249     }
250     {
251       SimpleWeb::CaseInsensitiveMultimap solution = {{"a", ""}};
252       auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("a");
253       ASSERT(parsed == solution);
254     }
255     {
256       SimpleWeb::CaseInsensitiveMultimap solution = {{"a", ""}, {"b", ""}};
257       {
258         auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("a; b");
259         ASSERT(parsed == solution);
260       }
261       {
262         auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("a;b");
263         ASSERT(parsed == solution);
264       }
265     }
266     {
267       SimpleWeb::CaseInsensitiveMultimap solution = {{"a", ""}, {"b", "c"}};
268       {
269         auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("a; b=c");
270         ASSERT(parsed == solution);
271       }
272       {
273         auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("a;b=c");
274         ASSERT(parsed == solution);
275       }
276     }
277     {
278       SimpleWeb::CaseInsensitiveMultimap solution = {{"form-data", ""}};
279       auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data");
280       ASSERT(parsed == solution);
281     }
282     {
283       SimpleWeb::CaseInsensitiveMultimap solution = {{"form-data", ""}, {"test", ""}};
284       {
285         auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; test");
286         ASSERT(parsed == solution);
287       }
288     }
289     {
290       SimpleWeb::CaseInsensitiveMultimap solution = {{"form-data", ""}, {"name", "file"}};
291       {
292         auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; name=\"file\"");
293         ASSERT(parsed == solution);
294       }
295       {
296         auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; name=file");
297         ASSERT(parsed == solution);
298       }
299     }
300     {
301       SimpleWeb::CaseInsensitiveMultimap solution = {{"form-data", ""}, {"name", "file"}, {"filename", "filename.png"}};
302       {
303         auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; name=\"file\"; filename=\"filename.png\"");
304         ASSERT(parsed == solution);
305       }
306       {
307         auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data;name=\"file\";filename=\"filename.png\"");
308         ASSERT(parsed == solution);
309       }
310       {
311         auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; name=file; filename=filename.png");
312         ASSERT(parsed == solution);
313       }
314       {
315         auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data;name=file;filename=filename.png");
316         ASSERT(parsed == solution);
317       }
318     }
319     {
320       SimpleWeb::CaseInsensitiveMultimap solution = {{"form-data", ""}, {"name", "fi le"}, {"filename", "file name.png"}};
321       {
322         auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; name=\"fi le\"; filename=\"file name.png\"");
323         ASSERT(parsed == solution);
324       }
325       {
326         auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; name=\"fi%20le\"; filename=\"file%20name.png\"");
327         ASSERT(parsed == solution);
328       }
329       {
330         auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; name=fi le; filename=file name.png");
331         ASSERT(parsed == solution);
332       }
333       {
334         auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; name=fi%20le; filename=file%20name.png");
335         ASSERT(parsed == solution);
336       }
337     }
338   }
339 
340   ASSERT(SimpleWeb::Date::to_string(std::chrono::system_clock::now()).size() == 29);
341 }
342