Skip to content

Commit 426aea1

Browse files
committed
Cleanup proposal fix for
#183
1 parent 175880d commit 426aea1

File tree

2 files changed

+57
-68
lines changed

2 files changed

+57
-68
lines changed

examples/Json/Json.ino

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,27 @@ void setup() {
6363
JsonObject root = doc.to<JsonObject>();
6464
root["foo"] = "bar";
6565
serializeJson(root, *response);
66+
Serial.println();
6667
request->send(response);
6768
});
6869

6970
// curl -v -X POST -H 'Content-Type: application/json' -d '{"name":"You"}' http://192.168.4.1/json2
7071
// curl -v -X PUT -H 'Content-Type: application/json' -d '{"name":"You"}' http://192.168.4.1/json2
72+
//
73+
// edge cases:
74+
//
75+
// curl -v -X POST -H "Content-Type: application/json" -d "1234" -H "Content-Length: 5" http://192.168.4.1/json2 => rx timeout
76+
// curl -v -X POST -H "Content-Type: application/json" -d "1234" -H "Content-Length: 2" http://192.168.4.1/json2 => 12
77+
// curl -v -X POST -H "Content-Type: application/json" -d "1234" -H "Content-Length: 4" http://192.168.4.1/json2 => 1234
78+
// curl -v -X POST -H "Content-Type: application/json" -d "1234" -H "Content-Length: 10" http://192.168.4.1/json2 => rx timeout
79+
// curl -v -X POST -H "Content-Type: application/json" -d "12345678" -H "Content-Length: 8" http://192.168.4.1/json2 => 12345678
80+
// curl -v -X POST -H "Content-Type: application/json" -d "123456789" -H "Content-Length: 8" http://192.168.4.1/json2 => 12345678
81+
// curl -v -X POST -H "Content-Type: application/json" -d "123456789" -H "Content-Length: 9" http://192.168.4.1/json2 => 413: Content length exceeds maximum allowed
82+
handler->setMaxContentLength(8);
7183
handler->setMethod(HTTP_POST | HTTP_PUT);
7284
handler->onRequest([](AsyncWebServerRequest *request, JsonVariant &json) {
7385
serializeJson(json, Serial);
86+
Serial.println();
7487
AsyncJsonResponse *response = new AsyncJsonResponse();
7588
JsonObject root = response->getRoot().to<JsonObject>();
7689
root["hello"] = json.as<JsonObject>()["name"];

src/AsyncJson.cpp

Lines changed: 44 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,6 @@
55

66
#if ASYNC_JSON_SUPPORT == 1
77

8-
typedef struct {
9-
size_t length; // the size we can write into "content", not including null termination
10-
uint8_t content
11-
[1]; // this will be of size "content-length" + 1 byte to guarantee that the content is null terminated. null termination is needed for ArduinoJson 5
12-
} AsyncJsonResponseBuffer;
13-
148
#if ARDUINOJSON_VERSION_MAJOR == 5
159
AsyncJsonResponse::AsyncJsonResponse(bool isArray) : _isValid{false} {
1610
_code = 200;
@@ -119,95 +113,77 @@ bool AsyncCallbackJsonWebHandler::canHandle(AsyncWebServerRequest *request) cons
119113

120114
void AsyncCallbackJsonWebHandler::handleRequest(AsyncWebServerRequest *request) {
121115
if (_onRequest) {
116+
// GET request:
122117
if (request->method() == HTTP_GET) {
123118
JsonVariant json;
124119
_onRequest(request, json);
125120
return;
126121
}
127-
// this is not a GET
128-
// check if json body is too large, if it is, don't deserialize
122+
123+
// POST / PUT / ... requests:
124+
// check if JSON body is too large, if it is, don't deserialize
129125
if (request->contentLength() > _maxContentLength) {
126+
#ifdef ESP32
127+
log_e("Content length exceeds maximum allowed");
128+
#endif
130129
request->send(413);
131130
return;
132131
}
133132

134-
// try to parse body as JSON
135-
if (request->_tempObject != NULL) // see if we succeeded allocating a buffer earlier
136-
{
137-
AsyncJsonResponseBuffer *buffer = (AsyncJsonResponseBuffer *)request->_tempObject;
133+
if (request->_tempObject == NULL) {
134+
// there is no body
135+
request->send(400);
136+
return;
137+
}
138+
138139
#if ARDUINOJSON_VERSION_MAJOR == 5
139-
DynamicJsonBuffer jsonBuffer;
140-
buffer->content[buffer->length] = '\0'; // null terminate, assume we allocated one extra char
141-
// parse can only get null terminated strings as parameters
142-
JsonVariant json = jsonBuffer.parse(buffer->content);
143-
if (json.success()) {
140+
DynamicJsonBuffer jsonBuffer;
141+
JsonVariant json = jsonBuffer.parse((const char *)request->_tempObject);
142+
if (json.success()) {
144143
#elif ARDUINOJSON_VERSION_MAJOR == 6
145-
DynamicJsonDocument jsonBuffer(this->maxJsonBufferSize); // content with length > this->maxJsonBufferSize might not get deserialized
146-
DeserializationError error = deserializeJson(jsonBuffer, buffer->content, buffer->length);
147-
if (!error) {
148-
JsonVariant json = jsonBuffer.as<JsonVariant>();
144+
DynamicJsonDocument jsonBuffer(this->maxJsonBufferSize);
145+
DeserializationError error = deserializeJson(jsonBuffer, (const char *)request->_tempObject);
146+
if (!error) {
147+
JsonVariant json = jsonBuffer.as<JsonVariant>();
149148
#else
150-
JsonDocument jsonBuffer;
151-
// deserializeJson expects a null terminated string or a pointer plus length
152-
DeserializationError error = deserializeJson(jsonBuffer, buffer->content, buffer->length);
153-
if (!error) {
154-
JsonVariant json = jsonBuffer.as<JsonVariant>();
149+
JsonDocument jsonBuffer;
150+
DeserializationError error = deserializeJson(jsonBuffer, (const char *)request->_tempObject);
151+
if (!error) {
152+
JsonVariant json = jsonBuffer.as<JsonVariant>();
155153
#endif
156154

157-
_onRequest(request, json);
158-
return;
159-
}
160-
// free buffer, we are done with it, so release memory ASAP
161-
free(request->_tempObject);
162-
request->_tempObject = NULL;
155+
_onRequest(request, json);
156+
} else {
157+
// error parsing the body
158+
request->send(400);
163159
}
164-
// there is no body, no buffer or we had an error parsing the body
165-
request->send(400);
166-
} else { // if no _onRequest
167-
request->send(500);
168160
}
169161
}
170162

171163
void AsyncCallbackJsonWebHandler::handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {
172164
if (_onRequest) {
173-
if (index == 0) // on first piece
174-
{
175-
// check nobody has already allocated the buffer
176-
if (request->_tempObject != NULL) {
177-
#ifdef ESP32
178-
log_e("Temp object already in use");
179-
#endif
180-
return; // do nothing else here, handleRequest will return a HTTP error
181-
}
182-
// check total size is valid
183-
if (total >= _maxContentLength) {
184-
return; // do nothing else here, handleRequest will return a HTTP error
185-
}
186-
// allocate buffer
187-
request->_tempObject = calloc(
188-
1, sizeof(AsyncJsonResponseBuffer) + total
189-
); // normally _tempObject will be "free"ed by the destructor of the request, but can release earlier if desired.
190-
if (request->_tempObject == NULL) { // if allocation failed
165+
// ignore callback if size is larger than maxContentLength
166+
if (total > _maxContentLength) {
167+
return;
168+
}
169+
170+
if (index == 0) {
171+
// this check allows request->_tempObject to be initialized from a middleware
172+
if (request->_tempObject == NULL) {
173+
request->_tempObject = calloc(total + 1, sizeof(uint8_t)); // null-terminated string
174+
if (request->_tempObject == NULL) {
191175
#ifdef ESP32
192-
log_e("Failed to allocate");
176+
log_e("Failed to allocate");
193177
#endif
194-
return; // do nothing else here, handleRequest will return a HTTP error
178+
request->abort();
179+
return;
180+
}
195181
}
196-
((AsyncJsonResponseBuffer *)request->_tempObject)->length = total; // store the size of allocation we made into _tempObject
197182
}
198183

199-
// add data to the buffer if the buffer exists
200184
if (request->_tempObject != NULL) {
201-
AsyncJsonResponseBuffer *buffer = (AsyncJsonResponseBuffer *)request->_tempObject;
202-
// check if the buffer is the right size so we don't write out of bounds
203-
if (buffer->length >= total && buffer->length >= index + len) {
204-
memcpy(buffer->content + index, data, len);
205-
} else {
206-
#ifdef ESP32
207-
log_e("Bad size of temp buffer");
208-
#endif
209-
return; // do nothing else here
210-
}
185+
uint8_t *buffer = (uint8_t *)request->_tempObject;
186+
memcpy(buffer + index, data, len);
211187
}
212188
}
213189
}

0 commit comments

Comments
 (0)