[SoftAP] HTTP POST requests not getting through to callback routine

I’m trying to upgrade a project to use the SoftAP interface on a shiny new Photon. After the initial frustration, so far so good–I’ve gotten the Photon serving the webpage fairly reliably. (Other issues can be sorted out another time–sometimes the web browser loads the page REALLY slow and/or the Photon just doesn’t send the whole page, etc.) FYI I am NOT using the SoftAP WiFi setup page at all…just a simple in-house HTML form.

However, when I click the “Submit” button on the HTML form, the browser (Firefox on Windows 7) hangs on “Connecting…” I put some debug code in the SoftAP callback, and the HTTP POST request never appears–almost like “POST” requests of any sort are reserved for the internal WiFi setup, which I’m not using at all. HTTP GET requests go right through to the callback routine. I know that my HTML page works just fine–I originally wrote it for the Core and the TCPServer/TCPClient pair, and it worked perfectly. The browser sends the POST request alright…it just doesn’t trigger the SoftAP callback routine. Any suggestions?

Have you got your code to show?
Are you using SYSTEM_THREAD(ENABLED)?
You are aware that you’re in Listening Mode when using SoftAP and hence slightly different rules apply?
Or have you been building with a local toolchain and a firmware branch that already grants user application code full access to SoftAP?

  Writer* Webpage;
  int ActivityTimer;
  Timer apTimer(30000, APTimeout);    // first connect delay.

  void APPageHandler(const char* url, ResponseCallback* cb, void* cbArg, Reader* body, Writer* result, void* reserved)
  {
    Serial.print("URL: ");
    Serial.println(url);

    cb(cbArg, 0, 200, "text/html", nullptr);
    Webpage = result;   // so we can write to it via external routines

    if (strcmp(url,"/d") == 0) SendData();

    // Main page
    if (strcmp(url, "/index") == 0) SendWebpage();

    // POST settings
    if (strcmp(url, "/cfg") == 0)
    {
      char* data = body->fetch_as_string();
      Serial.print("POST Data: ");
      Serial.println(data);
      DoPOST(data);
      // free the data! IMPORTANT!
      free(data);

      WiFi.listen(false);   // exit listen mode
    }

    ActivityTimer = millis();   // reset timeout timer.
  }

  STARTUP(softap_set_application_page_handler(APPageHandler, nullptr));

  //----------------------------------------------------------------------------
  void DoAPPage()
  {
    apTimer.start();                // will time out in 30 seconds
    ActivityTimer = millis();
    WiFi.listen();
    // "LISTEN" blocks until listen mode is exited.
  }

  // Little routine to handle exiting from LISTEN mode if no activity for a prolonged period.
  void APTimeout()
  {
    apTimer.changePeriod(5000);             // interrupt every 5 seconds after the initial 30-second grace period

    if ((millis() - ActivityTimer) > 10000)   // delay for "after connected"
    {
      WiFi.listen(false);
      apTimer.stop();
    }
  }

The output data simply shows accesses to "/index" and "/d". I have never seen any access (of any name/URL, etc.) when I click the form Submit button. Just nothing. All I'm trying to do is utilize the following from the documentation:

[quote]Retrieving the request data. When the HTTP request contains a request body (such as with a POST request), the Reader object provided by the body parameter can be used
to retrieve the request data. [/quote]

No. Do I need to? I'm perfectly happy with the WiFi.listen instruction blocking, as I'm using a timer to exit LISTEN mode.

Yes, I know that I'm in Listening Mode. Slightly different rules as in what? I'm NOT using TCPServer/TCPClient. My webpage works perfectly on the Core--it is most definitely sending the POST request, but it's just not getting through the SoftAP layer on the Photon.

No, just the Particle Dev IDE. I'd like full access to SoftAP...but without the hassle. Yes, I've done local builds before.

OK, @ScruffR, I know I really didn't give any helpful details above. I seem to have pinned down the source (but not the cause) of the problem. Basically, I modified @randomguy1124's example from here: Using new SoftAP Http pages to configure other settings - #4 by randomguy1124

I can set the HTML FORM to use POST without an issue, as follows:
const char index_html[] = "<html><div align=\"center\"><form action=\"color\" method=\"post\"><input id=\"background-color\" name=\"color\" type=\"color\"/><input type=\"submit\" value=\"Go!\"/></form></div></html>";
The problem arises when I specify the EncType attribute of the HTML FORM bracket to text/plain. There are three valid EncTypes to choose from, as follows:

application/x-www-form-urlencoded

DEFAULT if nothing specified

const char index_html[] = "<html><div align=\"center\"><form action=\"color\" method=\"post\" enctype=\"application/x-www-form-urlencoded\"><input id=\"background-color\" name=\"color\" type=\"color\"/><input type=\"submit\" value=\"Go!\"/></form></div></html>";
(or just omit the "enctype" argument altogether.) My difficulty with this is that I'd have to write a routine to correct all of the %xx hexadecimal escape sequences back into ASCII characters.
Output:

multipart/form-data

const char index_html[] = "<html><div align=\"center\"><form action=\"color\" method=\"post\" enctype=\"multipart/form-data\"><input id=\"background-color\" name=\"color\" type=\"color\"/><input type=\"submit\" value=\"Go!\"/></form></div></html>";
Output debug stream:

I don't know who wants to try to decipher that with a microcontroller, but it's there!

text/plain

const char index_html[] = "<html><div align=\"center\"><form action=\"color\" method=\"post\" enctype=\"text/plain\"><input id=\"background-color\" name=\"color\" type=\"color\"/><input type=\"submit\" value=\"Go!\"/></form></div></html>";
The web browser hangs (waiting for a 200 or 404 response), and the Photon does not indicate anything has happened. THIS IS WHAT I'M TRYING TO USE!

Does this help?

I’ve been experimenting with SoftAP recently and have just tried what you describe and am getting the same effect.

A POST with Content-Type: text/plain doesn’t invoke the page handler. I’ve got a Serial.print at the top of the handler and it doesn’t show anything. I’ve been using Wireshark to see what goes back and forth from my laptop, and can see that the Photon SoftAP does send a 404 but the browser doesn’t recognise it. I wonder whether it’s because the http response hasn’t got a content-length or chunked length of zero so the browser hangs.

This is what I’m seeing on the hanging request/response:

POST /colour HTTP/1.1
Host: 192.168.0.1
User-Agent: Mozilla/5.0 (Windows NT 6.1;
WOW64; rv:47.0) Gecko/20100101 Firefox/47.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://192.168.0.1/colourformplain
Connection: keep-alive
Content-Type: text/plain
Content-Length: 15

color=#966432

HTTP/1.1 404 Not Found
Content-Type: text/html
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Connection: Keep-Alive

If I request a page that doesn’t exist using a GET I get this (which works properly):

GET /sdfsfsdfsdfsfd HTTP/1.1
Host: 192.168.0.1
User-Agent: Mozilla/5.0 (Windows NT 6.1;
WOW64; rv:47.0) Gecko/20100101 Firefox/47.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
 
HTTP/1.1 404 Not Found
X-MYHEADER: testing123bad
Content-Type: text/plain
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Connection: Keep-Alive
Access-Control-Allow-Origin: *
Transfer-Encoding: chunked
 
18
Error 404 Page Not Found
0

The difference here is that my page handler has been invoked. I customised it to add my own header and some friendly text.

If I remove my customisations I get this (which works properly):

GET /sdfsdfsdfsdfsdfsdf HTTP/1.1
Host: 192.168.0.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive

HTTP/1.1 404 Not Found
Content-Type: text/plain
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Connection: Keep-Alive
Access-Control-Allow-Origin: *
Transfer-Encoding: chunked

0

So the two that work correctly both send something that indicates to the browser what to expect in the way of a response body.

Of course, this doesn’t solve your problem, however you might want to reconsider using application/x-www-form-urlencoded because text/plain sends the colour string as “color=#966432” (see first example above) so even if you get text/plain working you’re still faced with decoding a hex string :smile:

At least with that example, you will still have to decode a hex string regardless of which enctype is used. In my case, I gave up and went with application/x-www-form-urlencoded. It's just FAR more of a decoding hassle when you have multiple controls on the form, and particularly if ANY of them return a text value. Basically:

  • All spaces are replaced with "+"
  • Most symbols and other ANSI characters are hex-escaped as in "%23" for "#"
  • Each control is separated with "&"

Compare to text/plain which does no encoding of any kind, and each control is separated with a carriage return (CR/LF). Urlencoded is just plain a lot more work to sort out in code. That is, until this bug is fixed and we can use text/plain. :persevere:

Do we have any feedback or a sign of a resolution for this issue?

I guess the Soft AP isn’t a particularly popular feature if this has been around for over 2 years?

I am attempting to build a none internet connected device with a smartphone based setup. I can do it with query parameters but I am unable to pass anything in the body itself which isn’t ideal!

So I finally came back to my project after 2 years. Redoing it for true SoftAP (wow, sure is nice). All the way to the form POST, only to encounter a mysterious problem. And then to rediscover my post documenting the issue from 2 years ago…still with no solution. :thinking::persevere:

1 Like

And two years i have the same issue

You may approach Broadcom/Cypress/… for that as they are the owners of the WICED framework (providing the SoftAP feature) Particle can only use but not alter.

I understand that WICED are the framework but Particle puts an interface to it. I will go to investigate if the issue are related with this facade to WICED or is ralated to WICED itself.