Fork of the excellent esp8266-react - https://github.com/rjwats/esp8266-react
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

169 lines
6.5 KiB

  1. #ifndef HttpEndpoint_h
  2. #define HttpEndpoint_h
  3. #include <functional>
  4. #include <AsyncJson.h>
  5. #include <ESPAsyncWebServer.h>
  6. #include <SecurityManager.h>
  7. #include <StatefulService.h>
  8. #include <JsonSerializer.h>
  9. #include <JsonDeserializer.h>
  10. #define HTTP_ENDPOINT_ORIGIN_ID "http"
  11. template <class T>
  12. class HttpGetEndpoint {
  13. public:
  14. HttpGetEndpoint(JsonSerializer<T> jsonSerializer,
  15. StatefulService<T>* statefulService,
  16. AsyncWebServer* server,
  17. const String& servicePath,
  18. SecurityManager* securityManager,
  19. AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN,
  20. size_t bufferSize = DEFAULT_BUFFER_SIZE) :
  21. _jsonSerializer(jsonSerializer), _statefulService(statefulService), _bufferSize(bufferSize) {
  22. server->on(servicePath.c_str(),
  23. HTTP_GET,
  24. securityManager->wrapRequest(std::bind(&HttpGetEndpoint::fetchSettings, this, std::placeholders::_1),
  25. authenticationPredicate));
  26. }
  27. HttpGetEndpoint(JsonSerializer<T> jsonSerializer,
  28. StatefulService<T>* statefulService,
  29. AsyncWebServer* server,
  30. const String& servicePath,
  31. size_t bufferSize = DEFAULT_BUFFER_SIZE) :
  32. _jsonSerializer(jsonSerializer), _statefulService(statefulService), _bufferSize(bufferSize) {
  33. server->on(servicePath.c_str(), HTTP_GET, std::bind(&HttpGetEndpoint::fetchSettings, this, std::placeholders::_1));
  34. }
  35. protected:
  36. JsonSerializer<T> _jsonSerializer;
  37. StatefulService<T>* _statefulService;
  38. size_t _bufferSize;
  39. void fetchSettings(AsyncWebServerRequest* request) {
  40. AsyncJsonResponse* response = new AsyncJsonResponse(false, _bufferSize);
  41. JsonObject jsonObject = response->getRoot().to<JsonObject>();
  42. _statefulService->read(jsonObject, _jsonSerializer);
  43. response->setLength();
  44. request->send(response);
  45. }
  46. };
  47. template <class T>
  48. class HttpPostEndpoint {
  49. public:
  50. HttpPostEndpoint(JsonSerializer<T> jsonSerializer,
  51. JsonDeserializer<T> jsonDeserializer,
  52. StatefulService<T>* statefulService,
  53. AsyncWebServer* server,
  54. const String& servicePath,
  55. SecurityManager* securityManager,
  56. AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN,
  57. size_t bufferSize = DEFAULT_BUFFER_SIZE) :
  58. _jsonSerializer(jsonSerializer),
  59. _jsonDeserializer(jsonDeserializer),
  60. _statefulService(statefulService),
  61. _updateHandler(
  62. servicePath,
  63. securityManager->wrapCallback(
  64. std::bind(&HttpPostEndpoint::updateSettings, this, std::placeholders::_1, std::placeholders::_2),
  65. authenticationPredicate),
  66. bufferSize),
  67. _bufferSize(bufferSize) {
  68. _updateHandler.setMethod(HTTP_POST);
  69. server->addHandler(&_updateHandler);
  70. }
  71. HttpPostEndpoint(JsonSerializer<T> jsonSerializer,
  72. JsonDeserializer<T> jsonDeserializer,
  73. StatefulService<T>* statefulService,
  74. AsyncWebServer* server,
  75. const String& servicePath,
  76. size_t bufferSize = DEFAULT_BUFFER_SIZE) :
  77. _jsonSerializer(jsonSerializer),
  78. _jsonDeserializer(jsonDeserializer),
  79. _statefulService(statefulService),
  80. _updateHandler(servicePath,
  81. std::bind(&HttpPostEndpoint::updateSettings, this, std::placeholders::_1, std::placeholders::_2),
  82. bufferSize),
  83. _bufferSize(bufferSize) {
  84. _updateHandler.setMethod(HTTP_POST);
  85. server->addHandler(&_updateHandler);
  86. }
  87. protected:
  88. JsonSerializer<T> _jsonSerializer;
  89. JsonDeserializer<T> _jsonDeserializer;
  90. StatefulService<T>* _statefulService;
  91. AsyncCallbackJsonWebHandler _updateHandler;
  92. size_t _bufferSize;
  93. void updateSettings(AsyncWebServerRequest* request, JsonVariant& json) {
  94. if (json.is<JsonObject>()) {
  95. AsyncJsonResponse* response = new AsyncJsonResponse(false, _bufferSize);
  96. // use callback to update the settings once the response is complete
  97. request->onDisconnect([this]() { _statefulService->callUpdateHandlers(HTTP_ENDPOINT_ORIGIN_ID); });
  98. // update the settings, deferring the call to the update handlers to when the response is complete
  99. _statefulService->updateWithoutPropagation([&](T& settings) {
  100. JsonObject jsonObject = json.as<JsonObject>();
  101. _jsonDeserializer(jsonObject, settings);
  102. jsonObject = response->getRoot().to<JsonObject>();
  103. _jsonSerializer(settings, jsonObject);
  104. });
  105. // write the response to the client
  106. response->setLength();
  107. request->send(response);
  108. } else {
  109. request->send(400);
  110. }
  111. }
  112. };
  113. template <class T>
  114. class HttpEndpoint : public HttpGetEndpoint<T>, public HttpPostEndpoint<T> {
  115. public:
  116. HttpEndpoint(JsonSerializer<T> jsonSerializer,
  117. JsonDeserializer<T> jsonDeserializer,
  118. StatefulService<T>* statefulService,
  119. AsyncWebServer* server,
  120. const String& servicePath,
  121. SecurityManager* securityManager,
  122. AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN,
  123. size_t bufferSize = DEFAULT_BUFFER_SIZE) :
  124. HttpGetEndpoint<T>(jsonSerializer,
  125. statefulService,
  126. server,
  127. servicePath,
  128. securityManager,
  129. authenticationPredicate,
  130. bufferSize),
  131. HttpPostEndpoint<T>(jsonSerializer,
  132. jsonDeserializer,
  133. statefulService,
  134. server,
  135. servicePath,
  136. securityManager,
  137. authenticationPredicate,
  138. bufferSize) {
  139. }
  140. HttpEndpoint(JsonSerializer<T> jsonSerializer,
  141. JsonDeserializer<T> jsonDeserializer,
  142. StatefulService<T>* statefulService,
  143. AsyncWebServer* server,
  144. const String& servicePath,
  145. size_t bufferSize = DEFAULT_BUFFER_SIZE) :
  146. HttpGetEndpoint<T>(jsonSerializer, statefulService, server, servicePath, bufferSize),
  147. HttpPostEndpoint<T>(jsonSerializer, jsonDeserializer, statefulService, server, servicePath, bufferSize) {
  148. }
  149. };
  150. #endif // end HttpEndpoint