test.cc 57 KB

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