ESP8266 AT command HTTP GET returns 408 Request Timeout

Hi guys,

I’m having trouble with the project im working on using ESP8266. It returns the following:

Reseting Module: Done!
Setting as Client: Done!
Set Connection Type: ............................Done!
Connecting to Wifi: ..Done
Connecting to TCP: Success
*********Doing Request**************
AT+CIPSEND=38
> 
Sending 38 bytes request to:172.20.10.2/x.php
-----------Request Start------------
GET /x.php HTTP/1.1
Host: 172.20.10.2
------------Request End-----------
G¨½¹¡�EE))Ô.:b72.20.10.2
SEND OK

Retrieving reply:.Done!
+IPD,530:HTTP/1.1 408 Request Timeout
Date: Thu, 25 Jan 2018 14:33:13 GMT
Server: Apache/2.4.4 (Win32) OpenSSL/0.9.8y PHP/5.4.16
Content-Length: 320
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>408 Request Timeout</title>
</head><body>
<h1>Request Timeout</h1>
<p>Server timeout waiting for the HTTP request from the client.</p>
<hr>
<address>Apache/2.4.4 (Win32) OpenSSL/0.9.8y PHP/5.4.16 Server at localhost Port 80</address>
</body></html>

OK
CLOSED

OK

Heres the code im using:

#include "SoftwareSerial.h"

SoftwareSerial esp(2, 3);// RX, TX

#define ESP8266_HOST "172.20.10.2"
#define ESP8266_URI "/x.php"

#define ESP8266_SSID "fjp-phone"
#define ESP8266_PASS "jo2x2016"

#define WIFI_RECCONNECT_AFTER 5
#define TCP_INIT_AFTER 2
#define DEBUG_MODE true

boolean TcpConnection = false;

void setup()
{
  esp.begin(9600);
  Serial.begin(9600);
  initialize();
}

void loop ()
{
  if( !TcpConnection ) {
     Serial.print("Connecting to TCP: ");
     TcpConnection = connectTCP();
     if ( TcpConnection ) Serial.println("Success");
     else Serial.println( "Failed" );
  }

  if( TcpConnection ) {
    Serial.println("*********Doing Request**************");
    Serial.println( doRequest() );
  }

  delay(2000);
}

void initialize() {
  int retries = 0;
  boolean connection_status = false;

  Serial.print("Reseting Module: ");
  while( !reset() ) {
    Serial.print(".");
    retries++;
  }
  Serial.println( "Done!" );

  Serial.print("Setting as Client: ");
  retries = 0;
  while( !setClient() ) {
    Serial.print(".");
    retries++;
  }
  Serial.println("Done!");

  Serial.print("Set Connection Type: ");
  retries = 0;
  while( !setConnectionType() ) {
    Serial.print(".");
    retries++;
  }
  Serial.println("Done!");

  Serial.print("Connecting to Wifi: ");
  retries = 0;
  while( !connection_status && retries < WIFI_RECCONNECT_AFTER ) {
    connection_status = connectWifi();
    Serial.print(".");
    retries++;
  }
  if ( !connection_status ) {
       Serial.println("Resetting again...");
       retries = 0;
       initialize();
  } else {
     Serial.println("Done");
  }
}

String sendData(String command, const int timeout, boolean debug=false)
{
    String response = "";
    esp.print(command + "\r\n"); // send the read character to the esp8266

    long int time = millis();
    while( (time+timeout) > millis() ) {
      while( esp.available() ) {
        char c = esp.read(); // read the next character.
        response+=c;
      }
    }
    if(debug) {
      Serial.print(response);
    }
    return response;
}

boolean reset()
{
  String response = "";
  String cmd = "AT+RST";
  response = sendData(cmd, 2000, false);
  if( response.indexOf("OK") >= 0 ) return true;
  else return false;
}

boolean setClient()
{
  String response = "";
  String cmd = "AT+CWMODE=1";
  response = sendData(cmd, 2000, false);
  if( response.indexOf("OK") >= 0 ) return true;
  else return false;
}


boolean setConnectionType()
{
  String response = "";
  String cmd = "AT+CIPMUX=0";// 0-single,1-multiple
  response = sendData(cmd, 2000, false);
  if( response.indexOf("OK") >= 0 ) return true;
  else return false;
}

//connect to your wifi network
boolean connectWifi()
{
  String response = "";
  String cmd = "AT+CWJAP=\"";cmd = cmd +ESP8266_SSID; 
  cmd = cmd +"\",\""; cmd = cmd +ESP8266_PASS +"\"";
  response = sendData(cmd, 4000, false);
  if( response.indexOf("OK") >= 0 ) return true;
  else return false;
}

String getIP()
{
  String response = "";
  String cmd = "AT+CIFSR";
  response = sendData(cmd, 1000, false);
  Serial.print(response);
}

boolean connectTCP()
{
  String response = "";
  String cmd = "AT+CIPSTART=\"TCP\",\"";
  cmd = cmd +ESP8266_HOST +"\",80";
  response = sendData(cmd, 2000, false);
  if( response.indexOf("OK") >= 0 )  return true;
  else return false;
}

String doRequest()
{
  String response = "";
  String post_request = "";
  int post_len = 0;
  String pr1 = "GET ";
  String pr2 = String(ESP8266_URI);
  String pr3 = " HTTP/1.1\r\n";
  String pr4 = "Host: ";
  String pr5 = String(ESP8266_HOST);

  post_request = pr1 +pr2 +pr3 +pr4 +pr5;
  post_len = post_request.length();
  
  response = sendData( "AT+CIPSEND=" +String(post_len), 2000, false);
  Serial.println(response);

  if( response.indexOf(">") >= 0 )
  {
    Serial.println( "Sending " +String(post_len) +" bytes request to:" +ESP8266_HOST +ESP8266_URI);
    Serial.println( "-----------Request Start------------" );
    Serial.println( post_request );
    Serial.println( "------------Request End-----------" );
    esp.print(pr1);
    esp.print(pr2);
    esp.print(pr3);
    esp.print(pr4);
    esp.println(pr5);
    esp.println("");
    delay(1000);
    response =  esp.readString();
    Serial.println(response);

    if( response.indexOf("SEND") >= 0 ) {
        Serial.print("Retrieving reply:");
        response = "";
        boolean done = false;
        int cnt = 0;
        while( done == false ) {
            while (esp.available()) {
              response = esp.readString();
              Serial.print(".");
            }
           if( response.indexOf("CLOSED") >= 0 || response.indexOf("OK") >= 0 || response.indexOf("</html>") >= 0  ) done = true;
        }
        Serial.print("Done!");
        return response;
    } else {
      TcpConnection = false;
      return "Error sending request";
    }
  } else {
    TcpConnection = false;
    return "Error occured";
  }
}

I’ve been stuck on this for days, im hoping someone could help me.

Thanks

What does the php script do? Does it really expect no input?

By the way, why is the Host line missing the \r\n on the end?

You are building up 'post_request' and even printing it out to the console:

Serial.println( post_request );

but where in your code are you sending it to the server ? Or have I missed something ?

@PaulS, Yes, no input for now because its just for testing. Even if I do request "GET /x.php?x=1", the response is still the same.

I suspect im missing some CRLF but im not sure. I tried adding "\r\n\r\n" at the end with no luck.

Apache error log says "request failed: error reading the headers" btw.

thanks

but where in your code are you sending it to the server ? Or have I missed something ?

Apparently, you did:

   esp.print(pr1);
    esp.print(pr2);
    esp.print(pr3);
    esp.print(pr4);
    esp.println(pr5);
    esp.println("");

Though why OP doesn't send the one compound string, instead of 5 strings is a mystery. Why OP isn't sending the same number of characters as he/she claimed to send is another one.

You are creating a compound string, containing \r\n after the GET statement, but not after the Host statement.

You are sending the number of characters in the compound string, but then sending more characters than that.

Ah yes. I see. You are right. Each esp.print creates its own CRLF characters which are not included in the length of post_request.length()

Each esp.print creates its own CRLF characters

No. Each println() does, though.

I thought only esp.println adds CRLF, thats why my last lines are

esp.println(pr5);
    esp.println("");

Im updating the code to its original form using one string variable.

I updated the code to use one variable.

String doRequest()
{
  String response = "";
  int post_len = 0;
  String post_request = "GET " +String(ESP8266_URI) +" HTTP/1.1\r\n";
         post_request = post_request +"Host: " +String(ESP8266_HOST) +"\r\n\r\n";

  post_len = post_request.length();
  
  response = sendData( "AT+CIPSEND=" +String(post_len), 2000, false);
  Serial.println(response);

  if( response.indexOf(">") >= 0 )
  {
    Serial.println( "Sending " +String(post_len) +" bytes request to:" +ESP8266_HOST +ESP8266_URI);
    Serial.println( "-----------Request Start------------" );
    Serial.println( post_request );
    Serial.println( "------------Request End-----------" );
    esp.print(post_request);
    delay(1000);
    response =  esp.readString();
    Serial.println(response);

    if( response.indexOf("SEND") >= 0 ) {
        Serial.print("Retrieving reply:");
        response = "";
        boolean done = false;
        int cnt = 0;
        while( done == false ) {
            while (esp.available()) {
              response = esp.readString();
              Serial.print(".");
            }
           if( response.indexOf("CLOSED") >= 0 || response.indexOf("OK") >= 0 || response.indexOf("</html>") >= 0  ) done = true;
        }
        Serial.print("Done!");
        return response;
    } else {
      TcpConnection = false;
      return "Error sending request";
    }
  } else {
    TcpConnection = false;
    return "Error occured";
  }
}

But now it skips my condition, Im looking for “SEND” in response after sending the command.

*********Doing Request**************
AT+CIPSEND=42
> 
Sending 42 bytes request to:172.20.10.2/x.php
-----------Request Start------------
GET /x.php HTTP/1.1
Host: 172.20.10.2


------------Request End-----------
G¨½¹¡�EE))Ô.:b72.20.10.2
Error sending request

OK. Can you also post the source of x.php ?

Nothing fancy.

<?php
echo "Hello World";
?>

The PHP is simple enough.
OK. In the OP you got this back after issuing the GET:

G¨½¹¡�EE))Ô.:b72.20.10.2
SEND OK

Now the SEND OK is missing:

G¨½¹¡�EE))Ô.:b72.20.10.2

You are relying on this to get the first response back.

    delay(1000);
    response =  esp.readString();

It may be a timing issue. The readString() times out - default 1000 mS.
It could be the same problem as here.

@6v6gt
I updated my code to consider the possibility timing issue with no luck. See below

String doRequest()
{
  int retries = 0;
  boolean done = false;
  String response = "";
  int post_len = 0;
  String post_request = "GET " +String(ESP8266_URI) +" HTTP/1.1\r\n";
         post_request = post_request +"Host: " +String(ESP8266_HOST) +"\r\n\r\n";

  post_len = post_request.length();
  
  response = sendData( "AT+CIPSEND=" +String(post_len), 2000, false);
  Serial.println(response);

  if( response.indexOf(">") >= 0 )
  {
    Serial.println( "Sending " +String(post_len) +" bytes request to:" +ESP8266_HOST +ESP8266_URI);
    Serial.println( "-----------Request Start------------" );
    Serial.println( post_request );
    Serial.println( "------------Request End-----------" );

    //SEND THE REQUEST
    esp.print( post_request );
    delay(2000);

    Serial.println("Waiting request to be sent...");
    retries = 0;
    while( done == false && retries <= 10 ) {
      response = esp.readStringUntil('\n');
      if( response.indexOf("SEND") >= 0 ) done = true;
      retries++;
    }

    if( done ) {
        Serial.print("Retrieving reply:");
        response = "";
        done = false;
        while( done == false ) {
            while (esp.available()) {
              response = esp.readString();
              Serial.print(".");
            }
           if( response.indexOf("CLOSED") >= 0 || response.indexOf("OK") >= 0 || response.indexOf("</html>") >= 0  ) done = true;
        }
        Serial.print("Done!");
        return response;
    } else {
      TcpConnection = false;
      return "Error sending request";
    }
  } else {
    TcpConnection = false;
    return "Error occured";
  }
}

I noticed that when I add “\r\n\r\n” in my request it returns “CLOSED OK” but it takes a couple of seconds

G¨½¹¡�EE))Ô.:b72.20.10.2
CLOSED OK

But when I remove “\r\n\r\n” in my request and use “println()” 2x (for “\r\n\r\n” ) instead of “print” it returns “SEND OK” right away but when I retrieve the output its “408 Request Time-out”

G¨½¹¡�EE))Ô.:b72.20.10.2
SEND OK

Apache error logs says

[Fri Jan 26 16:04:36 2018] [error] [client 180.191.111.42] request failed: error reading the headers

Thanks for your help guys, any inputs surely helps. :wink:

It looks like the same sort of error I was getting with the WiFiEsp library.

Constant timeout and data send errors.

Assuming all of this is debug output in Serial Monitor:

Retrieving reply:.Done!
+IPD,530:HTTP/1.1 408 Request Timeout
Date: Thu, 25 Jan 2018 14:33:13 GMT
Server: Apache/2.4.4 (Win32) OpenSSL/0.9.8y PHP/5.4.16
Content-Length: 320
Connection: close
Content-Type: text/html; charset=iso-8859-1

408 Request Timeout

Request Timeout

Server timeout waiting for the HTTP request from the client.


Apache/2.4.4 (Win32) OpenSSL/0.9.8y PHP/5.4.16 Server at localhost Port 80

OK
CLOSED

OK

I spent a lot of time inside the WiFiEsp library trying to figure what was going on.

I eventually figured out that the timeout values, used by the author while waiting for data to be received or sent, were just to small.

I can only assume his WiFi network at his home was more ideal than mine and the data transmission rate between his ESP8266 and ADSL modem was faster and less prone to transmission errors that it is between mine.

I increased all the authors timeout values and the data and send errors all virtually disappeared.

You may have to do something similar in the library you are using.

You could try raising an issue on Github with the author of your library, but it is not likely it will be dealt with any time soon.

If you are reasonably proficient with coding then it might be a good learning exercise to follow this function call esp.read() back through the library and see if you can find any literal integers that look as though they might be millis timeouts (200, 100, 50,…) Or any variables or class data members along the lines of _timout.

In WiFiEsp library it was calls to this function that were the problem readUntil(timeout). The author had various integer literals that worked with his WiFi network but not mine.
I ended up creating a class data member called ‘timeout’ with 8000ms in it…so I could increase all the ms timeout values in all the calls to this function by changing one line of code, i.e. timeout = 8000;

And no I didn’t bother using HN in this case :wink: …not intended for you OP.

OK. Then back to basics. What happens if you :

  1. issue this in a web browser in the same network: http://172.20.10.2/x.php
  2. issue the native AT commands directly in the serial console

You seem to be trying to implement a wifi library from scratch!

Why bother when WiFiEsp works with an ESP8266 connected via Serial to an Arduino.

Whatever.

Try the following.....

Double the timeout values you are passing to sendData(String command, const int timeout, boolean debug=false)

And change the following to use millis() to keep polling esp for data until a timeout expires....say 8000ms
Get rid of the delay(1000);

    delay(1000);
    response =  esp.readString();

Guys,

I give up with my code and used WiFiEsp as suggested by @boylesg and I got it working now. :slight_smile:

I wish knew WiFiEsp earlier.

Thanks for the help everyone!

//fj