/* Part of the WEBSERVER MODULE Copyright (C) 2016-2019 by Xose PĂ©rez */ #pragma once #include "web.h" #include "api.h" #include "libs/TypeChecks.h" namespace espurna { namespace web { namespace print { namespace traits { template using print_callable_t = decltype(std::declval()(std::declval())); template using is_print_callable = is_detected; } // namespace traits void RequestPrint::_onDisconnect() { #if API_SUPPORT // TODO: in case this comes from `apiRegister`'ed endpoint, there's still a lingering ApiRequestHelper that we must remove auto* req = request(); if (req->_tempObject) { auto* ptr = reinterpret_cast(req->_tempObject); delete ptr; req->_tempObject = nullptr; } #endif state(State::Done); } template void RequestPrint::_callback(CallbackType&& callback) { if (State::None != state()) { return; } callback(*this); flush(); } template void RequestPrint::scheduleFromRequest(Config config, AsyncWebServerRequest* request, CallbackType callback) { static_assert( traits::is_print_callable::value, "CallbackType needs to be a callable with void(Print&)"); // because of async nature of the server, we need to make sure we outlive 'request' object auto print = std::shared_ptr( new RequestPrint(config, request)); // attach one ptr to onDisconnect capture, so we can detect disconnection before scheduled function runs request->onDisconnect( [print]() { print->_onDisconnect(); }); // attach another capture to the scheduled function, so we execute as soon as we exit next loop() espurnaRegisterOnce( [callback, print]() { print->_callback(callback); }); } static constexpr auto DefaultConfig = Config{ .mimeType = "text/plain", .backlog = { .count = 2, .size = TCP_MSS, .timeout = duration::Seconds(5) }, }; template void RequestPrint::scheduleFromRequest(AsyncWebServerRequest* request, CallbackType callback) { RequestPrint::scheduleFromRequest(DefaultConfig, request, callback); } } // namespace print } // namespace web } // namespace espurna