test.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. #include <gtest/gtest.h>
  2. #include <httplib.h>
  3. #include <future>
  4. #include <iostream>
  5. #define SERVER_CERT_FILE "./cert.pem"
  6. #define SERVER_PRIVATE_KEY_FILE "./key.pem"
  7. #ifdef _WIN32
  8. #include <process.h>
  9. #define msleep(n) ::Sleep(n)
  10. #else
  11. #define msleep(n) ::usleep(n * 1000)
  12. #endif
  13. using namespace std;
  14. using namespace httplib;
  15. const char* HOST = "localhost";
  16. const int PORT = 1234;
  17. #ifdef _WIN32
  18. TEST(StartupTest, WSAStartup)
  19. {
  20. WSADATA wsaData;
  21. int ret = WSAStartup(0x0002, &wsaData);
  22. ASSERT_EQ(0, ret);
  23. }
  24. #endif
  25. TEST(SplitTest, ParseQueryString)
  26. {
  27. string s = "key1=val1&key2=val2&key3=val3";
  28. map<string, string> dic;
  29. detail::split(s.c_str(), s.c_str() + s.size(), '&', [&](const char* b, const char* e) {
  30. string key, val;
  31. detail::split(b, e, '=', [&](const char* b, const char* e) {
  32. if (key.empty()) {
  33. key.assign(b, e);
  34. } else {
  35. val.assign(b, e);
  36. }
  37. });
  38. dic[key] = val;
  39. });
  40. EXPECT_EQ("val1", dic["key1"]);
  41. EXPECT_EQ("val2", dic["key2"]);
  42. EXPECT_EQ("val3", dic["key3"]);
  43. }
  44. TEST(ParseQueryTest, ParseQueryString)
  45. {
  46. string s = "key1=val1&key2=val2&key3=val3";
  47. map<string, string> dic;
  48. detail::parse_query_text(s, dic);
  49. EXPECT_EQ("val1", dic["key1"]);
  50. EXPECT_EQ("val2", dic["key2"]);
  51. EXPECT_EQ("val3", dic["key3"]);
  52. }
  53. TEST(SocketTest, OpenClose)
  54. {
  55. socket_t sock = detail::create_server_socket(HOST, PORT, 0);
  56. ASSERT_NE(-1, sock);
  57. auto ret = detail::close_socket(sock);
  58. EXPECT_EQ(0, ret);
  59. }
  60. TEST(SocketTest, OpenCloseWithAI_PASSIVE)
  61. {
  62. socket_t sock = detail::create_server_socket(nullptr, PORT, AI_PASSIVE);
  63. ASSERT_NE(-1, sock);
  64. auto ret = detail::close_socket(sock);
  65. EXPECT_EQ(0, ret);
  66. }
  67. TEST(GetHeaderValueTest, DefaultValue)
  68. {
  69. MultiMap map = {{"Dummy","Dummy"}};
  70. auto val = detail::get_header_value(map, "Content-Type", "text/plain");
  71. ASSERT_STREQ("text/plain", val);
  72. }
  73. TEST(GetHeaderValueTest, DefaultValueInt)
  74. {
  75. MultiMap map = {{"Dummy","Dummy"}};
  76. auto val = detail::get_header_value_int(map, "Content-Length", 100);
  77. EXPECT_EQ(100, val);
  78. }
  79. TEST(GetHeaderValueTest, RegularValue)
  80. {
  81. MultiMap map = {{"Content-Type", "text/html"}, {"Dummy", "Dummy"}};
  82. auto val = detail::get_header_value(map, "Content-Type", "text/plain");
  83. ASSERT_STREQ("text/html", val);
  84. }
  85. TEST(GetHeaderValueTest, RegularValueInt)
  86. {
  87. MultiMap map = {{"Content-Length", "100"}, {"Dummy", "Dummy"}};
  88. auto val = detail::get_header_value_int(map, "Content-Length", 0);
  89. EXPECT_EQ(100, val);
  90. }
  91. void testChunkedEncoding(httplib::HttpVersion ver)
  92. {
  93. auto host = "www.httpwatch.com";
  94. auto port = 80;
  95. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  96. httplib::SSLClient cli(host, port, ver);
  97. #else
  98. httplib::Client cli(host, port, ver);
  99. #endif
  100. auto res = cli.get("/httpgallery/chunked/chunkedimage.aspx?0.4153841143030137");
  101. ASSERT_TRUE(res != nullptr);
  102. std::string out;
  103. httplib::detail::read_file("./image.jpg", out);
  104. EXPECT_EQ(200, res->status);
  105. EXPECT_EQ(out, res->body);
  106. }
  107. TEST(ChunkedEncodingTest, FromHTTPWatch)
  108. {
  109. testChunkedEncoding(httplib::HttpVersion::v1_0);
  110. testChunkedEncoding(httplib::HttpVersion::v1_1);
  111. }
  112. class ServerTest : public ::testing::Test {
  113. protected:
  114. ServerTest()
  115. : cli_(HOST, PORT)
  116. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  117. , svr_(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE)
  118. #endif
  119. , up_(false) {}
  120. virtual void SetUp() {
  121. svr_.set_base_dir("./www");
  122. svr_.get("/hi", [&](const Request& /*req*/, Response& res) {
  123. res.set_content("Hello World!", "text/plain");
  124. })
  125. .get("/", [&](const Request& /*req*/, Response& res) {
  126. res.set_redirect("/hi");
  127. })
  128. .post("/person", [&](const Request& req, Response& res) {
  129. if (req.has_param("name") && req.has_param("note")) {
  130. persons_[req.params.at("name")] = req.params.at("note");
  131. } else {
  132. res.status = 400;
  133. }
  134. })
  135. .get("/person/(.*)", [&](const Request& req, Response& res) {
  136. string name = req.matches[1];
  137. if (persons_.find(name) != persons_.end()) {
  138. auto note = persons_[name];
  139. res.set_content(note, "text/plain");
  140. } else {
  141. res.status = 404;
  142. }
  143. })
  144. .get("/stop", [&](const Request& /*req*/, Response& /*res*/) {
  145. svr_.stop();
  146. });
  147. persons_["john"] = "programmer";
  148. f_ = async([&](){
  149. up_ = true;
  150. svr_.listen(HOST, PORT);
  151. });
  152. while (!up_) {
  153. msleep(1);
  154. }
  155. }
  156. virtual void TearDown() {
  157. //svr_.stop(); // NOTE: This causes dead lock on Windows.
  158. cli_.get("/stop");
  159. f_.get();
  160. }
  161. map<string, string> persons_;
  162. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  163. SSLClient cli_;
  164. SSLServer svr_;
  165. #else
  166. Client cli_;
  167. Server svr_;
  168. #endif
  169. future<void> f_;
  170. bool up_;
  171. };
  172. TEST_F(ServerTest, GetMethod200)
  173. {
  174. auto res = cli_.get("/hi");
  175. ASSERT_TRUE(res != nullptr);
  176. EXPECT_EQ(200, res->status);
  177. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  178. EXPECT_EQ("Hello World!", res->body);
  179. }
  180. TEST_F(ServerTest, GetMethod302)
  181. {
  182. auto res = cli_.get("/");
  183. ASSERT_TRUE(res != nullptr);
  184. EXPECT_EQ(302, res->status);
  185. EXPECT_EQ("/hi", res->get_header_value("Location"));
  186. }
  187. TEST_F(ServerTest, GetMethod404)
  188. {
  189. auto res = cli_.get("/invalid");
  190. ASSERT_TRUE(res != nullptr);
  191. EXPECT_EQ(404, res->status);
  192. }
  193. TEST_F(ServerTest, HeadMethod200)
  194. {
  195. auto res = cli_.head("/hi");
  196. ASSERT_TRUE(res != nullptr);
  197. EXPECT_EQ(200, res->status);
  198. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  199. EXPECT_EQ("", res->body);
  200. }
  201. TEST_F(ServerTest, HeadMethod404)
  202. {
  203. auto res = cli_.head("/invalid");
  204. ASSERT_TRUE(res != nullptr);
  205. EXPECT_EQ(404, res->status);
  206. EXPECT_EQ("", res->body);
  207. }
  208. TEST_F(ServerTest, GetMethodPersonJohn)
  209. {
  210. auto res = cli_.get("/person/john");
  211. ASSERT_TRUE(res != nullptr);
  212. EXPECT_EQ(200, res->status);
  213. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  214. EXPECT_EQ("programmer", res->body);
  215. }
  216. TEST_F(ServerTest, PostMethod1)
  217. {
  218. auto res = cli_.get("/person/john1");
  219. ASSERT_TRUE(res != nullptr);
  220. ASSERT_EQ(404, res->status);
  221. res = cli_.post("/person", "name=john1&note=coder", "application/x-www-form-urlencoded");
  222. ASSERT_TRUE(res != nullptr);
  223. ASSERT_EQ(200, res->status);
  224. res = cli_.get("/person/john1");
  225. ASSERT_TRUE(res != nullptr);
  226. ASSERT_EQ(200, res->status);
  227. ASSERT_EQ("text/plain", res->get_header_value("Content-Type"));
  228. ASSERT_EQ("coder", res->body);
  229. }
  230. TEST_F(ServerTest, PostMethod2)
  231. {
  232. auto res = cli_.get("/person/john2");
  233. ASSERT_TRUE(res != nullptr);
  234. ASSERT_EQ(404, res->status);
  235. Map params;
  236. params["name"] = "john2";
  237. params["note"] = "coder";
  238. res = cli_.post("/person", params);
  239. ASSERT_TRUE(res != nullptr);
  240. ASSERT_EQ(200, res->status);
  241. res = cli_.get("/person/john2");
  242. ASSERT_TRUE(res != nullptr);
  243. ASSERT_EQ(200, res->status);
  244. ASSERT_EQ("text/plain", res->get_header_value("Content-Type"));
  245. ASSERT_EQ("coder", res->body);
  246. }
  247. TEST_F(ServerTest, GetMethodDir)
  248. {
  249. auto res = cli_.get("/dir/");
  250. ASSERT_TRUE(res != nullptr);
  251. EXPECT_EQ(200, res->status);
  252. EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
  253. auto body = R"(<html>
  254. <head>
  255. </head>
  256. <body>
  257. <a href="/dir/test.html">Test</a>
  258. <a href="/hi">hi</a>
  259. </body>
  260. </html>
  261. )";
  262. EXPECT_EQ(body, res->body);
  263. }
  264. TEST_F(ServerTest, GetMethodDirTest)
  265. {
  266. auto res = cli_.get("/dir/test.html");
  267. ASSERT_TRUE(res != nullptr);
  268. EXPECT_EQ(200, res->status);
  269. EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
  270. EXPECT_EQ("test.html", res->body);
  271. }
  272. TEST_F(ServerTest, GetMethodDirTestWithDoubleDots)
  273. {
  274. auto res = cli_.get("/dir/../dir/test.html");
  275. ASSERT_TRUE(res != nullptr);
  276. EXPECT_EQ(200, res->status);
  277. EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
  278. EXPECT_EQ("test.html", res->body);
  279. }
  280. TEST_F(ServerTest, GetMethodInvalidPath)
  281. {
  282. auto res = cli_.get("/dir/../test.html");
  283. ASSERT_TRUE(res != nullptr);
  284. EXPECT_EQ(404, res->status);
  285. }
  286. TEST_F(ServerTest, GetMethodOutOfBaseDir)
  287. {
  288. auto res = cli_.get("/../www/dir/test.html");
  289. ASSERT_TRUE(res != nullptr);
  290. EXPECT_EQ(404, res->status);
  291. }
  292. TEST_F(ServerTest, GetMethodOutOfBaseDir2)
  293. {
  294. auto res = cli_.get("/dir/../../www/dir/test.html");
  295. ASSERT_TRUE(res != nullptr);
  296. EXPECT_EQ(404, res->status);
  297. }
  298. TEST_F(ServerTest, InvalidBaseDir)
  299. {
  300. EXPECT_EQ(false, svr_.set_base_dir("invalid_dir"));
  301. EXPECT_EQ(true, svr_.set_base_dir("."));
  302. }
  303. TEST_F(ServerTest, EmptyRequest)
  304. {
  305. auto res = cli_.get("");
  306. ASSERT_TRUE(res != nullptr);
  307. EXPECT_EQ(400, res->status);
  308. }
  309. TEST_F(ServerTest, LongRequest)
  310. {
  311. auto res = cli_.get("/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/__ok__");
  312. ASSERT_TRUE(res != nullptr);
  313. EXPECT_EQ(404, res->status);
  314. }
  315. TEST_F(ServerTest, TooLongRequest)
  316. {
  317. auto res = cli_.get("/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/__ng___");
  318. ASSERT_TRUE(res != nullptr);
  319. EXPECT_EQ(400, res->status);
  320. }
  321. TEST_F(ServerTest, LongHeader)
  322. {
  323. Request req;
  324. req.method = "GET";
  325. req.path = "/hi";
  326. std::string host_and_port;
  327. host_and_port += HOST;
  328. host_and_port += ":";
  329. host_and_port += std::to_string(PORT);
  330. req.set_header("Host", host_and_port.c_str());
  331. req.set_header("Accept", "*/*");
  332. req.set_header("User-Agent", "cpp-httplib/0.1");
  333. req.set_header("Header-Name", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  334. auto res = std::make_shared<Response>();
  335. auto ret = cli_.send(req, *res);
  336. ASSERT_TRUE(ret);
  337. EXPECT_EQ(200, res->status);
  338. }
  339. TEST_F(ServerTest, TooLongHeader)
  340. {
  341. Request req;
  342. req.method = "GET";
  343. req.path = "/hi";
  344. std::string host_and_port;
  345. host_and_port += HOST;
  346. host_and_port += ":";
  347. host_and_port += std::to_string(PORT);
  348. req.set_header("Host", host_and_port.c_str());
  349. req.set_header("Accept", "*/*");
  350. req.set_header("User-Agent", "cpp-httplib/0.1");
  351. req.set_header("Header-Name", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  352. auto res = std::make_shared<Response>();
  353. auto ret = cli_.send(req, *res);
  354. ASSERT_TRUE(ret);
  355. EXPECT_EQ(400, res->status);
  356. }
  357. class ServerTestWithAI_PASSIVE : public ::testing::Test {
  358. protected:
  359. ServerTestWithAI_PASSIVE()
  360. : cli_(HOST, PORT)
  361. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  362. , svr_(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE)
  363. #endif
  364. , up_(false) {}
  365. virtual void SetUp() {
  366. svr_.get("/hi", [&](const Request& /*req*/, Response& res) {
  367. res.set_content("Hello World!", "text/plain");
  368. });
  369. svr_.get("/stop", [&](const Request& /*req*/, Response& /*res*/) {
  370. svr_.stop();
  371. });
  372. f_ = async([&](){
  373. up_ = true;
  374. svr_.listen(nullptr, PORT, AI_PASSIVE);
  375. });
  376. while (!up_) {
  377. msleep(1);
  378. }
  379. }
  380. virtual void TearDown() {
  381. //svr_.stop(); // NOTE: This causes dead lock on Windows.
  382. cli_.get("/stop");
  383. f_.get();
  384. }
  385. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  386. SSLClient cli_;
  387. SSLServer svr_;
  388. #else
  389. Client cli_;
  390. Server svr_;
  391. #endif
  392. future<void> f_;
  393. bool up_;
  394. };
  395. TEST_F(ServerTestWithAI_PASSIVE, GetMethod200)
  396. {
  397. auto res = cli_.get("/hi");
  398. ASSERT_TRUE(res != nullptr);
  399. EXPECT_EQ(200, res->status);
  400. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  401. EXPECT_EQ("Hello World!", res->body);
  402. }
  403. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  404. TEST(SSLClientTest, ServerNameIndication)
  405. {
  406. SSLClient cli("httpbin.org", 443);
  407. auto res = cli.get("/get");
  408. ASSERT_TRUE(res != nullptr);
  409. ASSERT_EQ(200, res->status);
  410. }
  411. #endif
  412. #ifdef _WIN32
  413. TEST(CleanupTest, WSACleanup)
  414. {
  415. int ret = WSACleanup();
  416. ASSERT_EQ(0, ret);
  417. }
  418. #endif
  419. // vim: et ts=4 sw=4 cin cino={1s ff=unix