Mirror of espurna firmware for wireless switches and more
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.

90 lines
2.4 KiB

  1. /*
  2. Part of the WEBSERVER MODULE
  3. Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
  4. */
  5. #pragma once
  6. #include "web.h"
  7. #include "api.h"
  8. #include "libs/TypeChecks.h"
  9. namespace espurna {
  10. namespace web {
  11. namespace print {
  12. namespace traits {
  13. template <typename T>
  14. using print_callable_t = decltype(std::declval<T>()(std::declval<Print&>()));
  15. template <typename T>
  16. using is_print_callable = is_detected<print_callable_t, T>;
  17. } // namespace traits
  18. void RequestPrint::_onDisconnect() {
  19. #if API_SUPPORT
  20. // TODO: in case this comes from `apiRegister`'ed endpoint, there's still a lingering ApiRequestHelper that we must remove
  21. auto* req = request();
  22. if (req->_tempObject) {
  23. auto* ptr = reinterpret_cast<espurna::api::Request*>(req->_tempObject);
  24. delete ptr;
  25. req->_tempObject = nullptr;
  26. }
  27. #endif
  28. state(State::Done);
  29. }
  30. template <typename CallbackType>
  31. void RequestPrint::_callback(CallbackType&& callback) {
  32. if (State::None != state()) {
  33. return;
  34. }
  35. callback(*this);
  36. flush();
  37. }
  38. template<typename CallbackType>
  39. void RequestPrint::scheduleFromRequest(Config config, AsyncWebServerRequest* request, CallbackType callback) {
  40. static_assert(
  41. traits::is_print_callable<CallbackType>::value,
  42. "CallbackType needs to be a callable with void(Print&)");
  43. // because of async nature of the server, we need to make sure we outlive 'request' object
  44. auto print = std::shared_ptr<RequestPrint>(
  45. new RequestPrint(config, request));
  46. // attach one ptr to onDisconnect capture, so we can detect disconnection before scheduled function runs
  47. request->onDisconnect(
  48. [print]() {
  49. print->_onDisconnect();
  50. });
  51. // attach another capture to the scheduled function, so we execute as soon as we exit next loop()
  52. espurnaRegisterOnce(
  53. [callback, print]() {
  54. print->_callback(callback);
  55. });
  56. }
  57. static constexpr auto DefaultConfig = Config{
  58. .mimeType = "text/plain",
  59. .backlog = {
  60. .count = 2,
  61. .size = TCP_MSS,
  62. .timeout = duration::Seconds(5)
  63. },
  64. };
  65. template <typename CallbackType>
  66. void RequestPrint::scheduleFromRequest(AsyncWebServerRequest* request, CallbackType callback) {
  67. RequestPrint::scheduleFromRequest(DefaultConfig, request, callback);
  68. }
  69. } // namespace print
  70. } // namespace web
  71. } // namespace espurna