forked from me-no-dev/ESPAsyncWebServer
* Added handler for correct JSON deserialization (even with multiple body data writes), addresses #195 * Fixed typo * Added JSON handler example to readme * Moved Json Handler uri parameter to constructor * Use request->_tempObject for JSON char data buffer * Moved onRequest to constructor in JSON async handler
This commit is contained in:
committed by
Me No Dev
parent
fc66fae6a9
commit
d7399a7664
15
README.md
15
README.md
@@ -30,6 +30,7 @@ To use this library you might need to have the latest git versions of [ESP32](ht
|
|||||||
- [GET, POST and FILE parameters](#get-post-and-file-parameters)
|
- [GET, POST and FILE parameters](#get-post-and-file-parameters)
|
||||||
- [FILE Upload handling](#file-upload-handling)
|
- [FILE Upload handling](#file-upload-handling)
|
||||||
- [Body data handling](#body-data-handling)
|
- [Body data handling](#body-data-handling)
|
||||||
|
- [JSON body handling with ArduinoJson](#json-body-handling-with-arduinojson)
|
||||||
- [Responses](#responses)
|
- [Responses](#responses)
|
||||||
- [Redirect to another URL](#redirect-to-another-url)
|
- [Redirect to another URL](#redirect-to-another-url)
|
||||||
- [Basic response with HTTP Code](#basic-response-with-http-code)
|
- [Basic response with HTTP Code](#basic-response-with-http-code)
|
||||||
@@ -313,6 +314,20 @@ void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
If needed, the `_tempObject` field on the request can be used to store a pointer to temporary data (e.g. from the body) associated with the request. If assigned, the pointer will automatically be freed along with the request.
|
||||||
|
|
||||||
|
### JSON body handling with ArduinoJson
|
||||||
|
Endpoints which consume JSON can use a special handler to get ready to use JSON data in the request callback:
|
||||||
|
```cpp
|
||||||
|
#include "AsyncJson.h"
|
||||||
|
#include "ArduinoJson.h"
|
||||||
|
|
||||||
|
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/rest/endpoint", [](AsyncWebServerRequest *request, JsonVariant &json) {
|
||||||
|
JsonObject& jsonObj = json.as<JsonObject>();
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
server.addHandler(handler);
|
||||||
|
```
|
||||||
|
|
||||||
## Responses
|
## Responses
|
||||||
### Redirect to another URL
|
### Redirect to another URL
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
// ESPasyncJson.h
|
// AsyncJson.h
|
||||||
/*
|
/*
|
||||||
Async Response to use with arduinoJson and asyncwebserver
|
Async Response to use with ArduinoJson and AsyncWebServer
|
||||||
Written by Andrew Melvin (SticilFace) with help from me-no-dev and BBlanchon.
|
Written by Andrew Melvin (SticilFace) with help from me-no-dev and BBlanchon.
|
||||||
|
|
||||||
example of callback in use
|
Example of callback in use
|
||||||
|
|
||||||
server.on("/json", HTTP_ANY, [](AsyncWebServerRequest * request) {
|
server.on("/json", HTTP_ANY, [](AsyncWebServerRequest * request) {
|
||||||
|
|
||||||
@@ -17,11 +17,27 @@
|
|||||||
request->send(response);
|
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_
|
#ifndef ASYNC_JSON_H_
|
||||||
#define ASYNC_JSON_H_
|
#define ASYNC_JSON_H_
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
const char* JSON_MIMETYPE = "application/json";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Json Response
|
* Json Response
|
||||||
* */
|
* */
|
||||||
@@ -57,7 +73,7 @@ class AsyncJsonResponse: public AsyncAbstractResponse {
|
|||||||
public:
|
public:
|
||||||
AsyncJsonResponse(bool isArray=false): _isValid{false} {
|
AsyncJsonResponse(bool isArray=false): _isValid{false} {
|
||||||
_code = 200;
|
_code = 200;
|
||||||
_contentType = "application/json";
|
_contentType = JSON_MIMETYPE;
|
||||||
if(isArray)
|
if(isArray)
|
||||||
_root = _jsonBuffer.createArray();
|
_root = _jsonBuffer.createArray();
|
||||||
else
|
else
|
||||||
@@ -80,4 +96,68 @@ class AsyncJsonResponse: public AsyncAbstractResponse {
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::function<void(AsyncWebServerRequest *request, JsonVariant &json)> ArJsonRequestHandlerFunction;
|
||||||
|
|
||||||
|
class AsyncCallbackJsonWebHandler: public AsyncWebHandler {
|
||||||
|
private:
|
||||||
|
protected:
|
||||||
|
const String _uri;
|
||||||
|
WebRequestMethodComposite _method;
|
||||||
|
ArJsonRequestHandlerFunction _onRequest;
|
||||||
|
int _contentLength;
|
||||||
|
int _maxContentLength;
|
||||||
|
public:
|
||||||
|
AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest) : _uri(uri), _method(HTTP_POST|HTTP_PUT|HTTP_PATCH), _onRequest(onRequest), _maxContentLength(16384) {}
|
||||||
|
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) {
|
||||||
|
DynamicJsonBuffer jsonBuffer;
|
||||||
|
JsonVariant json = jsonBuffer.parse((uint8_t*)(request->_tempObject));
|
||||||
|
if (json.success()) {
|
||||||
|
_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
|
#endif
|
||||||
|
Reference in New Issue
Block a user