From bde2fce07b7e0c442b451950de247600bb2742a8 Mon Sep 17 00:00:00 2001 From: Marco Tombesi <32168423+baggior@users.noreply.github.com> Date: Sat, 22 Jun 2019 12:20:31 +0200 Subject: [PATCH] arduino json 6 async web server migration (#491) * arduino json 6 async web server migration * Update .travis.yml fix travis error * Revert "Update .travis.yml" This reverts commit 37d1bf0e71ad21dc502aa632c1df503820686046. * gitignore * test fix travis * fix travis * fix proposed in #487 * fix travis * fix travis * fix travis * fix travis * ARDUINOJSON_5_COMPATIBILITY * replaced to #if ARDUINOJSON_VERSION_MAJOR == 5 * fix * added AsyncWebServer::end() * added AsyncWebServer::end() * Update WebServer.cpp fix * fix typo * fix typo --- .gitignore | 1 + .travis.yml | 17 ++++- README.md | 144 +++++++++++++++++++++------------------- library.json | 2 +- library.properties | 2 +- src/AsyncJson.h | 69 +++++++++++++++++-- src/ESPAsyncWebServer.h | 1 + src/WebServer.cpp | 9 ++- 8 files changed, 166 insertions(+), 79 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..722d5e7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode diff --git a/.travis.yml b/.travis.yml index ce0228f..48d0747 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,10 +3,25 @@ language: bash os: - linux +dist: + - xenial + +addons: + apt: + packages: + - xvfb + +# services: +# - xvfb + + script: - /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16 - - sleep 3 +# - /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -screen 0 1400x900x24 -ac +extension GLX +render; - export DISPLAY=:1.0 + - sleep 3 + - ls -l /tmp/*pid + - wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz - tar xf arduino-1.6.5-linux64.tar.xz - mv arduino-1.6.5 $HOME/arduino_ide diff --git a/README.md b/README.md index 7ec5424..f013dda 100644 --- a/README.md +++ b/README.md @@ -11,76 +11,80 @@ For ESP32 it requires [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) to work To use this library you might need to have the latest git versions of [ESP32](https://github.com/espressif/arduino-esp32) Arduino Core ## Table of contents -- [ESPAsyncWebServer ](#espasyncwebserver-) - - [Installation](#installation) - - [Using PlatformIO](#using-platformio) - - [Why should you care](#why-should-you-care) - - [Important things to remember](#important-things-to-remember) - - [Principles of operation](#principles-of-operation) - - [The Async Web server](#the-async-web-server) - - [Request Life Cycle](#request-life-cycle) - - [Rewrites and how do they work](#rewrites-and-how-do-they-work) - - [Handlers and how do they work](#handlers-and-how-do-they-work) - - [Responses and how do they work](#responses-and-how-do-they-work) - - [Template processing](#template-processing) - - [Libraries and projects that use AsyncWebServer](#libraries-and-projects-that-use-asyncwebserver) - - [Request Variables](#request-variables) - - [Common Variables](#common-variables) - - [Headers](#headers) - - [GET, POST and FILE parameters](#get-post-and-file-parameters) - - [FILE Upload handling](#file-upload-handling) - - [Body data handling](#body-data-handling) - - [JSON body handling with ArduinoJson](#json-body-handling-with-arduinojson) - - [Responses](#responses) - - [Redirect to another URL](#redirect-to-another-url) - - [Basic response with HTTP Code](#basic-response-with-http-code) - - [Basic response with HTTP Code and extra headers](#basic-response-with-http-code-and-extra-headers) - - [Basic response with string content](#basic-response-with-string-content) - - [Basic response with string content and extra headers](#basic-response-with-string-content-and-extra-headers) - - [Send large webpage from PROGMEM](#send-large-webpage-from-progmem) - - [Send large webpage from PROGMEM and extra headers](#send-large-webpage-from-progmem-and-extra-headers) - - [Send large webpage from PROGMEM containing templates](#send-large-webpage-from-progmem-containing-templates) - - [Send large webpage from PROGMEM containing templates and extra headers](#send-large-webpage-from-progmem-containing-templates-and-extra-headers) - - [Send binary content from PROGMEM](#send-binary-content-from-progmem) - - [Respond with content coming from a Stream](#respond-with-content-coming-from-a-stream) - - [Respond with content coming from a Stream and extra headers](#respond-with-content-coming-from-a-stream-and-extra-headers) - - [Respond with content coming from a Stream containing templates](#respond-with-content-coming-from-a-stream-containing-templates) - - [Respond with content coming from a Stream containing templates and extra headers](#respond-with-content-coming-from-a-stream-containing-templates-and-extra-headers) - - [Respond with content coming from a File](#respond-with-content-coming-from-a-file) - - [Respond with content coming from a File and extra headers](#respond-with-content-coming-from-a-file-and-extra-headers) - - [Respond with content coming from a File containing templates](#respond-with-content-coming-from-a-file-containing-templates) - - [Respond with content using a callback](#respond-with-content-using-a-callback) - - [Respond with content using a callback and extra headers](#respond-with-content-using-a-callback-and-extra-headers) - - [Respond with content using a callback containing templates](#respond-with-content-using-a-callback-containing-templates) - - [Respond with content using a callback containing templates and extra headers](#respond-with-content-using-a-callback-containing-templates-and-extra-headers) - - [Chunked Response](#chunked-response) - - [Print to response](#print-to-response) - - [ArduinoJson Basic Response](#arduinojson-basic-response) - - [ArduinoJson Advanced Response](#arduinojson-advanced-response) - - [Serving static files](#serving-static-files) - - [Serving specific file by name](#serving-specific-file-by-name) - - [Serving files in directory](#serving-files-in-directory) - - [Specifying Cache-Control header](#specifying-cache-control-header) - - [Specifying Date-Modified header](#specifying-date-modified-header) - - [Specifying Template Processor callback](#specifying-template-processor-callback) - - [Using filters](#using-filters) - - [Serve different site files in AP mode](#serve-different-site-files-in-ap-mode) - - [Rewrite to different index on AP](#rewrite-to-different-index-on-ap) - - [Serving different hosts](#serving-different-hosts) - - [Bad Responses](#bad-responses) - - [Respond with content using a callback without content length to HTTP/1.0 clients](#respond-with-content-using-a-callback-without-content-length-to-http10-clients) - - [Async WebSocket Plugin](#async-websocket-plugin) - - [Async WebSocket Event](#async-websocket-event) - - [Methods for sending data to a socket client](#methods-for-sending-data-to-a-socket-client) - - [Async Event Source Plugin](#async-event-source-plugin) - - [Setup Event Source on the server](#setup-event-source-on-the-server) - - [Setup Event Source in the browser](#setup-event-source-in-the-browser) - - [Scanning for available WiFi Networks](#scanning-for-available-wifi-networks) - - [Remove handlers and rewrites](#remove-handlers-and-rewrites) - - [Setting up the server](#setting-up-the-server) - - [Setup global and class functions as request handlers](#setup-global-and-class-functions-as-request-handlers) - - [Methods for controlling websocket connections](#methods-for-controlling-websocket-connections) - - [Adding default headers to all responses](#adding-default-headers) +- [ESPAsyncWebServer ![Build Status](https://travis-ci.org/me-no-dev/ESPAsyncWebServer)](#espasyncwebserver-build-statushttpstravis-ciorgme-no-devespasyncwebserver) + - [Table of contents](#table-of-contents) + - [Installation](#installation) + - [Using PlatformIO](#using-platformio) + - [Why should you care](#why-should-you-care) + - [Important things to remember](#important-things-to-remember) + - [Principles of operation](#principles-of-operation) + - [The Async Web server](#the-async-web-server) + - [Request Life Cycle](#request-life-cycle) + - [Rewrites and how do they work](#rewrites-and-how-do-they-work) + - [Handlers and how do they work](#handlers-and-how-do-they-work) + - [Responses and how do they work](#responses-and-how-do-they-work) + - [Template processing](#template-processing) + - [Libraries and projects that use AsyncWebServer](#libraries-and-projects-that-use-asyncwebserver) + - [Request Variables](#request-variables) + - [Common Variables](#common-variables) + - [Headers](#headers) + - [GET, POST and FILE parameters](#get-post-and-file-parameters) + - [FILE Upload handling](#file-upload-handling) + - [Body data handling](#body-data-handling) + - [JSON body handling with ArduinoJson](#json-body-handling-with-arduinojson) + - [Responses](#responses) + - [Redirect to another URL](#redirect-to-another-url) + - [Basic response with HTTP Code](#basic-response-with-http-code) + - [Basic response with HTTP Code and extra headers](#basic-response-with-http-code-and-extra-headers) + - [Basic response with string content](#basic-response-with-string-content) + - [Basic response with string content and extra headers](#basic-response-with-string-content-and-extra-headers) + - [Send large webpage from PROGMEM](#send-large-webpage-from-progmem) + - [Send large webpage from PROGMEM and extra headers](#send-large-webpage-from-progmem-and-extra-headers) + - [Send large webpage from PROGMEM containing templates](#send-large-webpage-from-progmem-containing-templates) + - [Send large webpage from PROGMEM containing templates and extra headers](#send-large-webpage-from-progmem-containing-templates-and-extra-headers) + - [Send binary content from PROGMEM](#send-binary-content-from-progmem) + - [Respond with content coming from a Stream](#respond-with-content-coming-from-a-stream) + - [Respond with content coming from a Stream and extra headers](#respond-with-content-coming-from-a-stream-and-extra-headers) + - [Respond with content coming from a Stream containing templates](#respond-with-content-coming-from-a-stream-containing-templates) + - [Respond with content coming from a Stream containing templates and extra headers](#respond-with-content-coming-from-a-stream-containing-templates-and-extra-headers) + - [Respond with content coming from a File](#respond-with-content-coming-from-a-file) + - [Respond with content coming from a File and extra headers](#respond-with-content-coming-from-a-file-and-extra-headers) + - [Respond with content coming from a File containing templates](#respond-with-content-coming-from-a-file-containing-templates) + - [Respond with content using a callback](#respond-with-content-using-a-callback) + - [Respond with content using a callback and extra headers](#respond-with-content-using-a-callback-and-extra-headers) + - [Respond with content using a callback containing templates](#respond-with-content-using-a-callback-containing-templates) + - [Respond with content using a callback containing templates and extra headers](#respond-with-content-using-a-callback-containing-templates-and-extra-headers) + - [Chunked Response](#chunked-response) + - [Chunked Response containing templates](#chunked-response-containing-templates) + - [Print to response](#print-to-response) + - [ArduinoJson Basic Response](#arduinojson-basic-response) + - [ArduinoJson Advanced Response](#arduinojson-advanced-response) + - [Serving static files](#serving-static-files) + - [Serving specific file by name](#serving-specific-file-by-name) + - [Serving files in directory](#serving-files-in-directory) + - [Serving static files with authentication](#serving-static-files-with-authentication) + - [Specifying Cache-Control header](#specifying-cache-control-header) + - [Specifying Date-Modified header](#specifying-date-modified-header) + - [Specifying Template Processor callback](#specifying-template-processor-callback) + - [Using filters](#using-filters) + - [Serve different site files in AP mode](#serve-different-site-files-in-ap-mode) + - [Rewrite to different index on AP](#rewrite-to-different-index-on-ap) + - [Serving different hosts](#serving-different-hosts) + - [Bad Responses](#bad-responses) + - [Respond with content using a callback without content length to HTTP/1.0 clients](#respond-with-content-using-a-callback-without-content-length-to-http10-clients) + - [Async WebSocket Plugin](#async-websocket-plugin) + - [Async WebSocket Event](#async-websocket-event) + - [Methods for sending data to a socket client](#methods-for-sending-data-to-a-socket-client) + - [Direct access to web socket message buffer](#direct-access-to-web-socket-message-buffer) + - [Async Event Source Plugin](#async-event-source-plugin) + - [Setup Event Source on the server](#setup-event-source-on-the-server) + - [Setup Event Source in the browser](#setup-event-source-in-the-browser) + - [Scanning for available WiFi Networks](#scanning-for-available-wifi-networks) + - [Remove handlers and rewrites](#remove-handlers-and-rewrites) + - [Setting up the server](#setting-up-the-server) + - [Setup global and class functions as request handlers](#setup-global-and-class-functions-as-request-handlers) + - [Methods for controlling websocket connections](#methods-for-controlling-websocket-connections) + - [Adding Default Headers](#adding-default-headers) ## Installation diff --git a/library.json b/library.json index a2f961a..73b5291 100644 --- a/library.json +++ b/library.json @@ -12,7 +12,7 @@ "type": "git", "url": "https://github.com/me-no-dev/ESPAsyncWebServer.git" }, - "version": "1.2.0", + "version": "1.2.1", "license": "LGPL-3.0", "frameworks": "arduino", "platforms": ["espressif8266", "espressif32"], diff --git a/library.properties b/library.properties index 5c144dc..345d308 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ESP Async WebServer -version=1.2.0 +version=1.2.1 author=Me-No-Dev maintainer=Me-No-Dev sentence=Async Web Server for ESP8266 and ESP31B diff --git a/src/AsyncJson.h b/src/AsyncJson.h index 8412159..2fa30d2 100644 --- a/src/AsyncJson.h +++ b/src/AsyncJson.h @@ -35,8 +35,15 @@ #ifndef ASYNC_JSON_H_ #define ASYNC_JSON_H_ #include +#include -constexpr char* JSON_MIMETYPE = "application/json"; +#if ARDUINOJSON_VERSION_MAJOR == 5 + #define ARDUINOJSON_5_COMPATIBILITY +#else + #define DYNAMIC_JSON_DOCUMENT_SIZE 1024 +#endif + +constexpr const char* JSON_MIMETYPE = "application/json"; /* * Json Response @@ -63,14 +70,27 @@ class ChunkPrint : public Print { } return 0; } + size_t write(const uint8_t *buffer, size_t size) + { + return this->Print::write(buffer, size); + } }; class AsyncJsonResponse: public AsyncAbstractResponse { private: + +#ifdef ARDUINOJSON_5_COMPATIBILITY DynamicJsonBuffer _jsonBuffer; +#else + DynamicJsonDocument _jsonBuffer; +#endif + JsonVariant _root; bool _isValid; - public: + + public: + +#ifdef ARDUINOJSON_5_COMPATIBILITY AsyncJsonResponse(bool isArray=false): _isValid{false} { _code = 200; _contentType = JSON_MIMETYPE; @@ -79,11 +99,28 @@ class AsyncJsonResponse: public AsyncAbstractResponse { else _root = _jsonBuffer.createObject(); } +#else + AsyncJsonResponse(size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE, bool isArray=false) : _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; } @@ -92,7 +129,12 @@ class AsyncJsonResponse: public AsyncAbstractResponse { 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; } }; @@ -106,9 +148,19 @@ protected: WebRequestMethodComposite _method; ArJsonRequestHandlerFunction _onRequest; int _contentLength; +#ifndef ARDUINOJSON_5_COMPATIBILITY + const size_t maxJsonBufferSize; +#endif int _maxContentLength; public: - 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) {} +#endif + void setMethod(WebRequestMethodComposite method){ _method = method; } void setMaxContentLength(int maxContentLength){ _maxContentLength = maxContentLength; } void onRequest(ArJsonRequestHandlerFunction fn){ _onRequest = fn; } @@ -123,7 +175,7 @@ public: if(_uri.length() && (_uri != request->url() && !request->url().startsWith(_uri+"/"))) return false; - if (!request->contentType().equalsIgnoreCase(JSON_MIMETYPE)) + if ( !request->contentType().equalsIgnoreCase(JSON_MIMETYPE) ) return false; request->addInterestingHeader("ANY"); @@ -133,9 +185,18 @@ public: 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(); +#endif + _onRequest(request, json); return; } diff --git a/src/ESPAsyncWebServer.h b/src/ESPAsyncWebServer.h index de6f0cd..1e77ec6 100644 --- a/src/ESPAsyncWebServer.h +++ b/src/ESPAsyncWebServer.h @@ -393,6 +393,7 @@ class AsyncWebServer { ~AsyncWebServer(); void begin(); + void end(); #if ASYNC_TCP_SSL_ENABLED void onSslFileRequest(AcSSlFileHandler cb, void* arg); diff --git a/src/WebServer.cpp b/src/WebServer.cpp index e6cd0c6..3774634 100644 --- a/src/WebServer.cpp +++ b/src/WebServer.cpp @@ -52,8 +52,9 @@ AsyncWebServer::AsyncWebServer(uint16_t port) } AsyncWebServer::~AsyncWebServer(){ - reset(); - delete _catchAllHandler; + reset(); + end(); + if(_catchAllHandler) delete _catchAllHandler; } AsyncWebRewrite& AsyncWebServer::addRewrite(AsyncWebRewrite* rewrite){ @@ -83,6 +84,10 @@ void AsyncWebServer::begin(){ _server.begin(); } +void AsyncWebServer::end(){ + _server.end(); +} + #if ASYNC_TCP_SSL_ENABLED void AsyncWebServer::onSslFileRequest(AcSSlFileHandler cb, void* arg){ _server.onSslFileRequest(cb, arg);