|
36 | 36 | #include <memory> |
37 | 37 | #include <string> |
38 | 38 |
|
| 39 | +#ifdef HAVE_GNUTLS |
| 40 | +#include <gnutls/gnutls.h> |
| 41 | +#endif |
| 42 | + |
39 | 43 | #include "./httpserver.hpp" |
40 | 44 | #include "./littletest.hpp" |
41 | 45 |
|
@@ -69,6 +73,26 @@ class ok_resource : public httpserver::http_resource { |
69 | 73 | } |
70 | 74 | }; |
71 | 75 |
|
| 76 | +#ifdef HAVE_GNUTLS |
| 77 | +class tls_info_resource : public httpserver::http_resource { |
| 78 | + public: |
| 79 | + shared_ptr<httpserver::http_response> render_GET(const httpserver::http_request& req) { |
| 80 | + std::string response; |
| 81 | + if (req.has_tls_session()) { |
| 82 | + gnutls_session_t session = req.get_tls_session(); |
| 83 | + if (session != nullptr) { |
| 84 | + response = "TLS_SESSION_PRESENT"; |
| 85 | + } else { |
| 86 | + response = "TLS_SESSION_NULL"; |
| 87 | + } |
| 88 | + } else { |
| 89 | + response = "NO_TLS_SESSION"; |
| 90 | + } |
| 91 | + return std::make_shared<httpserver::string_response>(response, 200, "text/plain"); |
| 92 | + } |
| 93 | +}; |
| 94 | +#endif // HAVE_GNUTLS |
| 95 | + |
72 | 96 | shared_ptr<httpserver::http_response> not_found_custom(const httpserver::http_request&) { |
73 | 97 | return std::make_shared<httpserver::string_response>("Not found custom", 404, "text/plain"); |
74 | 98 | } |
@@ -648,6 +672,144 @@ LT_BEGIN_AUTO_TEST(ws_start_stop_suite, custom_error_resources) |
648 | 672 | ws.stop(); |
649 | 673 | LT_END_AUTO_TEST(custom_error_resources) |
650 | 674 |
|
| 675 | +LT_BEGIN_AUTO_TEST(ws_start_stop_suite, ipv6_webserver) |
| 676 | + httpserver::webserver ws = httpserver::create_webserver(PORT + 20).use_ipv6(); |
| 677 | + ok_resource ok; |
| 678 | + LT_ASSERT_EQ(true, ws.register_resource("base", &ok)); |
| 679 | + bool started = ws.start(false); |
| 680 | + // IPv6 may not be available, so we just check the configuration worked |
| 681 | + if (started) { |
| 682 | + curl_global_init(CURL_GLOBAL_ALL); |
| 683 | + std::string s; |
| 684 | + CURL *curl = curl_easy_init(); |
| 685 | + CURLcode res; |
| 686 | + curl_easy_setopt(curl, CURLOPT_URL, "http://[::1]:" STR(PORT + 20) "/base"); |
| 687 | + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); |
| 688 | + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc); |
| 689 | + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s); |
| 690 | + res = curl_easy_perform(curl); |
| 691 | + if (res == 0) { |
| 692 | + LT_CHECK_EQ(s, "OK"); |
| 693 | + } |
| 694 | + curl_easy_cleanup(curl); |
| 695 | + ws.stop(); |
| 696 | + } |
| 697 | + LT_CHECK_EQ(1, 1); // Test passes even if IPv6 not available |
| 698 | +LT_END_AUTO_TEST(ipv6_webserver) |
| 699 | + |
| 700 | +LT_BEGIN_AUTO_TEST(ws_start_stop_suite, dual_stack_webserver) |
| 701 | + httpserver::webserver ws = httpserver::create_webserver(PORT + 21).use_dual_stack(); |
| 702 | + ok_resource ok; |
| 703 | + LT_ASSERT_EQ(true, ws.register_resource("base", &ok)); |
| 704 | + bool started = ws.start(false); |
| 705 | + if (started) { |
| 706 | + curl_global_init(CURL_GLOBAL_ALL); |
| 707 | + std::string s; |
| 708 | + CURL *curl = curl_easy_init(); |
| 709 | + CURLcode res; |
| 710 | + curl_easy_setopt(curl, CURLOPT_URL, "localhost:" STR(PORT + 21) "/base"); |
| 711 | + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); |
| 712 | + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc); |
| 713 | + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s); |
| 714 | + res = curl_easy_perform(curl); |
| 715 | + LT_ASSERT_EQ(res, 0); |
| 716 | + LT_CHECK_EQ(s, "OK"); |
| 717 | + curl_easy_cleanup(curl); |
| 718 | + ws.stop(); |
| 719 | + } |
| 720 | + LT_CHECK_EQ(1, 1); // Test passes even if dual stack not available |
| 721 | +LT_END_AUTO_TEST(dual_stack_webserver) |
| 722 | + |
| 723 | +LT_BEGIN_AUTO_TEST(ws_start_stop_suite, bind_address_ipv4) |
| 724 | + int port = PORT + 22; |
| 725 | + httpserver::webserver ws = httpserver::create_webserver(port).bind_address("127.0.0.1"); |
| 726 | + ok_resource ok; |
| 727 | + LT_ASSERT_EQ(true, ws.register_resource("base", &ok)); |
| 728 | + ws.start(false); |
| 729 | + |
| 730 | + curl_global_init(CURL_GLOBAL_ALL); |
| 731 | + std::string s; |
| 732 | + CURL *curl = curl_easy_init(); |
| 733 | + CURLcode res; |
| 734 | + std::string url = "http://127.0.0.1:" + std::to_string(port) + "/base"; |
| 735 | + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); |
| 736 | + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); |
| 737 | + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc); |
| 738 | + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s); |
| 739 | + res = curl_easy_perform(curl); |
| 740 | + LT_ASSERT_EQ(res, 0); |
| 741 | + LT_CHECK_EQ(s, "OK"); |
| 742 | + curl_easy_cleanup(curl); |
| 743 | + |
| 744 | + ws.stop(); |
| 745 | +LT_END_AUTO_TEST(bind_address_ipv4) |
| 746 | + |
| 747 | +#ifdef HAVE_GNUTLS |
| 748 | +LT_BEGIN_AUTO_TEST(ws_start_stop_suite, https_webserver) |
| 749 | + int port = PORT + 23; |
| 750 | + httpserver::webserver ws = httpserver::create_webserver(port) |
| 751 | + .use_ssl() |
| 752 | + .https_mem_key(ROOT "/key.pem") |
| 753 | + .https_mem_cert(ROOT "/cert.pem"); |
| 754 | + ok_resource ok; |
| 755 | + LT_ASSERT_EQ(true, ws.register_resource("base", &ok)); |
| 756 | + bool started = ws.start(false); |
| 757 | + if (!started) { |
| 758 | + // SSL setup may fail in some environments, skip the test |
| 759 | + LT_CHECK_EQ(1, 1); |
| 760 | + } else { |
| 761 | + curl_global_init(CURL_GLOBAL_ALL); |
| 762 | + std::string s; |
| 763 | + CURL *curl = curl_easy_init(); |
| 764 | + CURLcode res; |
| 765 | + std::string url = "https://localhost:" + std::to_string(port) + "/base"; |
| 766 | + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); |
| 767 | + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); |
| 768 | + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc); |
| 769 | + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s); |
| 770 | + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); |
| 771 | + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); |
| 772 | + res = curl_easy_perform(curl); |
| 773 | + LT_ASSERT_EQ(res, 0); |
| 774 | + LT_CHECK_EQ(s, "OK"); |
| 775 | + curl_easy_cleanup(curl); |
| 776 | + ws.stop(); |
| 777 | + } |
| 778 | +LT_END_AUTO_TEST(https_webserver) |
| 779 | + |
| 780 | +LT_BEGIN_AUTO_TEST(ws_start_stop_suite, tls_session_getters) |
| 781 | + int port = PORT + 24; |
| 782 | + httpserver::webserver ws = httpserver::create_webserver(port) |
| 783 | + .use_ssl() |
| 784 | + .https_mem_key(ROOT "/key.pem") |
| 785 | + .https_mem_cert(ROOT "/cert.pem"); |
| 786 | + tls_info_resource tls_info; |
| 787 | + LT_ASSERT_EQ(true, ws.register_resource("tls_info", &tls_info)); |
| 788 | + bool started = ws.start(false); |
| 789 | + if (!started) { |
| 790 | + // SSL setup may fail in some environments, skip the test |
| 791 | + LT_CHECK_EQ(1, 1); |
| 792 | + } else { |
| 793 | + curl_global_init(CURL_GLOBAL_ALL); |
| 794 | + std::string s; |
| 795 | + CURL *curl = curl_easy_init(); |
| 796 | + CURLcode res; |
| 797 | + std::string url = "https://localhost:" + std::to_string(port) + "/tls_info"; |
| 798 | + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); |
| 799 | + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); |
| 800 | + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc); |
| 801 | + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s); |
| 802 | + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); |
| 803 | + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); |
| 804 | + res = curl_easy_perform(curl); |
| 805 | + LT_ASSERT_EQ(res, 0); |
| 806 | + LT_CHECK_EQ(s, "TLS_SESSION_PRESENT"); |
| 807 | + curl_easy_cleanup(curl); |
| 808 | + ws.stop(); |
| 809 | + } |
| 810 | +LT_END_AUTO_TEST(tls_session_getters) |
| 811 | +#endif // HAVE_GNUTLS |
| 812 | + |
651 | 813 | #endif |
652 | 814 |
|
653 | 815 | LT_BEGIN_AUTO_TEST_ENV() |
|
0 commit comments