test_http.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include <unity.h>
  2. #include <atomic>
  3. #include "kbf.h"
  4. #include "kbf/wifi.h"
  5. #include "kbf/http/server.h"
  6. #include "kbf/http/client.h"
  7. using namespace kbf;
  8. std::atomic<bool> asyncFinished = {false};
  9. TEST_CASE("HTTP server <--> client / GET, POST, 404, 405", "[kbf_http]") {
  10. wifi::start();
  11. auto server = http::Server();
  12. http::Response (*handleGet)(const http::Request &) = {[](const http::Request &request) {
  13. TEST_ASSERT_EQUAL(http::GET, request.method);
  14. return http::Response("OK");
  15. }};
  16. server.route({http::GET, "/get-only", handleGet});
  17. http::Response (*handlePost)(const http::Request &) = {[](const http::Request &request) {
  18. TEST_ASSERT_EQUAL(http::POST, request.method);
  19. return http::Response("OK");
  20. }};
  21. server.route({http::POST, "/post-only", handlePost});
  22. http::Response (*handleGetAndPost)(const http::Request &) = {[](const http::Request &request) {
  23. if (request.method == http::GET) {
  24. return http::Response("GET");
  25. } else if (request.method == http::POST) {
  26. return http::Response("POST");
  27. } else {
  28. TEST_FAIL();
  29. return http::Response("fail"); // unreachable but the compiler moans otherwise
  30. }
  31. }};
  32. server.route({http::GET, "/get-and-post", handleGetAndPost});
  33. server.route({http::POST, "/get-and-post", handleGetAndPost});
  34. server.start();
  35. auto client = http::Client();
  36. auto response = client.get("http://localhost/get-only");
  37. TEST_ASSERT_EQUAL(200, response->status);
  38. TEST_ASSERT_EQUAL_STRING("OK", response->body.c_str());
  39. response = client.get("http://localhost/non-existent");
  40. TEST_ASSERT_EQUAL(404, response->status);
  41. TEST_ASSERT_EQUAL_STRING("This URI does not exist", response->body.c_str());
  42. response = client.get("http://localhost/post-only");
  43. TEST_ASSERT_EQUAL(405, response->status);
  44. TEST_ASSERT_EQUAL_STRING("Request method for this URI is not handled by server", response->body.c_str());
  45. response = client.get("http://localhost/get-and-post");
  46. TEST_ASSERT_EQUAL(200, response->status);
  47. TEST_ASSERT_EQUAL_STRING("GET", response->body.c_str());
  48. // TODO test POST once the client can do POST
  49. wifi::stop();
  50. }
  51. TEST_CASE("HTTP server <--> client / custom headers", "[kbf_http]") {
  52. wifi::start();
  53. auto server = http::Server();
  54. http::Response (*handleContentTypeTest)(const http::Request &) = {[](const http::Request &request) {
  55. auto response = http::Response("OK");
  56. if (!request.query.empty() && request.query.at("type") == "txt") {
  57. response.contentType = "text/plain";
  58. }
  59. return response;
  60. }};
  61. server.route({http::GET, "/content-type-test", handleContentTypeTest});
  62. http::Response (*handleCustomHeaderTest)(const http::Request &) = {[](const http::Request &request) {
  63. auto response = http::Response("OK");
  64. response.headers["X-Secret"] = request.query.at("secret");
  65. return response;
  66. }};
  67. server.route({http::GET, "/custom-header-test", handleCustomHeaderTest});
  68. server.start();
  69. auto client = http::Client();
  70. auto response = client.get("http://localhost/content-type-test");
  71. TEST_ASSERT_EQUAL_STRING("text/html", response->headers.at("Content-Type").c_str());
  72. TEST_ASSERT_EQUAL_STRING("OK", response->body.data());
  73. response = client.get("http://localhost/content-type-test?type=txt");
  74. TEST_ASSERT_EQUAL_STRING("text/plain", response->headers.at("Content-Type").c_str());
  75. TEST_ASSERT_EQUAL_STRING("OK", response->body.data());
  76. response = client.get("http://localhost/custom-header-test?secret=THISis1337");
  77. TEST_ASSERT_EQUAL_STRING("THISis1337", response->headers.at("X-Secret").c_str());
  78. TEST_ASSERT_EQUAL_STRING("OK", response->body.data());
  79. wifi::stop();
  80. }
  81. TEST_CASE("HTTP server <--> client / async", "[kbf_http]") {
  82. wifi::start();
  83. http::Response (*handleRequest)(const http::Request &) = {[](const http::Request &request) {
  84. auto response = http::Response("OK");
  85. kbf::sleep(100);
  86. return response;
  87. }};
  88. auto server = http::Server()
  89. .route({http::GET, "/", handleRequest})
  90. .start();
  91. auto client = http::Client(true);
  92. client.onSuccess = {[](http::Client &client, const http::Response &response) {
  93. TEST_ASSERT_EQUAL_STRING("OK", response.body.data());
  94. asyncFinished = true;
  95. }};
  96. auto response = client.get("http://localhost/");
  97. TEST_ASSERT_NULL(response);
  98. TEST_ASSERT_EQUAL(false, asyncFinished);
  99. kbf::sleep(200);
  100. TEST_ASSERT_EQUAL(true, asyncFinished);
  101. wifi::stop();
  102. }
  103. TEST_CASE("HTTP server <--> client / CORS", "[kbf_http]") {
  104. TEST_FAIL_MESSAGE("not yet implemented");
  105. }
  106. TEST_CASE("HTTP server <--> client / SPIFFS static route", "[kbf_http]") {
  107. TEST_FAIL_MESSAGE("not yet implemented");
  108. }