test_proxy.cc 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. #include <chrono>
  2. #include <future>
  3. #include <gtest/gtest.h>
  4. #include <httplib.h>
  5. using namespace std;
  6. using namespace httplib;
  7. #if defined(CPPHTTPLIB_OPENSSL_SUPPORT) || defined(CPPHTTPLIB_MBEDTLS_SUPPORT)
  8. #define CPPHTTPLIB_SSL_SUPPORT
  9. #endif
  10. std::string normalizeJson(const std::string &json) {
  11. std::string result;
  12. for (char c : json) {
  13. if (c != ' ' && c != '\t' && c != '\n' && c != '\r') { result += c; }
  14. }
  15. return result;
  16. }
  17. template <typename T> void ProxyTest(T &cli, bool basic) {
  18. cli.set_proxy("localhost", basic ? 3128 : 3129);
  19. auto res = cli.Get("/httpbin/get");
  20. ASSERT_TRUE(res != nullptr);
  21. EXPECT_EQ(StatusCode::ProxyAuthenticationRequired_407, res->status);
  22. }
  23. TEST(ProxyTest, NoSSLBasic) {
  24. Client cli("nghttp2.org");
  25. ProxyTest(cli, true);
  26. }
  27. #ifdef CPPHTTPLIB_SSL_SUPPORT
  28. TEST(ProxyTest, SSLBasic) {
  29. SSLClient cli("nghttp2.org");
  30. ProxyTest(cli, true);
  31. }
  32. TEST(ProxyTest, NoSSLDigest) {
  33. Client cli("nghttp2.org");
  34. ProxyTest(cli, false);
  35. }
  36. TEST(ProxyTest, SSLDigest) {
  37. SSLClient cli("nghttp2.org");
  38. ProxyTest(cli, false);
  39. }
  40. #endif
  41. // ----------------------------------------------------------------------------
  42. template <typename T>
  43. void RedirectProxyText(T &cli, const char *path, bool basic) {
  44. cli.set_proxy("localhost", basic ? 3128 : 3129);
  45. if (basic) {
  46. cli.set_proxy_basic_auth("hello", "world");
  47. } else {
  48. #ifdef CPPHTTPLIB_SSL_SUPPORT
  49. cli.set_proxy_digest_auth("hello", "world");
  50. #endif
  51. }
  52. cli.set_follow_location(true);
  53. auto res = cli.Get(path);
  54. ASSERT_TRUE(res != nullptr);
  55. EXPECT_EQ(StatusCode::OK_200, res->status);
  56. }
  57. TEST(RedirectTest, HTTPBinNoSSLBasic) {
  58. Client cli("nghttp2.org");
  59. RedirectProxyText(cli, "/httpbin/redirect/2", true);
  60. }
  61. #ifdef CPPHTTPLIB_SSL_SUPPORT
  62. TEST(RedirectTest, HTTPBinNoSSLDigest) {
  63. Client cli("nghttp2.org");
  64. RedirectProxyText(cli, "/httpbin/redirect/2", false);
  65. }
  66. TEST(RedirectTest, HTTPBinSSLBasic) {
  67. SSLClient cli("nghttp2.org");
  68. RedirectProxyText(cli, "/httpbin/redirect/2", true);
  69. }
  70. TEST(RedirectTest, HTTPBinSSLDigest) {
  71. SSLClient cli("nghttp2.org");
  72. RedirectProxyText(cli, "/httpbin/redirect/2", false);
  73. }
  74. #endif
  75. #ifdef CPPHTTPLIB_SSL_SUPPORT
  76. TEST(RedirectTest, YouTubeNoSSLBasic) {
  77. Client cli("youtube.com");
  78. RedirectProxyText(cli, "/", true);
  79. }
  80. TEST(RedirectTest, YouTubeNoSSLDigest) {
  81. Client cli("youtube.com");
  82. RedirectProxyText(cli, "/", false);
  83. }
  84. TEST(RedirectTest, YouTubeSSLBasic) {
  85. SSLClient cli("youtube.com");
  86. RedirectProxyText(cli, "/", true);
  87. }
  88. TEST(RedirectTest, YouTubeSSLDigest) {
  89. std::this_thread::sleep_for(std::chrono::seconds(3));
  90. SSLClient cli("youtube.com");
  91. RedirectProxyText(cli, "/", false);
  92. }
  93. #endif
  94. // ----------------------------------------------------------------------------
  95. template <typename T> void BaseAuthTestFromHTTPWatch(T &cli) {
  96. cli.set_proxy("localhost", 3128);
  97. cli.set_proxy_basic_auth("hello", "world");
  98. {
  99. auto res = cli.Get("/basic-auth/hello/world");
  100. ASSERT_TRUE(res != nullptr);
  101. EXPECT_EQ(StatusCode::Unauthorized_401, res->status);
  102. }
  103. {
  104. auto res = cli.Get("/basic-auth/hello/world",
  105. {make_basic_authentication_header("hello", "world")});
  106. ASSERT_TRUE(res != nullptr);
  107. EXPECT_EQ(normalizeJson("{\"authenticated\":true,\"user\":\"hello\"}\n"),
  108. normalizeJson(res->body));
  109. EXPECT_EQ(StatusCode::OK_200, res->status);
  110. }
  111. {
  112. cli.set_basic_auth("hello", "world");
  113. auto res = cli.Get("/basic-auth/hello/world");
  114. ASSERT_TRUE(res != nullptr);
  115. EXPECT_EQ(normalizeJson("{\"authenticated\":true,\"user\":\"hello\"}\n"),
  116. normalizeJson(res->body));
  117. EXPECT_EQ(StatusCode::OK_200, res->status);
  118. }
  119. {
  120. cli.set_basic_auth("hello", "bad");
  121. auto res = cli.Get("/basic-auth/hello/world");
  122. ASSERT_TRUE(res != nullptr);
  123. EXPECT_EQ(StatusCode::Unauthorized_401, res->status);
  124. }
  125. {
  126. cli.set_basic_auth("bad", "world");
  127. auto res = cli.Get("/basic-auth/hello/world");
  128. ASSERT_TRUE(res != nullptr);
  129. EXPECT_EQ(StatusCode::Unauthorized_401, res->status);
  130. }
  131. }
  132. TEST(BaseAuthTest, NoSSL) {
  133. Client cli("httpcan.org");
  134. BaseAuthTestFromHTTPWatch(cli);
  135. }
  136. #ifdef CPPHTTPLIB_SSL_SUPPORT
  137. TEST(BaseAuthTest, SSL) {
  138. SSLClient cli("httpcan.org");
  139. BaseAuthTestFromHTTPWatch(cli);
  140. }
  141. #endif
  142. // ----------------------------------------------------------------------------
  143. #ifdef CPPHTTPLIB_SSL_SUPPORT
  144. template <typename T> void DigestAuthTestFromHTTPWatch(T &cli) {
  145. cli.set_proxy("localhost", 3129);
  146. cli.set_proxy_digest_auth("hello", "world");
  147. {
  148. auto res = cli.Get("/digest-auth/auth/hello/world");
  149. ASSERT_TRUE(res != nullptr);
  150. EXPECT_EQ(StatusCode::Unauthorized_401, res->status);
  151. }
  152. {
  153. std::vector<std::string> paths = {
  154. "/digest-auth/auth/hello/world/MD5",
  155. "/digest-auth/auth/hello/world/SHA-256",
  156. "/digest-auth/auth/hello/world/SHA-512",
  157. };
  158. cli.set_digest_auth("hello", "world");
  159. for (auto path : paths) {
  160. auto res = cli.Get(path.c_str());
  161. ASSERT_TRUE(res != nullptr);
  162. std::string algo(path.substr(path.rfind('/') + 1));
  163. EXPECT_EQ(
  164. normalizeJson("{\"algorithm\":\"" + algo +
  165. "\",\"authenticated\":true,\"user\":\"hello\"}\n"),
  166. normalizeJson(res->body));
  167. EXPECT_EQ(StatusCode::OK_200, res->status);
  168. }
  169. cli.set_digest_auth("hello", "bad");
  170. for (auto path : paths) {
  171. auto res = cli.Get(path.c_str());
  172. ASSERT_TRUE(res != nullptr);
  173. EXPECT_EQ(StatusCode::Unauthorized_401, res->status);
  174. }
  175. cli.set_digest_auth("bad", "world");
  176. for (auto path : paths) {
  177. auto res = cli.Get(path.c_str());
  178. ASSERT_TRUE(res != nullptr);
  179. EXPECT_EQ(StatusCode::Unauthorized_401, res->status);
  180. }
  181. }
  182. }
  183. TEST(DigestAuthTest, SSL) {
  184. SSLClient cli("httpcan.org");
  185. DigestAuthTestFromHTTPWatch(cli);
  186. }
  187. TEST(DigestAuthTest, NoSSL) {
  188. Client cli("httpcan.org");
  189. DigestAuthTestFromHTTPWatch(cli);
  190. }
  191. #endif
  192. // ----------------------------------------------------------------------------
  193. template <typename T> void KeepAliveTest(T &cli, bool basic) {
  194. cli.set_proxy("localhost", basic ? 3128 : 3129);
  195. if (basic) {
  196. cli.set_proxy_basic_auth("hello", "world");
  197. } else {
  198. #ifdef CPPHTTPLIB_SSL_SUPPORT
  199. cli.set_proxy_digest_auth("hello", "world");
  200. #endif
  201. }
  202. cli.set_follow_location(true);
  203. #ifdef CPPHTTPLIB_SSL_SUPPORT
  204. cli.set_digest_auth("hello", "world");
  205. #endif
  206. {
  207. auto res = cli.Get("/httpbin/get");
  208. EXPECT_EQ(StatusCode::OK_200, res->status);
  209. }
  210. {
  211. auto res = cli.Get("/httpbin/redirect/2");
  212. EXPECT_EQ(StatusCode::OK_200, res->status);
  213. }
  214. {
  215. std::vector<std::string> paths = {
  216. "/httpbin/digest-auth/auth/hello/world/MD5",
  217. "/httpbin/digest-auth/auth/hello/world/SHA-256",
  218. "/httpbin/digest-auth/auth/hello/world/SHA-512",
  219. "/httpbin/digest-auth/auth-int/hello/world/MD5",
  220. };
  221. for (auto path : paths) {
  222. auto res = cli.Get(path.c_str());
  223. EXPECT_EQ(normalizeJson("{\"authenticated\":true,\"user\":\"hello\"}\n"),
  224. normalizeJson(res->body));
  225. EXPECT_EQ(StatusCode::OK_200, res->status);
  226. }
  227. }
  228. {
  229. int count = 10;
  230. while (count--) {
  231. auto res = cli.Get("/httpbin/get");
  232. EXPECT_EQ(StatusCode::OK_200, res->status);
  233. }
  234. }
  235. }
  236. #ifdef CPPHTTPLIB_SSL_SUPPORT
  237. TEST(KeepAliveTest, NoSSLWithBasic) {
  238. Client cli("nghttp2.org");
  239. KeepAliveTest(cli, true);
  240. }
  241. TEST(KeepAliveTest, SSLWithBasic) {
  242. SSLClient cli("nghttp2.org");
  243. KeepAliveTest(cli, true);
  244. }
  245. TEST(KeepAliveTest, NoSSLWithDigest) {
  246. Client cli("nghttp2.org");
  247. KeepAliveTest(cli, false);
  248. }
  249. TEST(KeepAliveTest, SSLWithDigest) {
  250. SSLClient cli("nghttp2.org");
  251. KeepAliveTest(cli, false);
  252. }
  253. #endif