test.cc 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918
  1. #include <future>
  2. #include <gtest/gtest.h>
  3. #include <httplib.h>
  4. #define SERVER_CERT_FILE "./cert.pem"
  5. #define SERVER_PRIVATE_KEY_FILE "./key.pem"
  6. #define CA_CERT_FILE "./ca-bundle.crt"
  7. #define CLIENT_CA_CERT_FILE "./rootCA.cert.pem"
  8. #define CLIENT_CA_CERT_DIR "."
  9. #define CLIENT_CERT_FILE "./client.cert.pem"
  10. #define CLIENT_PRIVATE_KEY_FILE "./client.key.pem"
  11. #ifdef _WIN32
  12. #include <process.h>
  13. #define msleep(n) ::Sleep(n)
  14. #else
  15. #define msleep(n) ::usleep(n * 1000)
  16. #endif
  17. using namespace std;
  18. using namespace httplib;
  19. const char *HOST = "localhost";
  20. const int PORT = 1234;
  21. const string LONG_QUERY_VALUE = string(25000, '@');
  22. const string LONG_QUERY_URL = "/long-query-value?key=" + LONG_QUERY_VALUE;
  23. const std::string JSON_DATA = "{\"hello\":\"world\"}";
  24. #ifdef _WIN32
  25. TEST(StartupTest, WSAStartup) {
  26. WSADATA wsaData;
  27. int ret = WSAStartup(0x0002, &wsaData);
  28. ASSERT_EQ(0, ret);
  29. }
  30. #endif
  31. TEST(SplitTest, ParseQueryString) {
  32. string s = "key1=val1&key2=val2&key3=val3";
  33. Params dic;
  34. detail::split(s.c_str(), s.c_str() + s.size(), '&',
  35. [&](const char *b, const char *e) {
  36. string key, val;
  37. detail::split(b, e, '=', [&](const char *b, const char *e) {
  38. if (key.empty()) {
  39. key.assign(b, e);
  40. } else {
  41. val.assign(b, e);
  42. }
  43. });
  44. dic.emplace(key, val);
  45. });
  46. EXPECT_EQ("val1", dic.find("key1")->second);
  47. EXPECT_EQ("val2", dic.find("key2")->second);
  48. EXPECT_EQ("val3", dic.find("key3")->second);
  49. }
  50. TEST(ParseQueryTest, ParseQueryString) {
  51. string s = "key1=val1&key2=val2&key3=val3";
  52. Params dic;
  53. detail::parse_query_text(s, dic);
  54. EXPECT_EQ("val1", dic.find("key1")->second);
  55. EXPECT_EQ("val2", dic.find("key2")->second);
  56. EXPECT_EQ("val3", dic.find("key3")->second);
  57. }
  58. TEST(GetHeaderValueTest, DefaultValue) {
  59. Headers headers = {{"Dummy", "Dummy"}};
  60. auto val = detail::get_header_value(headers, "Content-Type", 0, "text/plain");
  61. EXPECT_STREQ("text/plain", val);
  62. }
  63. TEST(GetHeaderValueTest, DefaultValueInt) {
  64. Headers headers = {{"Dummy", "Dummy"}};
  65. auto val = detail::get_header_value_uint64(headers, "Content-Length", 100);
  66. EXPECT_EQ(100ull, val);
  67. }
  68. TEST(GetHeaderValueTest, RegularValue) {
  69. Headers headers = {{"Content-Type", "text/html"}, {"Dummy", "Dummy"}};
  70. auto val = detail::get_header_value(headers, "Content-Type", 0, "text/plain");
  71. EXPECT_STREQ("text/html", val);
  72. }
  73. TEST(GetHeaderValueTest, RegularValueInt) {
  74. Headers headers = {{"Content-Length", "100"}, {"Dummy", "Dummy"}};
  75. auto val = detail::get_header_value_uint64(headers, "Content-Length", 0);
  76. EXPECT_EQ(100ull, val);
  77. }
  78. TEST(GetHeaderValueTest, Range) {
  79. {
  80. Headers headers = {make_range_header({{1, -1}})};
  81. auto val = detail::get_header_value(headers, "Range", 0, 0);
  82. EXPECT_STREQ("bytes=1-", val);
  83. }
  84. {
  85. Headers headers = {make_range_header({{-1, 1}})};
  86. auto val = detail::get_header_value(headers, "Range", 0, 0);
  87. EXPECT_STREQ("bytes=-1", val);
  88. }
  89. {
  90. Headers headers = {make_range_header({{1, 10}})};
  91. auto val = detail::get_header_value(headers, "Range", 0, 0);
  92. EXPECT_STREQ("bytes=1-10", val);
  93. }
  94. {
  95. Headers headers = {make_range_header({{1, 10}, {100, -1}})};
  96. auto val = detail::get_header_value(headers, "Range", 0, 0);
  97. EXPECT_STREQ("bytes=1-10, 100-", val);
  98. }
  99. {
  100. Headers headers = {make_range_header({{1, 10}, {100, 200}})};
  101. auto val = detail::get_header_value(headers, "Range", 0, 0);
  102. EXPECT_STREQ("bytes=1-10, 100-200", val);
  103. }
  104. {
  105. Headers headers = {make_range_header({{0, 0}, {-1, 1}})};
  106. auto val = detail::get_header_value(headers, "Range", 0, 0);
  107. EXPECT_STREQ("bytes=0-0, -1", val);
  108. }
  109. }
  110. TEST(ParseHeaderValueTest, Range) {
  111. {
  112. Ranges ranges;
  113. auto ret = detail::parse_range_header("bytes=1-", ranges);
  114. EXPECT_TRUE(ret);
  115. EXPECT_EQ(1u, ranges.size());
  116. EXPECT_EQ(1u, ranges[0].first);
  117. EXPECT_EQ(-1, ranges[0].second);
  118. }
  119. {
  120. Ranges ranges;
  121. auto ret = detail::parse_range_header("bytes=-1", ranges);
  122. EXPECT_TRUE(ret);
  123. EXPECT_EQ(1u, ranges.size());
  124. EXPECT_EQ(-1, ranges[0].first);
  125. EXPECT_EQ(1u, ranges[0].second);
  126. }
  127. {
  128. Ranges ranges;
  129. auto ret = detail::parse_range_header("bytes=1-10", ranges);
  130. EXPECT_TRUE(ret);
  131. EXPECT_EQ(1u, ranges.size());
  132. EXPECT_EQ(1u, ranges[0].first);
  133. EXPECT_EQ(10u, ranges[0].second);
  134. }
  135. {
  136. Ranges ranges;
  137. auto ret = detail::parse_range_header("bytes=10-1", ranges);
  138. EXPECT_FALSE(ret);
  139. }
  140. {
  141. Ranges ranges;
  142. auto ret = detail::parse_range_header("bytes=1-10, 100-", ranges);
  143. EXPECT_TRUE(ret);
  144. EXPECT_EQ(2u, ranges.size());
  145. EXPECT_EQ(1u, ranges[0].first);
  146. EXPECT_EQ(10u, ranges[0].second);
  147. EXPECT_EQ(100u, ranges[1].first);
  148. EXPECT_EQ(-1, ranges[1].second);
  149. }
  150. {
  151. Ranges ranges;
  152. auto ret =
  153. detail::parse_range_header("bytes=1-10, 100-200, 300-400", ranges);
  154. EXPECT_TRUE(ret);
  155. EXPECT_EQ(3u, ranges.size());
  156. EXPECT_EQ(1u, ranges[0].first);
  157. EXPECT_EQ(10u, ranges[0].second);
  158. EXPECT_EQ(100u, ranges[1].first);
  159. EXPECT_EQ(200u, ranges[1].second);
  160. EXPECT_EQ(300u, ranges[2].first);
  161. EXPECT_EQ(400u, ranges[2].second);
  162. }
  163. }
  164. TEST(ChunkedEncodingTest, FromHTTPWatch) {
  165. auto host = "www.httpwatch.com";
  166. auto sec = 2;
  167. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  168. auto port = 443;
  169. httplib::SSLClient cli(host, port, sec);
  170. #else
  171. auto port = 80;
  172. httplib::Client cli(host, port, sec);
  173. #endif
  174. auto res =
  175. cli.Get("/httpgallery/chunked/chunkedimage.aspx?0.4153841143030137");
  176. ASSERT_TRUE(res != nullptr);
  177. std::string out;
  178. httplib::detail::read_file("./image.jpg", out);
  179. EXPECT_EQ(200, res->status);
  180. EXPECT_EQ(out, res->body);
  181. }
  182. TEST(ChunkedEncodingTest, WithContentReceiver) {
  183. auto host = "www.httpwatch.com";
  184. auto sec = 2;
  185. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  186. auto port = 443;
  187. httplib::SSLClient cli(host, port, sec);
  188. #else
  189. auto port = 80;
  190. httplib::Client cli(host, port, sec);
  191. #endif
  192. std::string body;
  193. auto res =
  194. cli.Get("/httpgallery/chunked/chunkedimage.aspx?0.4153841143030137",
  195. [&](const char *data, size_t data_length) {
  196. body.append(data, data_length);
  197. return true;
  198. });
  199. ASSERT_TRUE(res != nullptr);
  200. std::string out;
  201. httplib::detail::read_file("./image.jpg", out);
  202. EXPECT_EQ(200, res->status);
  203. EXPECT_EQ(out, body);
  204. }
  205. TEST(ChunkedEncodingTest, WithResponseHandlerAndContentReceiver) {
  206. auto host = "www.httpwatch.com";
  207. auto sec = 2;
  208. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  209. auto port = 443;
  210. httplib::SSLClient cli(host, port, sec);
  211. #else
  212. auto port = 80;
  213. httplib::Client cli(host, port, sec);
  214. #endif
  215. std::string body;
  216. auto res = cli.Get(
  217. "/httpgallery/chunked/chunkedimage.aspx?0.4153841143030137", Headers(),
  218. [&](const Response &response) {
  219. EXPECT_EQ(200, response.status);
  220. return true;
  221. },
  222. [&](const char *data, size_t data_length) {
  223. body.append(data, data_length);
  224. return true;
  225. });
  226. ASSERT_TRUE(res != nullptr);
  227. std::string out;
  228. httplib::detail::read_file("./image.jpg", out);
  229. EXPECT_EQ(200, res->status);
  230. EXPECT_EQ(out, body);
  231. }
  232. TEST(RangeTest, FromHTTPBin) {
  233. auto host = "httpbin.org";
  234. auto sec = 5;
  235. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  236. auto port = 443;
  237. httplib::SSLClient cli(host, port, sec);
  238. #else
  239. auto port = 80;
  240. httplib::Client cli(host, port, sec);
  241. #endif
  242. {
  243. httplib::Headers headers;
  244. auto res = cli.Get("/range/32", headers);
  245. ASSERT_TRUE(res != nullptr);
  246. EXPECT_EQ(res->body, "abcdefghijklmnopqrstuvwxyzabcdef");
  247. EXPECT_EQ(200, res->status);
  248. }
  249. {
  250. httplib::Headers headers = {httplib::make_range_header({{1, -1}})};
  251. auto res = cli.Get("/range/32", headers);
  252. ASSERT_TRUE(res != nullptr);
  253. EXPECT_EQ(res->body, "bcdefghijklmnopqrstuvwxyzabcdef");
  254. EXPECT_EQ(206, res->status);
  255. }
  256. {
  257. httplib::Headers headers = {httplib::make_range_header({{1, 10}})};
  258. auto res = cli.Get("/range/32", headers);
  259. ASSERT_TRUE(res != nullptr);
  260. EXPECT_EQ(res->body, "bcdefghijk");
  261. EXPECT_EQ(206, res->status);
  262. }
  263. {
  264. httplib::Headers headers = {httplib::make_range_header({{0, 31}})};
  265. auto res = cli.Get("/range/32", headers);
  266. ASSERT_TRUE(res != nullptr);
  267. EXPECT_EQ(res->body, "abcdefghijklmnopqrstuvwxyzabcdef");
  268. EXPECT_EQ(200, res->status);
  269. }
  270. {
  271. httplib::Headers headers = {httplib::make_range_header({{0, -1}})};
  272. auto res = cli.Get("/range/32", headers);
  273. ASSERT_TRUE(res != nullptr);
  274. EXPECT_EQ(res->body, "abcdefghijklmnopqrstuvwxyzabcdef");
  275. EXPECT_EQ(200, res->status);
  276. }
  277. {
  278. httplib::Headers headers = {httplib::make_range_header({{0, 32}})};
  279. auto res = cli.Get("/range/32", headers);
  280. ASSERT_TRUE(res != nullptr);
  281. EXPECT_EQ(416, res->status);
  282. }
  283. }
  284. TEST(ConnectionErrorTest, InvalidHost) {
  285. auto host = "-abcde.com";
  286. auto sec = 2;
  287. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  288. auto port = 443;
  289. httplib::SSLClient cli(host, port, sec);
  290. #else
  291. auto port = 80;
  292. httplib::Client cli(host, port, sec);
  293. #endif
  294. auto res = cli.Get("/");
  295. ASSERT_TRUE(res == nullptr);
  296. }
  297. TEST(ConnectionErrorTest, InvalidPort) {
  298. auto host = "localhost";
  299. auto sec = 2;
  300. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  301. auto port = 44380;
  302. httplib::SSLClient cli(host, port, sec);
  303. #else
  304. auto port = 8080;
  305. httplib::Client cli(host, port, sec);
  306. #endif
  307. auto res = cli.Get("/");
  308. ASSERT_TRUE(res == nullptr);
  309. }
  310. TEST(ConnectionErrorTest, Timeout) {
  311. auto host = "google.com";
  312. auto sec = 2;
  313. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  314. auto port = 44380;
  315. httplib::SSLClient cli(host, port, sec);
  316. #else
  317. auto port = 8080;
  318. httplib::Client cli(host, port, sec);
  319. #endif
  320. auto res = cli.Get("/");
  321. ASSERT_TRUE(res == nullptr);
  322. }
  323. TEST(CancelTest, NoCancel) {
  324. auto host = "httpbin.org";
  325. auto sec = 5;
  326. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  327. auto port = 443;
  328. httplib::SSLClient cli(host, port, sec);
  329. #else
  330. auto port = 80;
  331. httplib::Client cli(host, port, sec);
  332. #endif
  333. auto res = cli.Get("/range/32", [](uint64_t, uint64_t) { return true; });
  334. ASSERT_TRUE(res != nullptr);
  335. EXPECT_EQ(res->body, "abcdefghijklmnopqrstuvwxyzabcdef");
  336. EXPECT_EQ(200, res->status);
  337. }
  338. TEST(CancelTest, WithCancelSmallPayload) {
  339. auto host = "httpbin.org";
  340. auto sec = 5;
  341. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  342. auto port = 443;
  343. httplib::SSLClient cli(host, port, sec);
  344. #else
  345. auto port = 80;
  346. httplib::Client cli(host, port, sec);
  347. #endif
  348. auto res = cli.Get("/range/32", [](uint64_t, uint64_t) { return false; });
  349. ASSERT_TRUE(res == nullptr);
  350. }
  351. TEST(CancelTest, WithCancelLargePayload) {
  352. auto host = "httpbin.org";
  353. auto sec = 5;
  354. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  355. auto port = 443;
  356. httplib::SSLClient cli(host, port, sec);
  357. #else
  358. auto port = 80;
  359. httplib::Client cli(host, port, sec);
  360. #endif
  361. uint32_t count = 0;
  362. httplib::Headers headers;
  363. auto res = cli.Get("/range/65536", headers,
  364. [&count](uint64_t, uint64_t) { return (count++ == 0); });
  365. ASSERT_TRUE(res == nullptr);
  366. }
  367. TEST(BaseAuthTest, FromHTTPWatch) {
  368. auto host = "httpbin.org";
  369. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  370. auto port = 443;
  371. httplib::SSLClient cli(host, port);
  372. #else
  373. auto port = 80;
  374. httplib::Client cli(host, port);
  375. #endif
  376. {
  377. auto res = cli.Get("/basic-auth/hello/world");
  378. ASSERT_TRUE(res != nullptr);
  379. EXPECT_EQ(401, res->status);
  380. }
  381. {
  382. auto res =
  383. cli.Get("/basic-auth/hello/world",
  384. {httplib::make_basic_authentication_header("hello", "world")});
  385. ASSERT_TRUE(res != nullptr);
  386. EXPECT_EQ(res->body,
  387. "{\n \"authenticated\": true, \n \"user\": \"hello\"\n}\n");
  388. EXPECT_EQ(200, res->status);
  389. }
  390. }
  391. TEST(AbsoluteRedirectTest, Redirect) {
  392. auto host = "httpbin.org";
  393. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  394. httplib::SSLClient cli(host);
  395. #else
  396. httplib::Client cli(host);
  397. #endif
  398. cli.follow_location(true);
  399. auto res = cli.Get("/absolute-redirect/3");
  400. ASSERT_TRUE(res != nullptr);
  401. EXPECT_EQ(200, res->status);
  402. }
  403. TEST(RedirectTest, Redirect) {
  404. auto host = "httpbin.org";
  405. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  406. httplib::SSLClient cli(host);
  407. #else
  408. httplib::Client cli(host);
  409. #endif
  410. cli.follow_location(true);
  411. auto res = cli.Get("/redirect/3");
  412. ASSERT_TRUE(res != nullptr);
  413. EXPECT_EQ(200, res->status);
  414. }
  415. TEST(RelativeRedirectTest, Redirect) {
  416. auto host = "httpbin.org";
  417. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  418. httplib::SSLClient cli(host);
  419. #else
  420. httplib::Client cli(host);
  421. #endif
  422. cli.follow_location(true);
  423. auto res = cli.Get("/relative-redirect/3");
  424. ASSERT_TRUE(res != nullptr);
  425. EXPECT_EQ(200, res->status);
  426. }
  427. TEST(TooManyRedirectTest, Redirect) {
  428. auto host = "httpbin.org";
  429. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  430. httplib::SSLClient cli(host);
  431. #else
  432. httplib::Client cli(host);
  433. #endif
  434. cli.follow_location(true);
  435. auto res = cli.Get("/redirect/21");
  436. ASSERT_TRUE(res == nullptr);
  437. }
  438. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  439. TEST(YahooRedirectTest, Redirect) {
  440. httplib::Client cli("yahoo.com");
  441. auto res = cli.Get("/");
  442. ASSERT_TRUE(res != nullptr);
  443. EXPECT_EQ(301, res->status);
  444. cli.follow_location(true);
  445. res = cli.Get("/");
  446. ASSERT_TRUE(res != nullptr);
  447. EXPECT_EQ(200, res->status);
  448. }
  449. TEST(HttpsToHttpRedirectTest, Redirect) {
  450. httplib::SSLClient cli("httpbin.org");
  451. cli.follow_location(true);
  452. auto res =
  453. cli.Get("/redirect-to?url=http%3A%2F%2Fwww.google.com&status_code=302");
  454. ASSERT_TRUE(res != nullptr);
  455. }
  456. #endif
  457. TEST(Server, BindAndListenSeparately) {
  458. Server svr;
  459. int port = svr.bind_to_any_port("localhost");
  460. ASSERT_TRUE(port > 0);
  461. svr.stop();
  462. }
  463. class ServerTest : public ::testing::Test {
  464. protected:
  465. ServerTest()
  466. : cli_(HOST, PORT)
  467. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  468. ,
  469. svr_(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE)
  470. #endif
  471. {
  472. }
  473. virtual void SetUp() {
  474. svr_.set_base_dir("./www");
  475. svr_.Get("/hi",
  476. [&](const Request & /*req*/, Response &res) {
  477. res.set_content("Hello World!", "text/plain");
  478. })
  479. .Get("/slow",
  480. [&](const Request & /*req*/, Response &res) {
  481. msleep(2000);
  482. res.set_content("slow", "text/plain");
  483. })
  484. .Get("/remote_addr",
  485. [&](const Request &req, Response &res) {
  486. auto remote_addr = req.headers.find("REMOTE_ADDR")->second;
  487. res.set_content(remote_addr.c_str(), "text/plain");
  488. })
  489. .Get("/endwith%",
  490. [&](const Request & /*req*/, Response &res) {
  491. res.set_content("Hello World!", "text/plain");
  492. })
  493. .Get("/", [&](const Request & /*req*/,
  494. Response &res) { res.set_redirect("/hi"); })
  495. .Post("/person",
  496. [&](const Request &req, Response &res) {
  497. if (req.has_param("name") && req.has_param("note")) {
  498. persons_[req.get_param_value("name")] =
  499. req.get_param_value("note");
  500. } else {
  501. res.status = 400;
  502. }
  503. })
  504. .Get("/person/(.*)",
  505. [&](const Request &req, Response &res) {
  506. string name = req.matches[1];
  507. if (persons_.find(name) != persons_.end()) {
  508. auto note = persons_[name];
  509. res.set_content(note, "text/plain");
  510. } else {
  511. res.status = 404;
  512. }
  513. })
  514. .Post("/x-www-form-urlencoded-json",
  515. [&](const Request &req, Response &res) {
  516. auto json = req.get_param_value("json");
  517. ASSERT_EQ(JSON_DATA, json);
  518. res.set_content(json, "appliation/json");
  519. res.status = 200;
  520. })
  521. .Get("/streamed-chunked",
  522. [&](const Request & /*req*/, Response &res) {
  523. res.set_chunked_content_provider(
  524. [](uint64_t /*offset*/, DataSink sink, Done done) {
  525. sink("123", 3);
  526. sink("456", 3);
  527. sink("789", 3);
  528. done();
  529. });
  530. })
  531. .Get("/streamed",
  532. [&](const Request & /*req*/, Response &res) {
  533. res.set_content_provider(
  534. 6, [](uint64_t offset, uint64_t /*length*/, DataSink sink) {
  535. sink(offset < 3 ? "a" : "b", 1);
  536. });
  537. })
  538. .Get("/streamed-with-range",
  539. [&](const Request & /*req*/, Response &res) {
  540. auto data = new std::string("abcdefg");
  541. res.set_content_provider(
  542. data->size(),
  543. [data](uint64_t offset, uint64_t length, DataSink sink) {
  544. size_t DATA_CHUNK_SIZE = 4;
  545. const auto &d = *data;
  546. auto out_len =
  547. std::min(static_cast<size_t>(length), DATA_CHUNK_SIZE);
  548. sink(&d[static_cast<size_t>(offset)], out_len);
  549. },
  550. [data] { delete data; });
  551. })
  552. .Get("/streamed-cancel",
  553. [&](const Request & /*req*/, Response &res) {
  554. res.set_content_provider(
  555. size_t(-1),
  556. [](uint64_t /*offset*/, uint64_t /*length*/, DataSink sink) {
  557. std::string data = "data_chunk";
  558. sink(data.data(), data.size());
  559. });
  560. })
  561. .Get("/with-range",
  562. [&](const Request & /*req*/, Response &res) {
  563. res.set_content("abcdefg", "text/plain");
  564. })
  565. .Post("/chunked",
  566. [&](const Request &req, Response & /*res*/) {
  567. EXPECT_EQ(req.body, "dechunked post body");
  568. })
  569. .Post("/large-chunked",
  570. [&](const Request &req, Response & /*res*/) {
  571. std::string expected(6 * 30 * 1024u, 'a');
  572. EXPECT_EQ(req.body, expected);
  573. })
  574. .Post("/multipart",
  575. [&](const Request &req, Response & /*res*/) {
  576. EXPECT_EQ(5u, req.files.size());
  577. ASSERT_TRUE(!req.has_file("???"));
  578. {
  579. const auto &file = req.get_file_value("text1");
  580. EXPECT_EQ("", file.filename);
  581. EXPECT_EQ("text default",
  582. req.body.substr(file.offset, file.length));
  583. }
  584. {
  585. const auto &file = req.get_file_value("text2");
  586. EXPECT_EQ("", file.filename);
  587. EXPECT_EQ("aωb", req.body.substr(file.offset, file.length));
  588. }
  589. {
  590. const auto &file = req.get_file_value("file1");
  591. EXPECT_EQ("hello.txt", file.filename);
  592. EXPECT_EQ("text/plain", file.content_type);
  593. EXPECT_EQ("h\ne\n\nl\nl\no\n",
  594. req.body.substr(file.offset, file.length));
  595. }
  596. {
  597. const auto &file = req.get_file_value("file3");
  598. EXPECT_EQ("", file.filename);
  599. EXPECT_EQ("application/octet-stream", file.content_type);
  600. EXPECT_EQ(0u, file.length);
  601. }
  602. })
  603. .Post("/empty",
  604. [&](const Request &req, Response &res) {
  605. EXPECT_EQ(req.body, "");
  606. res.set_content("empty", "text/plain");
  607. })
  608. .Put("/put",
  609. [&](const Request &req, Response &res) {
  610. EXPECT_EQ(req.body, "PUT");
  611. res.set_content(req.body, "text/plain");
  612. })
  613. .Patch("/patch",
  614. [&](const Request &req, Response &res) {
  615. EXPECT_EQ(req.body, "PATCH");
  616. res.set_content(req.body, "text/plain");
  617. })
  618. .Delete("/delete",
  619. [&](const Request & /*req*/, Response &res) {
  620. res.set_content("DELETE", "text/plain");
  621. })
  622. .Options(R"(\*)",
  623. [&](const Request & /*req*/, Response &res) {
  624. res.set_header("Allow", "GET, POST, HEAD, OPTIONS");
  625. })
  626. .Get("/request-target",
  627. [&](const Request &req, Response & /*res*/) {
  628. EXPECT_EQ("/request-target?aaa=bbb&ccc=ddd", req.target);
  629. EXPECT_EQ("bbb", req.get_param_value("aaa"));
  630. EXPECT_EQ("ddd", req.get_param_value("ccc"));
  631. })
  632. .Get("/long-query-value",
  633. [&](const Request &req, Response & /*res*/) {
  634. EXPECT_EQ(LONG_QUERY_URL, req.target);
  635. EXPECT_EQ(LONG_QUERY_VALUE, req.get_param_value("key"));
  636. })
  637. .Get("/array-param",
  638. [&](const Request &req, Response & /*res*/) {
  639. EXPECT_EQ(3u, req.get_param_value_count("array"));
  640. EXPECT_EQ("value1", req.get_param_value("array", 0));
  641. EXPECT_EQ("value2", req.get_param_value("array", 1));
  642. EXPECT_EQ("value3", req.get_param_value("array", 2));
  643. })
  644. .Post("/validate-no-multiple-headers",
  645. [&](const Request &req, Response & /*res*/) {
  646. EXPECT_EQ(1u, req.get_header_value_count("Content-Length"));
  647. EXPECT_EQ("5", req.get_header_value("Content-Length"));
  648. })
  649. .Post("/content_receiver",
  650. [&](const Request & /*req*/, Response &res,
  651. const ContentReader &content_reader) {
  652. std::string body;
  653. content_reader([&](const char *data, size_t data_length) {
  654. EXPECT_EQ(data_length, 7);
  655. body.append(data, data_length);
  656. return true;
  657. });
  658. EXPECT_EQ(body, "content");
  659. res.set_content(body, "text/plain");
  660. })
  661. .Put("/content_receiver",
  662. [&](const Request & /*req*/, Response &res,
  663. const ContentReader &content_reader) {
  664. std::string body;
  665. content_reader([&](const char *data, size_t data_length) {
  666. body.append(data, data_length);
  667. return true;
  668. });
  669. EXPECT_EQ(body, "content");
  670. res.set_content(body, "text/plain");
  671. })
  672. .Patch("/content_receiver",
  673. [&](const Request & /*req*/, Response &res,
  674. const ContentReader &content_reader) {
  675. std::string body;
  676. content_reader([&](const char *data, size_t data_length) {
  677. body.append(data, data_length);
  678. return true;
  679. });
  680. EXPECT_EQ(body, "content");
  681. res.set_content(body, "text/plain");
  682. })
  683. #ifdef CPPHTTPLIB_ZLIB_SUPPORT
  684. .Get("/gzip",
  685. [&](const Request & /*req*/, Response &res) {
  686. res.set_content(
  687. "12345678901234567890123456789012345678901234567890123456789"
  688. "01234567890123456789012345678901234567890",
  689. "text/plain");
  690. })
  691. .Get("/nogzip",
  692. [&](const Request & /*req*/, Response &res) {
  693. res.set_content(
  694. "12345678901234567890123456789012345678901234567890123456789"
  695. "01234567890123456789012345678901234567890",
  696. "application/octet-stream");
  697. })
  698. .Post("/gzipmultipart",
  699. [&](const Request &req, Response & /*res*/) {
  700. EXPECT_EQ(2u, req.files.size());
  701. ASSERT_TRUE(!req.has_file("???"));
  702. {
  703. const auto &file = req.get_file_value("key1");
  704. EXPECT_EQ("", file.filename);
  705. EXPECT_EQ("test", req.body.substr(file.offset, file.length));
  706. }
  707. {
  708. const auto &file = req.get_file_value("key2");
  709. EXPECT_EQ("", file.filename);
  710. EXPECT_EQ("--abcdefg123",
  711. req.body.substr(file.offset, file.length));
  712. }
  713. })
  714. #endif
  715. ;
  716. persons_["john"] = "programmer";
  717. t_ = thread([&]() { ASSERT_TRUE(svr_.listen(HOST, PORT)); });
  718. while (!svr_.is_running()) {
  719. msleep(1);
  720. }
  721. }
  722. virtual void TearDown() {
  723. svr_.stop();
  724. for (auto &t : request_threads_) {
  725. t.join();
  726. }
  727. t_.join();
  728. }
  729. map<string, string> persons_;
  730. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  731. SSLClient cli_;
  732. SSLServer svr_;
  733. #else
  734. Client cli_;
  735. Server svr_;
  736. #endif
  737. thread t_;
  738. std::vector<thread> request_threads_;
  739. };
  740. TEST_F(ServerTest, GetMethod200) {
  741. auto res = cli_.Get("/hi");
  742. ASSERT_TRUE(res != nullptr);
  743. EXPECT_EQ("HTTP/1.1", res->version);
  744. EXPECT_EQ(200, res->status);
  745. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  746. EXPECT_EQ(1, res->get_header_value_count("Content-Type"));
  747. EXPECT_EQ("Hello World!", res->body);
  748. }
  749. TEST_F(ServerTest, GetMethod302) {
  750. auto res = cli_.Get("/");
  751. ASSERT_TRUE(res != nullptr);
  752. EXPECT_EQ(302, res->status);
  753. EXPECT_EQ("/hi", res->get_header_value("Location"));
  754. }
  755. TEST_F(ServerTest, GetMethod404) {
  756. auto res = cli_.Get("/invalid");
  757. ASSERT_TRUE(res != nullptr);
  758. EXPECT_EQ(404, res->status);
  759. }
  760. TEST_F(ServerTest, HeadMethod200) {
  761. auto res = cli_.Head("/hi");
  762. ASSERT_TRUE(res != nullptr);
  763. EXPECT_EQ(200, res->status);
  764. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  765. EXPECT_EQ("", res->body);
  766. }
  767. TEST_F(ServerTest, HeadMethod404) {
  768. auto res = cli_.Head("/invalid");
  769. ASSERT_TRUE(res != nullptr);
  770. EXPECT_EQ(404, res->status);
  771. EXPECT_EQ("", res->body);
  772. }
  773. TEST_F(ServerTest, GetMethodPersonJohn) {
  774. auto res = cli_.Get("/person/john");
  775. ASSERT_TRUE(res != nullptr);
  776. EXPECT_EQ(200, res->status);
  777. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  778. EXPECT_EQ("programmer", res->body);
  779. }
  780. TEST_F(ServerTest, PostMethod1) {
  781. auto res = cli_.Get("/person/john1");
  782. ASSERT_TRUE(res != nullptr);
  783. ASSERT_EQ(404, res->status);
  784. res = cli_.Post("/person", "name=john1&note=coder",
  785. "application/x-www-form-urlencoded");
  786. ASSERT_TRUE(res != nullptr);
  787. ASSERT_EQ(200, res->status);
  788. res = cli_.Get("/person/john1");
  789. ASSERT_TRUE(res != nullptr);
  790. ASSERT_EQ(200, res->status);
  791. ASSERT_EQ("text/plain", res->get_header_value("Content-Type"));
  792. ASSERT_EQ("coder", res->body);
  793. }
  794. TEST_F(ServerTest, PostMethod2) {
  795. auto res = cli_.Get("/person/john2");
  796. ASSERT_TRUE(res != nullptr);
  797. ASSERT_EQ(404, res->status);
  798. Params params;
  799. params.emplace("name", "john2");
  800. params.emplace("note", "coder");
  801. res = cli_.Post("/person", params);
  802. ASSERT_TRUE(res != nullptr);
  803. ASSERT_EQ(200, res->status);
  804. res = cli_.Get("/person/john2");
  805. ASSERT_TRUE(res != nullptr);
  806. ASSERT_EQ(200, res->status);
  807. ASSERT_EQ("text/plain", res->get_header_value("Content-Type"));
  808. ASSERT_EQ("coder", res->body);
  809. }
  810. TEST_F(ServerTest, PostWwwFormUrlEncodedJson) {
  811. Params params;
  812. params.emplace("json", JSON_DATA);
  813. auto res = cli_.Post("/x-www-form-urlencoded-json", params);
  814. ASSERT_TRUE(res != nullptr);
  815. ASSERT_EQ(200, res->status);
  816. ASSERT_EQ(JSON_DATA, res->body);
  817. }
  818. TEST_F(ServerTest, PostEmptyContent) {
  819. auto res = cli_.Post("/empty", "", "text/plain");
  820. ASSERT_TRUE(res != nullptr);
  821. ASSERT_EQ(200, res->status);
  822. ASSERT_EQ("empty", res->body);
  823. }
  824. TEST_F(ServerTest, GetMethodDir) {
  825. auto res = cli_.Get("/dir/");
  826. ASSERT_TRUE(res != nullptr);
  827. EXPECT_EQ(200, res->status);
  828. EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
  829. auto body = R"(<html>
  830. <head>
  831. </head>
  832. <body>
  833. <a href="/dir/test.html">Test</a>
  834. <a href="/hi">hi</a>
  835. </body>
  836. </html>
  837. )";
  838. EXPECT_EQ(body, res->body);
  839. }
  840. TEST_F(ServerTest, GetMethodDirTest) {
  841. auto res = cli_.Get("/dir/test.html");
  842. ASSERT_TRUE(res != nullptr);
  843. EXPECT_EQ(200, res->status);
  844. EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
  845. EXPECT_EQ("test.html", res->body);
  846. }
  847. TEST_F(ServerTest, GetMethodDirTestWithDoubleDots) {
  848. auto res = cli_.Get("/dir/../dir/test.html");
  849. ASSERT_TRUE(res != nullptr);
  850. EXPECT_EQ(200, res->status);
  851. EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
  852. EXPECT_EQ("test.html", res->body);
  853. }
  854. TEST_F(ServerTest, GetMethodInvalidPath) {
  855. auto res = cli_.Get("/dir/../test.html");
  856. ASSERT_TRUE(res != nullptr);
  857. EXPECT_EQ(404, res->status);
  858. }
  859. TEST_F(ServerTest, GetMethodOutOfBaseDir) {
  860. auto res = cli_.Get("/../www/dir/test.html");
  861. ASSERT_TRUE(res != nullptr);
  862. EXPECT_EQ(404, res->status);
  863. }
  864. TEST_F(ServerTest, GetMethodOutOfBaseDir2) {
  865. auto res = cli_.Get("/dir/../../www/dir/test.html");
  866. ASSERT_TRUE(res != nullptr);
  867. EXPECT_EQ(404, res->status);
  868. }
  869. TEST_F(ServerTest, InvalidBaseDir) {
  870. EXPECT_EQ(false, svr_.set_base_dir("invalid_dir"));
  871. EXPECT_EQ(true, svr_.set_base_dir("."));
  872. }
  873. TEST_F(ServerTest, EmptyRequest) {
  874. auto res = cli_.Get("");
  875. ASSERT_TRUE(res == nullptr);
  876. }
  877. TEST_F(ServerTest, LongRequest) {
  878. std::string request;
  879. for (size_t i = 0; i < 545; i++) {
  880. request += "/TooLongRequest";
  881. }
  882. request += "OK";
  883. auto res = cli_.Get(request.c_str());
  884. ASSERT_TRUE(res != nullptr);
  885. EXPECT_EQ(404, res->status);
  886. }
  887. TEST_F(ServerTest, TooLongRequest) {
  888. std::string request;
  889. for (size_t i = 0; i < 545; i++) {
  890. request += "/TooLongRequest";
  891. }
  892. request += "_NG";
  893. auto res = cli_.Get(request.c_str());
  894. ASSERT_TRUE(res != nullptr);
  895. EXPECT_EQ(414, res->status);
  896. }
  897. TEST_F(ServerTest, LongHeader) {
  898. Request req;
  899. req.method = "GET";
  900. req.path = "/hi";
  901. std::string host_and_port;
  902. host_and_port += HOST;
  903. host_and_port += ":";
  904. host_and_port += std::to_string(PORT);
  905. req.headers.emplace("Host", host_and_port.c_str());
  906. req.headers.emplace("Accept", "*/*");
  907. req.headers.emplace("User-Agent", "cpp-httplib/0.1");
  908. req.headers.emplace(
  909. "Header-Name",
  910. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  911. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  912. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  913. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  914. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  915. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  916. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  917. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  918. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  919. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  920. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  921. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  922. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  923. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  924. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  925. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  926. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  927. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  928. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  929. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  930. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  931. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  932. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  933. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  934. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  935. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  936. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  937. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  938. "@@@@@@@@@@@@@@@@");
  939. auto res = std::make_shared<Response>();
  940. auto ret = cli_.send(req, *res);
  941. ASSERT_TRUE(ret);
  942. EXPECT_EQ(200, res->status);
  943. }
  944. TEST_F(ServerTest, LongQueryValue) {
  945. auto res = cli_.Get(LONG_QUERY_URL.c_str());
  946. ASSERT_TRUE(res != nullptr);
  947. EXPECT_EQ(414, res->status);
  948. }
  949. TEST_F(ServerTest, TooLongHeader) {
  950. Request req;
  951. req.method = "GET";
  952. req.path = "/hi";
  953. std::string host_and_port;
  954. host_and_port += HOST;
  955. host_and_port += ":";
  956. host_and_port += std::to_string(PORT);
  957. req.headers.emplace("Host", host_and_port.c_str());
  958. req.headers.emplace("Accept", "*/*");
  959. req.headers.emplace("User-Agent", "cpp-httplib/0.1");
  960. req.headers.emplace(
  961. "Header-Name",
  962. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  963. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  964. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  965. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  966. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  967. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  968. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  969. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  970. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  971. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  972. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  973. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  974. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  975. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  976. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  977. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  978. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  979. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  980. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  981. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  982. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  983. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  984. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  985. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  986. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  987. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  988. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  989. "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
  990. "@@@@@@@@@@@@@@@@@");
  991. auto res = std::make_shared<Response>();
  992. auto ret = cli_.send(req, *res);
  993. ASSERT_TRUE(ret);
  994. EXPECT_EQ(200, res->status);
  995. }
  996. TEST_F(ServerTest, PercentEncoding) {
  997. auto res = cli_.Get("/e%6edwith%");
  998. ASSERT_TRUE(res != nullptr);
  999. EXPECT_EQ(200, res->status);
  1000. }
  1001. TEST_F(ServerTest, PercentEncodingUnicode) {
  1002. auto res = cli_.Get("/e%u006edwith%");
  1003. ASSERT_TRUE(res != nullptr);
  1004. EXPECT_EQ(200, res->status);
  1005. }
  1006. TEST_F(ServerTest, InvalidPercentEncoding) {
  1007. auto res = cli_.Get("/%endwith%");
  1008. ASSERT_TRUE(res != nullptr);
  1009. EXPECT_EQ(404, res->status);
  1010. }
  1011. TEST_F(ServerTest, InvalidPercentEncodingUnicode) {
  1012. auto res = cli_.Get("/%uendwith%");
  1013. ASSERT_TRUE(res != nullptr);
  1014. EXPECT_EQ(404, res->status);
  1015. }
  1016. TEST_F(ServerTest, EndWithPercentCharacterInQuery) {
  1017. auto res = cli_.Get("/hello?aaa=bbb%");
  1018. ASSERT_TRUE(res != nullptr);
  1019. EXPECT_EQ(404, res->status);
  1020. }
  1021. TEST_F(ServerTest, MultipartFormData) {
  1022. MultipartFormDataItems items = {
  1023. {"text1", "text default", "", ""},
  1024. {"text2", "aωb", "", ""},
  1025. {"file1", "h\ne\n\nl\nl\no\n", "hello.txt", "text/plain"},
  1026. {"file2", "{\n \"world\", true\n}\n", "world.json", "application/json"},
  1027. {"file3", "", "", "application/octet-stream"},
  1028. };
  1029. auto res = cli_.Post("/multipart", items);
  1030. ASSERT_TRUE(res != nullptr);
  1031. EXPECT_EQ(200, res->status);
  1032. }
  1033. TEST_F(ServerTest, CaseInsensitiveHeaderName) {
  1034. auto res = cli_.Get("/hi");
  1035. ASSERT_TRUE(res != nullptr);
  1036. EXPECT_EQ(200, res->status);
  1037. EXPECT_EQ("text/plain", res->get_header_value("content-type"));
  1038. EXPECT_EQ("Hello World!", res->body);
  1039. }
  1040. TEST_F(ServerTest, CaseInsensitiveTransferEncoding) {
  1041. Request req;
  1042. req.method = "POST";
  1043. req.path = "/chunked";
  1044. std::string host_and_port;
  1045. host_and_port += HOST;
  1046. host_and_port += ":";
  1047. host_and_port += std::to_string(PORT);
  1048. req.headers.emplace("Host", host_and_port.c_str());
  1049. req.headers.emplace("Accept", "*/*");
  1050. req.headers.emplace("User-Agent", "cpp-httplib/0.1");
  1051. req.headers.emplace("Content-Type", "text/plain");
  1052. req.headers.emplace("Content-Length", "0");
  1053. req.headers.emplace(
  1054. "Transfer-Encoding",
  1055. "Chunked"); // Note, "Chunked" rather than typical "chunked".
  1056. // Client does not chunk, so make a chunked body manually.
  1057. req.body = "4\r\ndech\r\nf\r\nunked post body\r\n0\r\n\r\n";
  1058. auto res = std::make_shared<Response>();
  1059. auto ret = cli_.send(req, *res);
  1060. ASSERT_TRUE(ret);
  1061. EXPECT_EQ(200, res->status);
  1062. }
  1063. TEST_F(ServerTest, GetStreamed2) {
  1064. auto res = cli_.Get("/streamed", {{make_range_header({{2, 3}})}});
  1065. ASSERT_TRUE(res != nullptr);
  1066. EXPECT_EQ(206, res->status);
  1067. EXPECT_EQ("2", res->get_header_value("Content-Length"));
  1068. EXPECT_EQ(std::string("ab"), res->body);
  1069. }
  1070. TEST_F(ServerTest, GetStreamed) {
  1071. auto res = cli_.Get("/streamed");
  1072. ASSERT_TRUE(res != nullptr);
  1073. EXPECT_EQ(200, res->status);
  1074. EXPECT_EQ("6", res->get_header_value("Content-Length"));
  1075. EXPECT_EQ(std::string("aaabbb"), res->body);
  1076. }
  1077. TEST_F(ServerTest, GetStreamedWithRange1) {
  1078. auto res = cli_.Get("/streamed-with-range", {{make_range_header({{3, 5}})}});
  1079. ASSERT_TRUE(res != nullptr);
  1080. EXPECT_EQ(206, res->status);
  1081. EXPECT_EQ("3", res->get_header_value("Content-Length"));
  1082. EXPECT_EQ(true, res->has_header("Content-Range"));
  1083. EXPECT_EQ(std::string("def"), res->body);
  1084. }
  1085. TEST_F(ServerTest, GetStreamedWithRange2) {
  1086. auto res = cli_.Get("/streamed-with-range", {{make_range_header({{1, -1}})}});
  1087. ASSERT_TRUE(res != nullptr);
  1088. EXPECT_EQ(206, res->status);
  1089. EXPECT_EQ("6", res->get_header_value("Content-Length"));
  1090. EXPECT_EQ(true, res->has_header("Content-Range"));
  1091. EXPECT_EQ(std::string("bcdefg"), res->body);
  1092. }
  1093. TEST_F(ServerTest, GetStreamedWithRangeMultipart) {
  1094. auto res =
  1095. cli_.Get("/streamed-with-range", {{make_range_header({{1, 2}, {4, 5}})}});
  1096. ASSERT_TRUE(res != nullptr);
  1097. EXPECT_EQ(206, res->status);
  1098. EXPECT_EQ("269", res->get_header_value("Content-Length"));
  1099. EXPECT_EQ(false, res->has_header("Content-Range"));
  1100. EXPECT_EQ(269, res->body.size());
  1101. }
  1102. TEST_F(ServerTest, GetStreamedEndless) {
  1103. size_t offset = 0;
  1104. auto res = cli_.Get("/streamed-cancel",
  1105. [&](const char * /*data*/, uint64_t data_length) {
  1106. if (offset < 100) {
  1107. offset += data_length;
  1108. return true;
  1109. }
  1110. return false;
  1111. });
  1112. ASSERT_TRUE(res == nullptr);
  1113. }
  1114. TEST_F(ServerTest, GetWithRange1) {
  1115. auto res = cli_.Get("/with-range", {{make_range_header({{3, 5}})}});
  1116. ASSERT_TRUE(res != nullptr);
  1117. EXPECT_EQ(206, res->status);
  1118. EXPECT_EQ("3", res->get_header_value("Content-Length"));
  1119. EXPECT_EQ(true, res->has_header("Content-Range"));
  1120. EXPECT_EQ(std::string("def"), res->body);
  1121. }
  1122. TEST_F(ServerTest, GetWithRange2) {
  1123. auto res = cli_.Get("/with-range", {{make_range_header({{1, -1}})}});
  1124. ASSERT_TRUE(res != nullptr);
  1125. EXPECT_EQ(206, res->status);
  1126. EXPECT_EQ("6", res->get_header_value("Content-Length"));
  1127. EXPECT_EQ(true, res->has_header("Content-Range"));
  1128. EXPECT_EQ(std::string("bcdefg"), res->body);
  1129. }
  1130. TEST_F(ServerTest, GetWithRange3) {
  1131. auto res = cli_.Get("/with-range", {{make_range_header({{0, 0}})}});
  1132. ASSERT_TRUE(res != nullptr);
  1133. EXPECT_EQ(206, res->status);
  1134. EXPECT_EQ("1", res->get_header_value("Content-Length"));
  1135. EXPECT_EQ(true, res->has_header("Content-Range"));
  1136. EXPECT_EQ(std::string("a"), res->body);
  1137. }
  1138. TEST_F(ServerTest, GetWithRange4) {
  1139. auto res = cli_.Get("/with-range", {{make_range_header({{-1, 2}})}});
  1140. ASSERT_TRUE(res != nullptr);
  1141. EXPECT_EQ(206, res->status);
  1142. EXPECT_EQ("2", res->get_header_value("Content-Length"));
  1143. EXPECT_EQ(true, res->has_header("Content-Range"));
  1144. EXPECT_EQ(std::string("fg"), res->body);
  1145. }
  1146. TEST_F(ServerTest, GetWithRangeMultipart) {
  1147. auto res = cli_.Get("/with-range", {{make_range_header({{1, 2}, {4, 5}})}});
  1148. ASSERT_TRUE(res != nullptr);
  1149. EXPECT_EQ(206, res->status);
  1150. EXPECT_EQ("269", res->get_header_value("Content-Length"));
  1151. EXPECT_EQ(false, res->has_header("Content-Range"));
  1152. EXPECT_EQ(269, res->body.size());
  1153. }
  1154. TEST_F(ServerTest, GetStreamedChunked) {
  1155. auto res = cli_.Get("/streamed-chunked");
  1156. ASSERT_TRUE(res != nullptr);
  1157. EXPECT_EQ(200, res->status);
  1158. EXPECT_EQ(std::string("123456789"), res->body);
  1159. }
  1160. TEST_F(ServerTest, LargeChunkedPost) {
  1161. Request req;
  1162. req.method = "POST";
  1163. req.path = "/large-chunked";
  1164. std::string host_and_port;
  1165. host_and_port += HOST;
  1166. host_and_port += ":";
  1167. host_and_port += std::to_string(PORT);
  1168. req.headers.emplace("Host", host_and_port.c_str());
  1169. req.headers.emplace("Accept", "*/*");
  1170. req.headers.emplace("User-Agent", "cpp-httplib/0.1");
  1171. req.headers.emplace("Content-Type", "text/plain");
  1172. req.headers.emplace("Content-Length", "0");
  1173. req.headers.emplace("Transfer-Encoding", "chunked");
  1174. std::string long_string(30 * 1024u, 'a');
  1175. std::string chunk = "7800\r\n" + long_string + "\r\n";
  1176. // Attempt to make a large enough post to exceed OS buffers, to test that
  1177. // the server handles short reads if the full chunk data isn't available.
  1178. req.body = chunk + chunk + chunk + chunk + chunk + chunk + "0\r\n\r\n";
  1179. auto res = std::make_shared<Response>();
  1180. auto ret = cli_.send(req, *res);
  1181. ASSERT_TRUE(ret);
  1182. EXPECT_EQ(200, res->status);
  1183. }
  1184. TEST_F(ServerTest, GetMethodRemoteAddr) {
  1185. auto res = cli_.Get("/remote_addr");
  1186. ASSERT_TRUE(res != nullptr);
  1187. EXPECT_EQ(200, res->status);
  1188. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  1189. EXPECT_TRUE(res->body == "::1" || res->body == "127.0.0.1");
  1190. }
  1191. TEST_F(ServerTest, SlowRequest) {
  1192. request_threads_.push_back(
  1193. std::thread([=]() { auto res = cli_.Get("/slow"); }));
  1194. request_threads_.push_back(
  1195. std::thread([=]() { auto res = cli_.Get("/slow"); }));
  1196. request_threads_.push_back(
  1197. std::thread([=]() { auto res = cli_.Get("/slow"); }));
  1198. msleep(100);
  1199. }
  1200. TEST_F(ServerTest, Put) {
  1201. auto res = cli_.Put("/put", "PUT", "text/plain");
  1202. ASSERT_TRUE(res != nullptr);
  1203. EXPECT_EQ(200, res->status);
  1204. EXPECT_EQ("PUT", res->body);
  1205. }
  1206. TEST_F(ServerTest, PutWithContentProvider) {
  1207. auto res = cli_.Put(
  1208. "/put", 3,
  1209. [](size_t /*offset*/, size_t /*length*/, DataSink sink) {
  1210. sink("PUT", 3);
  1211. },
  1212. "text/plain");
  1213. ASSERT_TRUE(res != nullptr);
  1214. EXPECT_EQ(200, res->status);
  1215. EXPECT_EQ("PUT", res->body);
  1216. }
  1217. #ifdef CPPHTTPLIB_ZLIB_SUPPORT
  1218. TEST_F(ServerTest, PutWithContentProviderWithGzip) {
  1219. auto res = cli_.Put(
  1220. "/put", 3,
  1221. [](size_t /*offset*/, size_t /*length*/, DataSink sink) {
  1222. sink("PUT", 3);
  1223. },
  1224. "text/plain", true);
  1225. ASSERT_TRUE(res != nullptr);
  1226. EXPECT_EQ(200, res->status);
  1227. EXPECT_EQ("PUT", res->body);
  1228. }
  1229. #endif
  1230. TEST_F(ServerTest, Patch) {
  1231. auto res = cli_.Patch("/patch", "PATCH", "text/plain");
  1232. ASSERT_TRUE(res != nullptr);
  1233. EXPECT_EQ(200, res->status);
  1234. EXPECT_EQ("PATCH", res->body);
  1235. }
  1236. TEST_F(ServerTest, Delete) {
  1237. auto res = cli_.Delete("/delete");
  1238. ASSERT_TRUE(res != nullptr);
  1239. EXPECT_EQ(200, res->status);
  1240. EXPECT_EQ("DELETE", res->body);
  1241. }
  1242. TEST_F(ServerTest, Options) {
  1243. auto res = cli_.Options("*");
  1244. ASSERT_TRUE(res != nullptr);
  1245. EXPECT_EQ(200, res->status);
  1246. EXPECT_EQ("GET, POST, HEAD, OPTIONS", res->get_header_value("Allow"));
  1247. EXPECT_TRUE(res->body.empty());
  1248. }
  1249. TEST_F(ServerTest, URL) {
  1250. auto res = cli_.Get("/request-target?aaa=bbb&ccc=ddd");
  1251. ASSERT_TRUE(res != nullptr);
  1252. EXPECT_EQ(200, res->status);
  1253. }
  1254. TEST_F(ServerTest, ArrayParam) {
  1255. auto res = cli_.Get("/array-param?array=value1&array=value2&array=value3");
  1256. ASSERT_TRUE(res != nullptr);
  1257. EXPECT_EQ(200, res->status);
  1258. }
  1259. TEST_F(ServerTest, NoMultipleHeaders) {
  1260. Headers headers = {{"Content-Length", "5"}};
  1261. auto res = cli_.Post("/validate-no-multiple-headers", headers, "hello",
  1262. "text/plain");
  1263. ASSERT_TRUE(res != nullptr);
  1264. EXPECT_EQ(200, res->status);
  1265. }
  1266. TEST_F(ServerTest, PostContentReceiver) {
  1267. auto res = cli_.Post("/content_receiver", "content", "text/plain");
  1268. ASSERT_TRUE(res != nullptr);
  1269. ASSERT_EQ(200, res->status);
  1270. ASSERT_EQ("content", res->body);
  1271. }
  1272. TEST_F(ServerTest, PostContentReceiverGzip) {
  1273. auto res = cli_.Post("/content_receiver", "content", "text/plain", true);
  1274. ASSERT_TRUE(res != nullptr);
  1275. ASSERT_EQ(200, res->status);
  1276. ASSERT_EQ("content", res->body);
  1277. }
  1278. TEST_F(ServerTest, PutContentReceiver) {
  1279. auto res = cli_.Put("/content_receiver", "content", "text/plain");
  1280. ASSERT_TRUE(res != nullptr);
  1281. ASSERT_EQ(200, res->status);
  1282. ASSERT_EQ("content", res->body);
  1283. }
  1284. TEST_F(ServerTest, PatchContentReceiver) {
  1285. auto res = cli_.Patch("/content_receiver", "content", "text/plain");
  1286. ASSERT_TRUE(res != nullptr);
  1287. ASSERT_EQ(200, res->status);
  1288. ASSERT_EQ("content", res->body);
  1289. }
  1290. TEST_F(ServerTest, HTTP2Magic) {
  1291. Request req;
  1292. req.method = "PRI";
  1293. req.path = "*";
  1294. req.body = "SM";
  1295. auto res = std::make_shared<Response>();
  1296. auto ret = cli_.send(req, *res);
  1297. ASSERT_TRUE(ret);
  1298. EXPECT_EQ(400, res->status);
  1299. }
  1300. TEST_F(ServerTest, KeepAlive) {
  1301. cli_.set_keep_alive_max_count(4);
  1302. std::vector<Request> requests;
  1303. Get(requests, "/hi");
  1304. Get(requests, "/hi");
  1305. Get(requests, "/hi");
  1306. Get(requests, "/not-exist");
  1307. Post(requests, "/empty", "", "text/plain");
  1308. std::vector<Response> responses;
  1309. auto ret = cli_.send(requests, responses);
  1310. ASSERT_TRUE(ret == true);
  1311. ASSERT_TRUE(requests.size() == responses.size());
  1312. for (int i = 0; i < 3; i++) {
  1313. auto &res = responses[i];
  1314. EXPECT_EQ(200, res.status);
  1315. EXPECT_EQ("text/plain", res.get_header_value("Content-Type"));
  1316. EXPECT_EQ("Hello World!", res.body);
  1317. }
  1318. {
  1319. auto &res = responses[3];
  1320. EXPECT_EQ(404, res.status);
  1321. }
  1322. {
  1323. auto &res = responses[4];
  1324. EXPECT_EQ(200, res.status);
  1325. EXPECT_EQ("text/plain", res.get_header_value("Content-Type"));
  1326. EXPECT_EQ("empty", res.body);
  1327. }
  1328. }
  1329. #ifdef CPPHTTPLIB_ZLIB_SUPPORT
  1330. TEST_F(ServerTest, Gzip) {
  1331. Headers headers;
  1332. headers.emplace("Accept-Encoding", "gzip, deflate");
  1333. auto res = cli_.Get("/gzip", headers);
  1334. ASSERT_TRUE(res != nullptr);
  1335. EXPECT_EQ("gzip", res->get_header_value("Content-Encoding"));
  1336. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  1337. EXPECT_EQ("33", res->get_header_value("Content-Length"));
  1338. EXPECT_EQ("123456789012345678901234567890123456789012345678901234567890123456"
  1339. "7890123456789012345678901234567890",
  1340. res->body);
  1341. EXPECT_EQ(200, res->status);
  1342. }
  1343. TEST_F(ServerTest, GzipWithoutAcceptEncoding) {
  1344. Headers headers;
  1345. auto res = cli_.Get("/gzip", headers);
  1346. ASSERT_TRUE(res != nullptr);
  1347. EXPECT_EQ("", res->get_header_value("Content-Encoding"));
  1348. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  1349. EXPECT_EQ("100", res->get_header_value("Content-Length"));
  1350. EXPECT_EQ("123456789012345678901234567890123456789012345678901234567890123456"
  1351. "7890123456789012345678901234567890",
  1352. res->body);
  1353. EXPECT_EQ(200, res->status);
  1354. }
  1355. TEST_F(ServerTest, GzipWithContentReceiver) {
  1356. Headers headers;
  1357. headers.emplace("Accept-Encoding", "gzip, deflate");
  1358. std::string body;
  1359. auto res =
  1360. cli_.Get("/gzip", headers, [&](const char *data, uint64_t data_length) {
  1361. EXPECT_EQ(data_length, 100);
  1362. body.append(data, data_length);
  1363. return true;
  1364. });
  1365. ASSERT_TRUE(res != nullptr);
  1366. EXPECT_EQ("gzip", res->get_header_value("Content-Encoding"));
  1367. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  1368. EXPECT_EQ("33", res->get_header_value("Content-Length"));
  1369. EXPECT_EQ("123456789012345678901234567890123456789012345678901234567890123456"
  1370. "7890123456789012345678901234567890",
  1371. body);
  1372. EXPECT_EQ(200, res->status);
  1373. }
  1374. TEST_F(ServerTest, GzipWithContentReceiverWithoutAcceptEncoding) {
  1375. Headers headers;
  1376. std::string body;
  1377. auto res =
  1378. cli_.Get("/gzip", headers, [&](const char *data, uint64_t data_length) {
  1379. EXPECT_EQ(data_length, 100);
  1380. body.append(data, data_length);
  1381. return true;
  1382. });
  1383. ASSERT_TRUE(res != nullptr);
  1384. EXPECT_EQ("", res->get_header_value("Content-Encoding"));
  1385. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  1386. EXPECT_EQ("100", res->get_header_value("Content-Length"));
  1387. EXPECT_EQ("123456789012345678901234567890123456789012345678901234567890123456"
  1388. "7890123456789012345678901234567890",
  1389. body);
  1390. EXPECT_EQ(200, res->status);
  1391. }
  1392. TEST_F(ServerTest, NoGzip) {
  1393. Headers headers;
  1394. headers.emplace("Accept-Encoding", "gzip, deflate");
  1395. auto res = cli_.Get("/nogzip", headers);
  1396. ASSERT_TRUE(res != nullptr);
  1397. EXPECT_EQ(false, res->has_header("Content-Encoding"));
  1398. EXPECT_EQ("application/octet-stream", res->get_header_value("Content-Type"));
  1399. EXPECT_EQ("100", res->get_header_value("Content-Length"));
  1400. EXPECT_EQ("123456789012345678901234567890123456789012345678901234567890123456"
  1401. "7890123456789012345678901234567890",
  1402. res->body);
  1403. EXPECT_EQ(200, res->status);
  1404. }
  1405. TEST_F(ServerTest, NoGzipWithContentReceiver) {
  1406. Headers headers;
  1407. headers.emplace("Accept-Encoding", "gzip, deflate");
  1408. std::string body;
  1409. auto res =
  1410. cli_.Get("/nogzip", headers, [&](const char *data, uint64_t data_length) {
  1411. EXPECT_EQ(data_length, 100);
  1412. body.append(data, data_length);
  1413. return true;
  1414. });
  1415. ASSERT_TRUE(res != nullptr);
  1416. EXPECT_EQ(false, res->has_header("Content-Encoding"));
  1417. EXPECT_EQ("application/octet-stream", res->get_header_value("Content-Type"));
  1418. EXPECT_EQ("100", res->get_header_value("Content-Length"));
  1419. EXPECT_EQ("123456789012345678901234567890123456789012345678901234567890123456"
  1420. "7890123456789012345678901234567890",
  1421. body);
  1422. EXPECT_EQ(200, res->status);
  1423. }
  1424. TEST_F(ServerTest, MultipartFormDataGzip) {
  1425. MultipartFormDataItems items = {
  1426. {"key1", "test", "", ""},
  1427. {"key2", "--abcdefg123", "", ""},
  1428. };
  1429. auto res = cli_.Post("/gzipmultipart", items, true);
  1430. ASSERT_TRUE(res != nullptr);
  1431. EXPECT_EQ(200, res->status);
  1432. }
  1433. #endif
  1434. class ServerTestWithAI_PASSIVE : public ::testing::Test {
  1435. protected:
  1436. ServerTestWithAI_PASSIVE()
  1437. : cli_(HOST, PORT)
  1438. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1439. ,
  1440. svr_(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE)
  1441. #endif
  1442. {
  1443. }
  1444. virtual void SetUp() {
  1445. svr_.Get("/hi", [&](const Request & /*req*/, Response &res) {
  1446. res.set_content("Hello World!", "text/plain");
  1447. });
  1448. t_ = thread([&]() { ASSERT_TRUE(svr_.listen(nullptr, PORT, AI_PASSIVE)); });
  1449. while (!svr_.is_running()) {
  1450. msleep(1);
  1451. }
  1452. }
  1453. virtual void TearDown() {
  1454. svr_.stop();
  1455. t_.join();
  1456. }
  1457. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1458. SSLClient cli_;
  1459. SSLServer svr_;
  1460. #else
  1461. Client cli_;
  1462. Server svr_;
  1463. #endif
  1464. thread t_;
  1465. };
  1466. TEST_F(ServerTestWithAI_PASSIVE, GetMethod200) {
  1467. auto res = cli_.Get("/hi");
  1468. ASSERT_TRUE(res != nullptr);
  1469. EXPECT_EQ(200, res->status);
  1470. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  1471. EXPECT_EQ("Hello World!", res->body);
  1472. }
  1473. class ServerUpDownTest : public ::testing::Test {
  1474. protected:
  1475. ServerUpDownTest() : cli_(HOST, PORT) {}
  1476. virtual void SetUp() {
  1477. t_ = thread([&]() {
  1478. svr_.bind_to_any_port(HOST);
  1479. msleep(500);
  1480. ASSERT_TRUE(svr_.listen_after_bind());
  1481. });
  1482. while (!svr_.is_running()) {
  1483. msleep(1);
  1484. }
  1485. }
  1486. virtual void TearDown() {
  1487. svr_.stop();
  1488. t_.join();
  1489. }
  1490. Client cli_;
  1491. Server svr_;
  1492. thread t_;
  1493. };
  1494. TEST_F(ServerUpDownTest, QuickStartStop) {
  1495. // Should not crash, especially when run with
  1496. // --gtest_filter=ServerUpDownTest.QuickStartStop --gtest_repeat=1000
  1497. }
  1498. class PayloadMaxLengthTest : public ::testing::Test {
  1499. protected:
  1500. PayloadMaxLengthTest()
  1501. : cli_(HOST, PORT)
  1502. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1503. ,
  1504. svr_(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE)
  1505. #endif
  1506. {
  1507. }
  1508. virtual void SetUp() {
  1509. svr_.set_payload_max_length(8);
  1510. svr_.Post("/test", [&](const Request & /*req*/, Response &res) {
  1511. res.set_content("test", "text/plain");
  1512. });
  1513. t_ = thread([&]() { ASSERT_TRUE(svr_.listen(HOST, PORT)); });
  1514. while (!svr_.is_running()) {
  1515. msleep(1);
  1516. }
  1517. }
  1518. virtual void TearDown() {
  1519. svr_.stop();
  1520. t_.join();
  1521. }
  1522. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1523. SSLClient cli_;
  1524. SSLServer svr_;
  1525. #else
  1526. Client cli_;
  1527. Server svr_;
  1528. #endif
  1529. thread t_;
  1530. };
  1531. TEST_F(PayloadMaxLengthTest, ExceedLimit) {
  1532. auto res = cli_.Post("/test", "123456789", "text/plain");
  1533. ASSERT_TRUE(res != nullptr);
  1534. EXPECT_EQ(413, res->status);
  1535. res = cli_.Post("/test", "12345678", "text/plain");
  1536. ASSERT_TRUE(res != nullptr);
  1537. EXPECT_EQ(200, res->status);
  1538. }
  1539. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  1540. TEST(SSLClientTest, ServerNameIndication) {
  1541. SSLClient cli("httpbin.org", 443);
  1542. auto res = cli.Get("/get");
  1543. ASSERT_TRUE(res != nullptr);
  1544. ASSERT_EQ(200, res->status);
  1545. }
  1546. TEST(SSLClientTest, ServerCertificateVerification) {
  1547. SSLClient cli("google.com");
  1548. auto res = cli.Get("/");
  1549. ASSERT_TRUE(res != nullptr);
  1550. ASSERT_EQ(301, res->status);
  1551. cli.enable_server_certificate_verification(true);
  1552. res = cli.Get("/");
  1553. ASSERT_TRUE(res == nullptr);
  1554. cli.set_ca_cert_path(CA_CERT_FILE);
  1555. res = cli.Get("/");
  1556. ASSERT_TRUE(res != nullptr);
  1557. ASSERT_EQ(301, res->status);
  1558. }
  1559. TEST(SSLClientTest, WildcardHostNameMatch) {
  1560. SSLClient cli("www.youtube.com");
  1561. cli.set_ca_cert_path(CA_CERT_FILE);
  1562. cli.enable_server_certificate_verification(true);
  1563. auto res = cli.Get("/");
  1564. ASSERT_TRUE(res != nullptr);
  1565. ASSERT_EQ(200, res->status);
  1566. }
  1567. TEST(SSLClientServerTest, ClientCertPresent) {
  1568. SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE, CLIENT_CA_CERT_FILE,
  1569. CLIENT_CA_CERT_DIR);
  1570. ASSERT_TRUE(svr.is_valid());
  1571. svr.Get("/test", [&](const Request &req, Response &res) {
  1572. res.set_content("test", "text/plain");
  1573. svr.stop();
  1574. ASSERT_TRUE(true);
  1575. auto peer_cert = SSL_get_peer_certificate(req.ssl);
  1576. ASSERT_TRUE(peer_cert != nullptr);
  1577. auto subject_name = X509_get_subject_name(peer_cert);
  1578. ASSERT_TRUE(subject_name != nullptr);
  1579. std::string common_name;
  1580. {
  1581. char name[BUFSIZ];
  1582. auto name_len = X509_NAME_get_text_by_NID(subject_name, NID_commonName,
  1583. name, sizeof(name));
  1584. common_name.assign(name, name_len);
  1585. }
  1586. EXPECT_EQ("Common Name", common_name);
  1587. X509_free(peer_cert);
  1588. });
  1589. thread t = thread([&]() { ASSERT_TRUE(svr.listen(HOST, PORT)); });
  1590. msleep(1);
  1591. httplib::SSLClient cli(HOST, PORT, 30, CLIENT_CERT_FILE,
  1592. CLIENT_PRIVATE_KEY_FILE);
  1593. auto res = cli.Get("/test");
  1594. ASSERT_TRUE(res != nullptr);
  1595. ASSERT_EQ(200, res->status);
  1596. t.join();
  1597. }
  1598. TEST(SSLClientServerTest, ClientCertMissing) {
  1599. SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE, CLIENT_CA_CERT_FILE,
  1600. CLIENT_CA_CERT_DIR);
  1601. ASSERT_TRUE(svr.is_valid());
  1602. svr.Get("/test", [&](const Request &, Response &) { ASSERT_TRUE(false); });
  1603. thread t = thread([&]() { ASSERT_TRUE(svr.listen(HOST, PORT)); });
  1604. msleep(1);
  1605. httplib::SSLClient cli(HOST, PORT, 30);
  1606. auto res = cli.Get("/test");
  1607. ASSERT_TRUE(res == nullptr);
  1608. svr.stop();
  1609. t.join();
  1610. }
  1611. TEST(SSLClientServerTest, TrustDirOptional) {
  1612. SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE, CLIENT_CA_CERT_FILE);
  1613. ASSERT_TRUE(svr.is_valid());
  1614. svr.Get("/test", [&](const Request &, Response &res) {
  1615. res.set_content("test", "text/plain");
  1616. svr.stop();
  1617. });
  1618. thread t = thread([&]() { ASSERT_TRUE(svr.listen(HOST, PORT)); });
  1619. msleep(1);
  1620. httplib::SSLClient cli(HOST, PORT, 30, CLIENT_CERT_FILE,
  1621. CLIENT_PRIVATE_KEY_FILE);
  1622. auto res = cli.Get("/test");
  1623. ASSERT_TRUE(res != nullptr);
  1624. ASSERT_EQ(200, res->status);
  1625. t.join();
  1626. }
  1627. /* Cannot test this case as there is no external access to SSL object to check
  1628. SSL_get_peer_certificate() == NULL TEST(SSLClientServerTest,
  1629. ClientCAPathRequired) { SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE,
  1630. nullptr, CLIENT_CA_CERT_DIR);
  1631. }
  1632. */
  1633. #endif
  1634. #ifdef _WIN32
  1635. TEST(CleanupTest, WSACleanup) {
  1636. int ret = WSACleanup();
  1637. ASSERT_EQ(0, ret);
  1638. }
  1639. #endif