ESP32 Asynch Web Server POST method not working

Viewed 4180

I'm having trouble getting the POST method to work with the ESP32 & the Async Web Server. To be precise, the POST route is recognised but processing of the body fails.

The ESP32 is a WROOM-32. The POST example is adapted from ESP32 Arduino async HTTP server: Serving HTML

The web server and indeed the ESP32 appears to work in every other way I have tried. Although my example below doesn't show it, the GET method works just fine. The problem arises when I try to process the body of the POST request. I have put a comment in the code "Code here is NOT execute" to show what is not working. The simple form "/testform.html" is displayed, but when submitted, the header part of the POST handler shows that the content type is "application/x-www-form-urlencoded", but nothing is returned to the Chrome browser and the print statements intended to show the body of the POST do not execute.

The ESP32 code is as follows (I'm using the Arduino IDE):

#include "WiFi.h"
#include "ESPAsyncWebServer.h"
#include "SPIFFS.h"
 
const char* ssid = "xxxxxx";      // Actual SSID & Pw removed
const char* password = "xxxxxx";
AsyncWebServer server(80);
 
void setup() {
  Serial.begin(115200);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  // Initialize SPIFFS
  if(!SPIFFS.begin(true)) {
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }
  Serial.println(WiFi.localIP());

  server.on("/testform.html", HTTP_GET, [](AsyncWebServerRequest *request) {
    request->send(SPIFFS, "/testform.html", String(), false);
  });
 
  server.on(
    "/my-handling-form-page",
    HTTP_POST,
    [](AsyncWebServerRequest * request) {
        // The following print statements work + removing them makes no difference
        // This is displayed on monitor "Content type::application/x-www-form-urlencoded"
        Serial.print("Content type::");
        Serial.println(request->contentType());
    },  // Route handling function
    
    NULL,
    [](AsyncWebServerRequest * request, uint8_t *data, size_t len, size_t index, size_t total) {

  // *** Code here is NOT executed *** 
    
  for (size_t i = 0; i < len; i++) {
    Serial.write(data[i]);
  }
  Serial.println();
  request->send(200);
  });

  // Start server
  server.begin();
}

void notFound(AsyncWebServerRequest *request) {
  request->send(404, "text/plain", "My not found ***** ");
}
 
void loop()`{
  
}

The "testform.htm" web page, is pretty simple and displays as expected when requested by the browser

<!DOCTYPE html>
<html>
  <head> 
    <b>Test Form</b>
  </head>

  <body>
    <form action="/my-handling-form-page" method="post">
      <ul>
        <li>
          <label for="name">Name:</label>
          <input type="text" id="name" name="user_name">
        </li>
      </ul>
       
      <li class="button">
        <button type="submit">Send your message</button>
      </li>
    </form>
  </body>
</html>

I hope someone can either find the obvious boo-boo or give me a clue to what I might try next.

2 Answers

Adding this here in case it is useful for someone even though the question is old.

It seems that the form of server.on() that you are using doesn't give you access to the POST body. In my testing, I can't see any parameters when using the form you are using.

However: there is a 5-argument version that allows you to attach a body handler. Inside that function, you can read the body byte-for-byte and parse it. Here is an example that uses the ArduinoJSON library.

// in your webserver setup function
server.on("/mypage",HTTP_POST, handleMyPage, nullptr, parseMyPageBody);                        


// callback definition
void parseMyPageBody(AsyncWebServerRequest* req, uint8_t* data, size_t len, size_t index, size_t total) {

    DynamicJsonDocument bodyJSON(1024);
    deserializeJson(bodyJSON, data, len);
    String tag1 = bodyJSON["tag1"];
    String tag2 = bodyJSON["tag2"];

    // rest of code
}

The below code works..

server.on(
    "/post",
    HTTP_POST,
    [](AsyncWebServerRequest * request){
        // The following print statements work + removing them makes no difference
        // This is displayed on monitor "Content type::application/x-www-form-urlencoded"
        Serial.print("Content type::");
        Serial.println(request->contentType());
        Serial.println("OFF hit.");
    String message;
    int params = request->params();
    Serial.printf("%d params sent in\n", params);
    for (int i = 0; i < params; i++)
    {
        AsyncWebParameter *p = request->getParam(i);
        if (p->isFile())
        {
            Serial.printf("_FILE[%s]: %s, size: %u", p->name().c_str(), p->value().c_str(), p->size());
        }
        else if (p->isPost())
        {
            Serial.printf("%s: %s \n", p->name().c_str(), p->value().c_str());
        }
        else
        {
            Serial.printf("_GET[%s]: %s", p->name().c_str(), p->value().c_str());
        }
    }
    
    });
Related