ESPAsyncWebServer icon indicating copy to clipboard operation
ESPAsyncWebServer copied to clipboard

400 Bad Request Error for Large JSON Requests

Open ali80 opened this issue 2 years ago • 5 comments

Description

I am encountering a 400 Bad Request error for JSON requests that are larger than a certain size. The code never reaches the callback and it seems to throw 400 error before that, probably in the request JSON parsing step.

Sample JSON that causes the issue ```json { "id": 0, "src": "50B4472BFE1F2AF5", "params": { "mid": "50B4472BFE1F2AF5", "t": "config", "rc": 4, "relays": [ { "name": "out1", "thr": 25, "hys": 1, "ac": 2, "inv": 0, "ic": 15 }, { "name": "out2", "thr": 0, "hys": 0, "ac": 0, "inv": 0, "ic": 10 }, { "name": "out3", "thr": 0, "hys": 0, "ac": 0, "inv": 0, "ic": 8 }, { "name": "ou4", "thr": 0, "hys": 0, "ac": 0, "inv": 0, "ic": 12 }, { "name": "ou5", "thr": 0, "hys": 0, "ac": 0, "inv": 0, "ic": 12 }, { "name": "out6", "thr": 0, "hys": 0, "ac": 0, "inv": 0, "ic": 12 }, { "name": "out7", "thr": 0, "hys": 0, "ac": 0, "inv": 0, "ic": 12 }, { "name": "out8", "thr": 0, "hys": 0, "ac": 0, "inv": 0, "ic": 12 } ], "sc": 1, "type": 7, "nodeName": "mynode", "v": "1.22+00", "network": 1, "tz_off": 3600 } } ```

The JSON is sent in compressed format and its size is 613 bytes. For smaller requests, there is no error.

Code

Here is the relevant code:

server.addHandler(Routes::rpc_post());
...
AsyncCallbackJsonWebHandler* Routes::rpc_post() { return _rpc_post; }

AsyncCallbackJsonWebHandler* _rpc_post
    = new AsyncCallbackJsonWebHandler(ROUTE_RPC, [](AsyncWebServerRequest* request, JsonVariant& json) {
          auto jsonObj = json.as<JsonObject>();
          AsyncJsonResponse* response = new AsyncJsonResponse(false, 2048);
          if (!response) {
              request->send(500, "application/json", "{\"error\":{\"message\":\"aloc error\"}}");
              log_c(2, MODULE "aloc error");
              return;
          }
          auto root = response->getRoot();
          root["res"] = "ok";
          response->setLength();
          request->send(response);
      });

Error message

The error message is: "400 Bad Request Error"

Expected outcome

I expect the JSON request to be processed successfully without encountering a 400 Bad Request error.

ali80 avatar Feb 01 '23 08:02 ali80

We're having the same issue. Are there any news on this?

1cue-jrupp avatar Apr 19 '23 12:04 1cue-jrupp

[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jun 18 '23 13:06 stale[bot]

I am having the same issue...

Hoogkamer avatar Jul 30 '23 07:07 Hoogkamer

[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future.

stale[bot] avatar Jul 30 '23 07:07 stale[bot]

This is how I solved it, apparently the data is sent in chunks.

File stationsFile;
server.on(
      "/post",
      HTTP_POST,
      [](AsyncWebServerRequest *request) {},
      NULL,
      [](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total)
      {
        if (index == 0)
        {
          stationsFile = SPIFFS.open("/stations.json", "w");
          Serial.println("opening file");
        }
        for (size_t i = 0; i < len; i++)
        {
          Serial.write(data[i]);
          stationsFile.write(data[i]);
        }
        if ((len + index) == total)
        {
          stationsFile.close();
          Serial.println("closing file");
        }

        request->send(200);
      });

Hoogkamer avatar Jul 30 '23 11:07 Hoogkamer

In AsyncCallbackJsonWebHandler, there are two main limits to be aware of:

  1. HTTP Content Length: This defines the maximum size of the HTTP request content that the server will accept. The default value is 16384 bytes (16 KB).
  2. JSON Buffer Size: This defines the maximum size of the JSON payload that can be parsed. The default value is 1024 bytes (1 KB), which might be too low for larger JSON requests. To handle larger JSON payloads, you need to increase the JSON buffer size. Here’s how you can do it:
const size_t jsonBufferSize = 4096;
AsyncCallbackJsonWebHandler* _rpc_post
    = new AsyncCallbackJsonWebHandler(ROUTE_RPC, [](AsyncWebServerRequest* request, JsonVariant& json) {
          auto jsonObj = json.as<JsonObject>();
          AsyncJsonResponse* response = new AsyncJsonResponse(false, 2048);
          if (!response) {
              request->send(500, "application/json", "{\"error\":{\"message\":\"aloc error\"}}");
              log_c(2, MODULE "aloc error");
              return;
          }
          auto root = response->getRoot();
          root["res"] = "ok";
          response->setLength();
          request->send(response);
      }, jsonBufferSize );

ali80 avatar May 16 '24 09:05 ali80