|
5 | 5 |
|
6 | 6 | #if ASYNC_JSON_SUPPORT == 1
|
7 | 7 |
|
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 |
| - |
14 | 8 | #if ARDUINOJSON_VERSION_MAJOR == 5
|
15 | 9 | AsyncJsonResponse::AsyncJsonResponse(bool isArray) : _isValid{false} {
|
16 | 10 | _code = 200;
|
@@ -119,95 +113,77 @@ bool AsyncCallbackJsonWebHandler::canHandle(AsyncWebServerRequest *request) cons
|
119 | 113 |
|
120 | 114 | void AsyncCallbackJsonWebHandler::handleRequest(AsyncWebServerRequest *request) {
|
121 | 115 | if (_onRequest) {
|
| 116 | + // GET request: |
122 | 117 | if (request->method() == HTTP_GET) {
|
123 | 118 | JsonVariant json;
|
124 | 119 | _onRequest(request, json);
|
125 | 120 | return;
|
126 | 121 | }
|
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 |
129 | 125 | if (request->contentLength() > _maxContentLength) {
|
| 126 | +#ifdef ESP32 |
| 127 | + log_e("Content length exceeds maximum allowed"); |
| 128 | +#endif |
130 | 129 | request->send(413);
|
131 | 130 | return;
|
132 | 131 | }
|
133 | 132 |
|
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 | + |
138 | 139 | #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()) { |
144 | 143 | #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>(); |
149 | 148 | #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>(); |
155 | 153 | #endif
|
156 | 154 |
|
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); |
163 | 159 | }
|
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); |
168 | 160 | }
|
169 | 161 | }
|
170 | 162 |
|
171 | 163 | void AsyncCallbackJsonWebHandler::handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {
|
172 | 164 | 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) { |
191 | 175 | #ifdef ESP32
|
192 |
| - log_e("Failed to allocate"); |
| 176 | + log_e("Failed to allocate"); |
193 | 177 | #endif
|
194 |
| - return; // do nothing else here, handleRequest will return a HTTP error |
| 178 | + request->abort(); |
| 179 | + return; |
| 180 | + } |
195 | 181 | }
|
196 |
| - ((AsyncJsonResponseBuffer *)request->_tempObject)->length = total; // store the size of allocation we made into _tempObject |
197 | 182 | }
|
198 | 183 |
|
199 |
| - // add data to the buffer if the buffer exists |
200 | 184 | 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); |
211 | 187 | }
|
212 | 188 | }
|
213 | 189 | }
|
|
0 commit comments