Skip to content

server.send send unexpected argument migrating from 2.4.x to 2.5.2 #6435

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
2 tasks done
Sparatutto opened this issue Aug 22, 2019 · 9 comments · Fixed by #6768 or #8599
Closed
2 tasks done

server.send send unexpected argument migrating from 2.4.x to 2.5.2 #6435

Sparatutto opened this issue Aug 22, 2019 · 9 comments · Fixed by #6768 or #8599
Assignees

Comments

@Sparatutto
Copy link

Basic Infos

  • I have read the documentation at readthedocs and the issue is not addressed there.

  • I have searched the issue tracker for a similar issue.

Platform

  • Hardware: Amica NudeMCU
  • Core Version: 2.5.2 downloaded by Arduino board manager
  • Development Env: Arduino IDE
  • Operating System: Windows

Settings in IDE

attached picture
setting-

Problem Description

I have updated the Arduino IDE to 1.8.9 and the core to 2.5.2 using the board manager ( not the git).
Compiling my project that was working and running very stable with the core 2.4.x now I'm facing some issue related to the number of argument returned by the http communication.
In particular I see an extra argument named plain received by the AP, that was not present and transferred before.
So expected number of arguments (correct in the last compile with 2.4.x) in this example was 3, instead with the new core I get 4.
extraarg

And this is making me crazy because I have many pages and not sure what is happening.

Maybe it is a stupid error of mine but having it in conjunction to the switch to this new core, I try to write you for a check.
Thanks!

MCVE Sketch

#include <ESP8266WebServer.h>
#include <ESP8266WiFi.h>

#define BLUELED 02 

WiFiClient client;
ESP8266WebServer server(80);

void setup() 
{

	/*****************************/
	Serial.begin(115200);
	Serial.setDebugOutput(true);
	delay(10);

	Serial.println("Start! ....");

	Serial.println(F("Access point mode selected"));
	WiFi.mode(WIFI_AP);
	WiFi.softAPConfig(IPAddress(192,168,1,1),IPAddress(192,168,1,1),IPAddress(255,255,255,0));
	WiFi.softAP("MyAPN","12345678");
	Serial.println(F("Access point mode started"));
	IPAddress myIP = WiFi.softAPIP();
	Serial.print(F("AP IP address: "));
	Serial.print(myIP);
	Serial.println(F(" - PWD:12345678"));

	server.on("/", handleRoot);
	server.on("/setting",handleSetting);
	// Start the server
	server.begin(); //server.begin(sysSetting.httpPort);   //
}


void loop() 
{
	server.handleClient();
	digitalWrite(BLUELED,(digitalRead(BLUELED)?LOW:HIGH));
	delay(100);
	return;
}



/******************************************************************************
* Function: debugArgum
*
* Print to the serial the received arguments of the client/server http comm
*
* Parameters:                
*             header and argum set to 'y' means print to serial            
* Return:                 
*             none            
******************************************************************************/
void debugHeaderArgum(char header, char argu)
{
  String argum = "";
  int cnt;
  if(header =='y')
  {
    for (cnt = 0; cnt < server.headers(); cnt++) 
    {
      argum = "HeadArg: " +(String)cnt + " - " + server.headerName(cnt) + " - " + server.header(cnt);
      Serial.println(argum);
    }
  }
  if(argu =='y')
  {
    for (cnt = 0; cnt < server.args(); cnt++) 
    {
      argum = "Arg: " +(String)cnt + " - " + server.argName(cnt) + " - " + server.arg(cnt);
      Serial.println(argum);
    } 
  }
}

void handleRoot() 
{
	String argum = "";
	int cnt = 0;

	debugHeaderArgum('n','n'); //show header and argument

	Serial.println(F("APN - param page"));
	argum = F("HTTP/1.1 301 OK\r\nLocation: /setting\r\nCache-Control: no-cache\r\n\r\n");
	server.sendContent(argum);
	return;
}

/******************************************************************************
* Function: moduleInfo
*
* general module info usable in serial port and http.
*
* Parameters:                
*             httpmode: is true the {t] will be replaced with <DIV> and {-t} with </DIV> otherwise with \r\n             
* Return:                 
*             string containing the info            
******************************************************************************/
String moduleInfo(bool httpMode)
{
	byte mac[6];
	char tmpBuff[100];
	String retString = "\r\n{t}xxx Module: " +(String)ESP.getChipId() + "{-t}\r\n{t}Module ID: 10 - test {-t}\r\n";
	
    WiFi.macAddress(mac);
	sprintf(tmpBuff,"{t}MAC Address: %02X:%02X:%02X:%02X:%02X:%02X{-t}\r\n",mac[5],mac[4],mac[3],mac[2],mac[1],mac[0]);
	retString += (String)tmpBuff + "{t}Firmware version: x.x {-t}\r\n";
   
    // print the received signal strength:
    long rssi = WiFi.RSSI();
    retString += "{t}Signal strength (RSSI): " + (String)rssi + "dBm{-t}\r\n";
    
    uint32_t realSize = ESP.getFlashChipRealSize();
    uint32_t ideSize = ESP.getFlashChipSize();
    FlashMode_t ideMode = ESP.getFlashChipMode();
    sprintf(tmpBuff,"{t}Flash: Real size: %u - IDE Size: %u - IDE speed: %u{-t}\r\n", realSize, ideSize, ESP.getFlashChipSpeed());
	retString += (String)tmpBuff ;
    sprintf(tmpBuff,"{t}Flash IDE mode:  %s{-t}\r\n", (ideMode == FM_QIO ? "QIO" : ideMode == FM_QOUT ? "QOUT" : ideMode == FM_DIO ? "DIO" : ideMode == FM_DOUT ? "DOUT" : "UNKNOWN"));
	retString += (String)tmpBuff ;
	if(httpMode)
	{
		retString.replace("{t}","<DIV>");
		retString.replace("{-t}","</DIV>");
	}
	else
	{
		retString.replace("{t}","");
		retString.replace("{-t}","");
	}
	return retString;	
}



/******************************************************************************
* Function: handleSetting
*
* Handle the connection to the configuration page used in APN and normal operation
*
* Parameters:                
*             none            
* Return:                 
*             none            
******************************************************************************/
void handleSetting()
{
	
	String decodeDst = "";
	server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
	server.sendHeader("Pragma", "no-cache");
	server.sendHeader("Expires", "-1");
	server.sendHeader("Host", "192.168.1.1");
	server.setContentLength(CONTENT_LENGTH_UNKNOWN);
	
	String webApn = F("<!DOCTYPE HTML>\r\n<html>\r\n<head>\r\n<title>Dommy</title>\r\n");                      
	webApn += F("<style type=\"text/css\">\r\n body {background: white; color: black; text-align: center} ");
	webApn += F(" form { color: blue; text-align: center}\r\n div {color: black; text-align: left}\r\n");
	webApn += F(" h1 { color: green; font: 36px Helvetica, Arial, sans-serif;}\r\n</style>\r\n</head>\r\n");

	debugHeaderArgum('n','y');
	
	if(server.args()== 3)
	{

		Serial.println(server.arg("ARG1"));

		Serial.println(server.arg("ARG2"));

		Serial.println(server.arg("ARG3"));

		ESP.wdtFeed(); // to ensure the wdt doesn't trigger
		webApn += F("<body><DIV></DIV><DIV>Module updated.</DIV>\r\n<DIV>It is restarting.</DIV>");
		webApn += "<DIV> <a href='http://www.xxxxxxx.yyy:8080'> Return to the main page </a> </DIV></body>\r\n</html>\r\n"; 
		//server.send(200, "text/html",webApn);
		server.send(200, "text/html", ""); 
		server.sendContent(webApn);
		server.sendContent("");
		delay(500);
		ESP.restart();
		return;
	}
	else if(server.args()> 3)
	{
		Serial.println("Wrong arg number!!");
	}
 // String header = "HTTP/1.1 200 OK\r\nContent-Type: text/html Cache-Control: no-cache\r\n\r\n";
 //   server.sendContent(header);
    

  webApn += F("<body>\r\n<form name='Setting' method='POST'>\r\n");      
  webApn += F("<table width='60%' border='0' cellspacing='5' cellpadding='5'>\r\n");
  webApn += F("<tr><td width='10%' valign='center'><h1>xxx Module Config</h1></td></tr>\r\n");
 
  webApn += "<tr><td width='10%' valign='center'>" + moduleInfo(true) + "</td></tr></table>\r\n";
  webApn += F("<table width='60%' border='0' cellspacing='5' cellpadding='5'>\r\n"); 
  webApn += F("<tr><td valign='center'>ARG1</td></tr>\r\n");  
  webApn += F("<tr><td valign='center'><input type='text' name='ARG1' size='2' maxlength='2' value='1'></td></tr>\r\n");  
  webApn += F("<tr><td valign='center'> ARG2 (no space but '_')</td></tr>\r\n");
  webApn += F("<tr><td valign='center'> \r\n<input type='text' name='ARG2' size='20' maxlength='20' value='2'><br></td>\r\n</tr>\r\n");
  
  webApn += F("<tr>\r\n<td valign='center'>ARG3 - max 25\r\n</td>\r\n</tr>\r\n");
  webApn += F("<tr>\r\n<td valign='center'>\r\n<input type='text' name='ARG3' size='25' maxlength='25' value='test'><br></td>\r\n</tr>\r\n");
   
  webApn += F("<tr>\r\n<td valign='center'>\r\n<input type=submit value='Update'>\r\n</td>\r\n</tr>\r\n</table>\r\n</form>\r\n</body>\r\n</html>"); 
  server.send(200, "text/html",webApn);
}

Debug Messages

Debug messages go here
@d-a-v
Copy link
Collaborator

d-a-v commented Aug 23, 2019

arg("plain") is the body. You can safely ignore it. It has been added to help solving a bug.
The webserver logic has been rewritten (#5636) but is still wip and in the need for testing.

@Sparatutto
Copy link
Author

Hi dav, thanks for the feedback.
I see you are changing a lot and maybe for me at the moment is better to stay with core 2.4.2.
By the way, I cannot ignore it, I have checks on the number and the names of the argument transferred to decide which server page must be loaded.
I could remove the check on the number and check only the names.
But unfortunately it seems to be not the only issue.

Another part of my code is transferring an argument composed by different part separated by a semicolon ";".
In some manner any ";" is recognized as a different argument.

`
bool manageClientUpdate(int module, int tmpZone, int btnCommand)

{

extern struct zone tmpServerZone[NUM_OF_ZONES];

char tmpBuffer[100];

int tmpPwd = random(2, 220); // 220 is the maximum because the password can be 30char max

sprintf(tmpBuffer, "&btnCmd=%01d&zcfg=%01d;%02d;%02d;%04d;%04d;%04d;%04d;%03d;%s;-", btnCommand, tmpZone, tmpServerZone[tmpZone].nonc, tmpServerZone[tmpZone].instantOnOff, tmpServerZone[tmpZone].timeOn_1 & (~USED_TODAY), tmpServerZone[tmpZone].timeOff_1 & (~USED_TODAY), tmpServerZone[tmpZone].timeOn_2 & (~USED_TODAY), tmpServerZone[tmpZone].timeOff_2 & (~USED_TODAY),tmpServerZone[tmpZone].monTimer,tmpServerZone[tmpZone].zoneName);
Serial.println("Module:" +(String)module + tmpBuffer);  

String webPage = "POST /cccc?"; //webPage = "POST /cccc?azyx=1&d=1&pippo=bene&pluto=male&paperino=1234 HTTP/1.1\r\n";

webPage+= "mid=" + (String)serverModules[module].moduleId + "&tmpp=100" + (String)tmpBuffer;

webPage += " HTTP/1.1\r\nHost: " +(String)serverModules[module].moduleIP + "\r\nCookie: TYPE=ttt;\r\nConnection: close\r\n\r\n";

client.print(webPage);
//Serial.print(webPage);
unsigned long timeout = millis();
while (client.available() == 0) 
{
  if (millis() - timeout > 5000) 
  {
    Serial.println(">>> Client Timeout !");
    client.stop();
    return false;
  }
} 
// Read all the lines of the reply from server and print them to Serial
String connResult =" ";
while(client.available())
{
  connResult+= client.readStringUntil('\n');
}
client.stop();
//Serial.print(connResult);
if(connResult.indexOf("HTTP/1.1 200 OK")>=0)
{
  Serial.println("\r\nClient updated");
  return true;
} 
else
  Serial.println("Client update failed");
//Serial.println("Server to client closed");   
return false;

}`

SO checking the returned arg I have one for any ";" and it is not correct.
I hope the comment can help you.

@devyte
Copy link
Collaborator

devyte commented Nov 10, 2019

@Sparatutto I don't understand why you can't just ignore plain. In your original post, please explain the expected output vs. the output that you get. Also, add hints to the code explaining why you can't ignore plain.

@devyte devyte added the waiting for feedback Waiting on additional info. If it's not received, the issue may be closed. label Nov 10, 2019
@Sparatutto
Copy link
Author

Sparatutto commented Nov 11, 2019

Hi Devyte,
yes for sure I can ignore the plain argument but it means change many of the written code so far.
In the problem description you can see the picture of the current output.
The expected output with the old core is ARG 0 to ARG 2 , ARG 3 is what I do not expect.

Regarding the code, I have conditional code based on the number of arguments and the content, maybe it is not the best way but it is what I have.
Here below an example.

// if the read/detail button is pressed the server send the information of the selected module
  if((server.args() == 1) && (server.hasArg("Req")))
         {
                module=server.arg("Req").toInt();
                 logTime();
                 //Serial.printf("superclient: module %02d @%s:%s STATUS REQUEST ", module, serverModules[module].moduleIP,serverModules[module].modulePort);
                 Serial.printf("superclient: module %02d @%s:%d STATUS REQUEST ", module, serverModules[module].moduleIP,serverModules[module].modulePort);
                 receivedTime = manageServerToClient(module); //manageServerToClient(module, &zoneStatusClient);
                 //Serial.println("Time received from module:" + (String)receivedTime); 
                 if(receivedTime>=0)
                 {
                             addAns = true;	
                 }
            }

// if the send button of a zone is pressed the corresponding zone of the selected module is updated
            if((server.args() == 10) && (server.hasArg("Name")))
             {
                 module=server.arg("Name").toInt();
                 tmpZone = server.arg("zone").toInt();   
                 Serial.println("The module required is:" + server.arg("Name") + " ZOne: " + server.arg("zon") + " - " + (String)tmpZone);

                 tmpServerZone[tmpZone].instantOnOff = server.arg("in").toInt();
                 tmpServerZone[tmpZone].nonc = server.arg("mo").toInt();
                 if(tmpServerZone[tmpZone].instantOnOff != ZONE_INPUT)
                 {
                              tmpServerZone[tmpZone].timeOn_1=server.arg("TB").substring(0,server.arg("TB").indexOf(":")).toInt()*MINUT_CONVER+server.arg("TB").substring(server.arg("TB").indexOf(":")+1).toInt(); 
tmpServerZone[tmpZone].timeOff_1= server.arg("TE").substring(0,server.arg("TE").indexOf(":")).toInt()*MINUT_CONVER + server.arg("TE").substring(server.arg("TE").indexOf(":")+1).toInt();

tmpServerZone[tmpZone].timeOn_2 = ....

...
}
...
// Send the initial part of the HTML web page
  server.send(200, "text/html", ""); 
  server.sendContent(webPage);
  //this occours only at the first login or any time the list button is pressed
  if(server.args() == 0)
  {
...
}

thx.

@d-a-v d-a-v self-assigned this Nov 11, 2019
@d-a-v d-a-v added this to the 2.6.1 milestone Nov 11, 2019
@d-a-v
Copy link
Collaborator

d-a-v commented Nov 13, 2019

@Sparatutto #6768 addresses your concern about arg("plain") which shouldn't be counted in the argument list.

About ; I'm afraid you'll have to escape it with %3B because it can be used as argument separator

These fixes may be available in core-2.6.1.

@Sparatutto
Copy link
Author

Hello all, @d-a-v
It seems you have fixed the issue in #6768 but i still see the issue: plain counted as argument.
I'm using board lib 3.0.2.
Am I doing some mistake ?
Commented already in #6768 in August.
Thanks for the feedback.

@d-a-v
Copy link
Collaborator

d-a-v commented Oct 15, 2021

Commented already in #6768 in August.

You should have opened a new issue back then so it may not have been forgotten.

Am I doing some mistake ?

The first mistake I can see is to not open a new issue to track that down.

If I can't answer now, this is going to be forgotten. Please open a new issue.

@d-a-v
Copy link
Collaborator

d-a-v commented Oct 15, 2021

Reopening

@d-a-v d-a-v reopened this Oct 15, 2021
@d-a-v d-a-v modified the milestones: 3.0.0, 3.1 Oct 15, 2021
@d-a-v d-a-v added type: troubleshooting and removed type: bug waiting for feedback Waiting on additional info. If it's not received, the issue may be closed. labels Oct 15, 2021
@Sparatutto
Copy link
Author

Commented already in #6768 in August.

You should have opened a new issue back then so it may not have been forgotten.

Am I doing some mistake ?

The first mistake I can see is to not open a new issue to track that down.

If I can't answer now, this is going to be forgotten. Please open a new issue.

@d-a-v thanks. and sorry for my mistake

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants