|
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