| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- // AsyncJson.h
- /*
- Async Response to use with ArduinoJson and AsyncWebServer
- Written by Andrew Melvin (SticilFace) with help from me-no-dev and BBlanchon.
- Example of callback in use
- server.on("/json", HTTP_ANY, [](AsyncWebServerRequest * request) {
- AsyncJsonResponse * response = new AsyncJsonResponse();
- JsonObject& root = response->getRoot();
- root["key1"] = "key number one";
- JsonObject& nested = root.createNestedObject("nested");
- nested["key1"] = "key number one";
- response->setLength();
- request->send(response);
- });
- --------------------
- Async Request to use with ArduinoJson and AsyncWebServer
- Written by Arsène von Wyss (avonwyss)
- Example
- AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/rest/endpoint");
- handler->onRequest([](AsyncWebServerRequest *request, JsonVariant &json) {
- JsonObject& jsonObj = json.as<JsonObject>();
- // ...
- });
- server.addHandler(handler);
-
- */
- #ifndef ASYNC_JSON_H_
- #define ASYNC_JSON_H_
- #include <ArduinoJson.h>
- #include <ESPAsyncWebServer.h>
- #include <Print.h>
- #if ARDUINOJSON_VERSION_MAJOR == 5
- #define ARDUINOJSON_5_COMPATIBILITY
- #else
- #ifndef DYNAMIC_JSON_DOCUMENT_SIZE
- #define DYNAMIC_JSON_DOCUMENT_SIZE 1024
- #endif
- #endif
- constexpr const char* JSON_MIMETYPE = "application/json";
- /*
- * Json Response
- * */
- class ChunkPrint : public Print {
- private:
- uint8_t* _destination;
- size_t _to_skip;
- size_t _to_write;
- size_t _pos;
- public:
- ChunkPrint(uint8_t* destination, size_t from, size_t len)
- : _destination(destination), _to_skip(from), _to_write(len), _pos{0} {}
- virtual ~ChunkPrint(){}
- size_t write(uint8_t c){
- if (_to_skip > 0) {
- _to_skip--;
- return 1;
- } else if (_to_write > 0) {
- _to_write--;
- _destination[_pos++] = c;
- return 1;
- }
- return 0;
- }
- size_t write(const uint8_t *buffer, size_t size)
- {
- return this->Print::write(buffer, size);
- }
- };
- class AsyncJsonResponse: public AsyncAbstractResponse {
- protected:
- #ifdef ARDUINOJSON_5_COMPATIBILITY
- DynamicJsonBuffer _jsonBuffer;
- #else
- DynamicJsonDocument _jsonBuffer;
- #endif
- JsonVariant _root;
- bool _isValid;
- public:
- #ifdef ARDUINOJSON_5_COMPATIBILITY
- AsyncJsonResponse(bool isArray=false): _isValid{false} {
- _code = 200;
- _contentType = JSON_MIMETYPE;
- if(isArray)
- _root = _jsonBuffer.createArray();
- else
- _root = _jsonBuffer.createObject();
- }
- #else
- AsyncJsonResponse(bool isArray=false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE) : _jsonBuffer(maxJsonBufferSize), _isValid{false} {
- _code = 200;
- _contentType = JSON_MIMETYPE;
- if(isArray)
- _root = _jsonBuffer.createNestedArray();
- else
- _root = _jsonBuffer.createNestedObject();
- }
- #endif
- ~AsyncJsonResponse() {}
- JsonVariant & getRoot() { return _root; }
- bool _sourceValid() const { return _isValid; }
- size_t setLength() {
- #ifdef ARDUINOJSON_5_COMPATIBILITY
- _contentLength = _root.measureLength();
- #else
- _contentLength = measureJson(_root);
- #endif
- if (_contentLength) { _isValid = true; }
- return _contentLength;
- }
- size_t getSize() { return _jsonBuffer.size(); }
- size_t _fillBuffer(uint8_t *data, size_t len){
- ChunkPrint dest(data, _sentLength, len);
- #ifdef ARDUINOJSON_5_COMPATIBILITY
- _root.printTo( dest ) ;
- #else
- serializeJson(_root, dest);
- #endif
- return len;
- }
- };
- class PrettyAsyncJsonResponse: public AsyncJsonResponse {
- public:
- #ifdef ARDUINOJSON_5_COMPATIBILITY
- PrettyAsyncJsonResponse (bool isArray=false) : AsyncJsonResponse{isArray} {}
- #else
- PrettyAsyncJsonResponse (bool isArray=false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE) : AsyncJsonResponse{isArray, maxJsonBufferSize} {}
- #endif
- size_t setLength () {
- #ifdef ARDUINOJSON_5_COMPATIBILITY
- _contentLength = _root.measurePrettyLength ();
- #else
- _contentLength = measureJsonPretty(_root);
- #endif
- if (_contentLength) {_isValid = true;}
- return _contentLength;
- }
- size_t _fillBuffer (uint8_t *data, size_t len) {
- ChunkPrint dest (data, _sentLength, len);
- #ifdef ARDUINOJSON_5_COMPATIBILITY
- _root.prettyPrintTo (dest);
- #else
- serializeJsonPretty(_root, dest);
- #endif
- return len;
- }
- };
- typedef std::function<void(AsyncWebServerRequest *request, JsonVariant &json)> ArJsonRequestHandlerFunction;
- class AsyncCallbackJsonWebHandler: public AsyncWebHandler {
- private:
- protected:
- const String _uri;
- WebRequestMethodComposite _method;
- ArJsonRequestHandlerFunction _onRequest;
- size_t _contentLength;
- #ifndef ARDUINOJSON_5_COMPATIBILITY
- const size_t maxJsonBufferSize;
- #endif
- size_t _maxContentLength;
- public:
- #ifdef ARDUINOJSON_5_COMPATIBILITY
- AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest)
- : _uri(uri), _method(HTTP_POST|HTTP_PUT|HTTP_PATCH), _onRequest(onRequest), _maxContentLength(16384) {}
- #else
- AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest, size_t maxJsonBufferSize=DYNAMIC_JSON_DOCUMENT_SIZE)
- : _uri(uri), _method(HTTP_POST|HTTP_PUT|HTTP_PATCH), _onRequest(onRequest), maxJsonBufferSize(maxJsonBufferSize), _maxContentLength(16384) {}
- #endif
-
- void setMethod(WebRequestMethodComposite method){ _method = method; }
- void setMaxContentLength(int maxContentLength){ _maxContentLength = maxContentLength; }
- void onRequest(ArJsonRequestHandlerFunction fn){ _onRequest = fn; }
- virtual bool canHandle(AsyncWebServerRequest *request) override final{
- if(!_onRequest)
- return false;
- if(!(_method & request->method()))
- return false;
- if(_uri.length() && (_uri != request->url() && !request->url().startsWith(_uri+"/")))
- return false;
- if ( !request->contentType().equalsIgnoreCase(JSON_MIMETYPE) )
- return false;
- request->addInterestingHeader("ANY");
- return true;
- }
- virtual void handleRequest(AsyncWebServerRequest *request) override final {
- if(_onRequest) {
- if (request->_tempObject != NULL) {
- #ifdef ARDUINOJSON_5_COMPATIBILITY
- DynamicJsonBuffer jsonBuffer;
- JsonVariant json = jsonBuffer.parse((uint8_t*)(request->_tempObject));
- if (json.success()) {
- #else
- DynamicJsonDocument jsonBuffer(this->maxJsonBufferSize);
- DeserializationError error = deserializeJson(jsonBuffer, (uint8_t*)(request->_tempObject));
- if(!error) {
- JsonVariant json = jsonBuffer.as<JsonVariant>();
- #endif
- _onRequest(request, json);
- return;
- }
- }
- request->send(_contentLength > _maxContentLength ? 413 : 400);
- } else {
- request->send(500);
- }
- }
- virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final {
- }
- virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override final {
- if (_onRequest) {
- _contentLength = total;
- if (total > 0 && request->_tempObject == NULL && total < _maxContentLength) {
- request->_tempObject = malloc(total);
- }
- if (request->_tempObject != NULL) {
- memcpy((uint8_t*)(request->_tempObject) + index, data, len);
- }
- }
- }
- virtual bool isRequestHandlerTrivial() override final {return _onRequest ? false : true;}
- };
- #endif
|