diff --git a/src/AsyncJson.h b/src/AsyncJson.h index 2fa6a2d2..b7d49c02 100644 --- a/src/AsyncJson.h +++ b/src/AsyncJson.h @@ -30,7 +30,7 @@ // ... }); server.addHandler(handler); - + */ #ifndef ASYNC_JSON_H_ #define ASYNC_JSON_H_ @@ -39,191 +39,246 @@ #include #if ARDUINOJSON_VERSION_MAJOR == 5 - #define ARDUINOJSON_5_COMPATIBILITY +#define ARDUINOJSON_5_COMPATIBILITY #else - #ifndef DYNAMIC_JSON_DOCUMENT_SIZE - #define DYNAMIC_JSON_DOCUMENT_SIZE 1024 - #endif +#ifndef DYNAMIC_JSON_DOCUMENT_SIZE +#define DYNAMIC_JSON_DOCUMENT_SIZE 1024 +#endif #endif -constexpr const char* JSON_MIMETYPE = "application/json"; +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) +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; + virtual ~ChunkPrint() {} + size_t write(uint8_t c) + { + if (_to_skip > 0) + { + _to_skip--; + return 1; } - size_t write(const uint8_t *buffer, size_t size) + else if (_to_write > 0) { - return this->Print::write(buffer, size); + _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: - +class AsyncJsonResponse : public AsyncAbstractResponse +{ +protected: #ifdef ARDUINOJSON_5_COMPATIBILITY - DynamicJsonBuffer _jsonBuffer; + DynamicJsonBuffer _jsonBuffer; #else - DynamicJsonDocument _jsonBuffer; + DynamicJsonDocument _jsonBuffer; #endif - JsonVariant _root; - bool _isValid; - - public: + 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(); - } + 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(); - } + 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() { + ~AsyncJsonResponse() + { + } + JsonVariant &getRoot() { return _root; } + bool _sourceValid() const { return _isValid; } + size_t setLength() + { -#ifdef ARDUINOJSON_5_COMPATIBILITY - _contentLength = _root.measureLength(); +#ifdef ARDUINOJSON_5_COMPATIBILITY + _contentLength = _root.measureLength(); #else - _contentLength = measureJson(_root); + _contentLength = measureJson(_root); #endif - if (_contentLength) { _isValid = true; } - return _contentLength; + if (_contentLength) + { + _isValid = true; } + return _contentLength; + } - size_t getSize() { return _jsonBuffer.size(); } + size_t getSize() { return _jsonBuffer.size(); } - size_t _fillBuffer(uint8_t *data, size_t len){ - ChunkPrint dest(data, _sentLength, len); + size_t _fillBuffer(uint8_t *data, size_t len) + { + ChunkPrint dest(data, _sentLength, len); -#ifdef ARDUINOJSON_5_COMPATIBILITY - _root.printTo( dest ) ; +#ifdef ARDUINOJSON_5_COMPATIBILITY + _root.printTo(dest); #else - serializeJson(_root, dest); + serializeJson(_root, dest); #endif - return len; - } + return len; + } }; -class PrettyAsyncJsonResponse: public AsyncJsonResponse { +class PrettyAsyncJsonResponse : public AsyncJsonResponse +{ public: #ifdef ARDUINOJSON_5_COMPATIBILITY - PrettyAsyncJsonResponse (bool isArray=false) : AsyncJsonResponse{isArray} {} + PrettyAsyncJsonResponse(bool isArray = false) : AsyncJsonResponse{isArray} + { + } #else - PrettyAsyncJsonResponse (bool isArray=false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE) : AsyncJsonResponse{isArray, maxJsonBufferSize} {} + PrettyAsyncJsonResponse(bool isArray = false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE) : AsyncJsonResponse{isArray, maxJsonBufferSize} + { + } #endif - size_t setLength () { + size_t setLength() + { #ifdef ARDUINOJSON_5_COMPATIBILITY - _contentLength = _root.measurePrettyLength (); + _contentLength = _root.measurePrettyLength(); #else - _contentLength = measureJsonPretty(_root); + _contentLength = measureJsonPretty(_root); #endif - if (_contentLength) {_isValid = true;} - return _contentLength; - } - size_t _fillBuffer (uint8_t *data, size_t len) { - ChunkPrint dest (data, _sentLength, len); + 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); + _root.prettyPrintTo(dest); #else - serializeJsonPretty(_root, dest); + serializeJsonPretty(_root, dest); #endif - return len; - } + return len; + } }; typedef std::function ArJsonRequestHandlerFunction; -class AsyncCallbackJsonWebHandler: public AsyncWebHandler { +class AsyncCallbackJsonWebHandler : public AsyncWebHandler +{ private: protected: const String _uri; WebRequestMethodComposite _method; ArJsonRequestHandlerFunction _onRequest; size_t _contentLength; -#ifndef ARDUINOJSON_5_COMPATIBILITY +#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) {} +#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) {} + 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) + void setMethod(WebRequestMethodComposite method) + { + _method = method; + } + void setMaxContentLength(int maxContentLength) { _maxContentLength = maxContentLength; } + void onRequest(ArJsonRequestHandlerFunction fn) { _onRequest = fn; } + + bool startsWithIgnoreCase(const char *a, const char *b) + { + if (a == NULL || b == NULL) + return false; + int i = 0; + while (b[i]) + { + if (a[i] == 0) + return false; + if (tolower(a[i]) != tolower(b[i])) + return false; + ++i; + } + return true; + } + + virtual bool canHandle(AsyncWebServerRequest *request) override final + { + if (!_onRequest) return false; - if(!(_method & request->method())) + if (!(_method & request->method())) return false; - if(_uri.length() && (_uri != request->url() && !request->url().startsWith(_uri+"/"))) + if (_uri.length() && (_uri != request->url() && !request->url().startsWith(_uri + "/"))) return false; - if ( !request->contentType().equalsIgnoreCase(JSON_MIMETYPE) ) + if (!startsWithIgnoreCase(request->contentType().c_str(), JSON_MIMETYPE)) return false; request->addInterestingHeader("ANY"); return true; } - virtual void handleRequest(AsyncWebServerRequest *request) override final { - if(_onRequest) { - if (request->_tempObject != NULL) { + virtual void handleRequest(AsyncWebServerRequest *request) override final + { + if (_onRequest) + { + if (request->_tempObject != NULL) + { -#ifdef ARDUINOJSON_5_COMPATIBILITY +#ifdef ARDUINOJSON_5_COMPATIBILITY DynamicJsonBuffer jsonBuffer; - JsonVariant json = jsonBuffer.parse((uint8_t*)(request->_tempObject)); - if (json.success()) { + 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) { + DeserializationError error = deserializeJson(jsonBuffer, (uint8_t *)(request->_tempObject)); + if (!error) + { JsonVariant json = jsonBuffer.as(); #endif @@ -232,23 +287,30 @@ class AsyncCallbackJsonWebHandler: public AsyncWebHandler { } } request->send(_contentLength > _maxContentLength ? 413 : 400); - } else { + } + 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 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) { + 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) { + if (total > 0 && request->_tempObject == NULL && total < _maxContentLength) + { request->_tempObject = malloc(total); } - if (request->_tempObject != NULL) { - memcpy((uint8_t*)(request->_tempObject) + index, data, len); + if (request->_tempObject != NULL) + { + memcpy((uint8_t *)(request->_tempObject) + index, data, len); } } } - virtual bool isRequestHandlerTrivial() override final {return _onRequest ? false : true;} + virtual bool isRequestHandlerTrivial() override final { return _onRequest ? false : true; } }; #endif