ESP8266 SENDING DATA - BAD REQUEST

Hi guys,

I am having some problems when I want to send a JSON to the server.

I have this code:

#include <ESP8266.h>
#include <SoftwareSerial.h>

#define SSID        "..."
#define PASSWORD    "..."
#define HOST_NAME   "jsonplaceholder.typicode.com"
#define HOST_PORT   (80)

SoftwareSerial mySerial(2, 3); /* RX:D3, TX:D2 */
ESP8266 wifi(mySerial);
bool setupSuccess = false;

struct Data {
  char title[64];
  char body[64];
};

void setup() {
  Serial.begin(9600);
  Serial.println("-Setup begin\n");
  
  Serial.println("--Checking wifi connection");
  delay(1500);

  showIPStatus();
  String IPStatus = wifi.getIPStatus().substring(7,8);
  Serial.println("STA: "+ IPStatus);
  if( IPStatus == "2" || IPStatus == "3"){
    Serial.println("\nConnected\n");
    disableMux();
    setupSuccess = true;
  } else {
    Serial.println("\nNot connected");
    if(connectWifi())
      setupSuccess = true;
  }
  Serial.println("\n-Setup end\n");
}

void loop() {
  // put your main code here, to run repeatedly:
  if(setupSuccess){
    sendData();
    //postData();
  }
  while(1);
}

bool startTCPConn(){
  Serial.print("--Starting TCP connection: ");
  mySerial.println("AT+CIPSTART=\"TCP\",\"jsonplaceholder.typicode.com\",80"); //start a TCP connection.
  if (mySerial.find("OK")) {
    Serial.println("OK");
  }
  else{
    Serial.println("ERR");
    return false;
  }
  delay(1000);
  Serial.print("--Checking TCP connection: ");
  if(wifi.getIPStatus().substring(7,8) == "3"){
    Serial.println("OK");
    return true;
  } else {
    Serial.println("ERR");
    return false;
  }
}

void postData(){
  if(startTCPConn()){
    char *postRequest = "POST /posts HTTP/1.1\r\nHost: jsonplaceholder.typicode.com\r\nContent-Type: application/json\r\n\r\n{\"title\":\"testing\",\"body\":\"arduinogato\",\"userId\":89}";
    String sendCmd = "AT+CIPSEND="; //determine the number of caracters to be sent.
    mySerial.print(sendCmd);
    mySerial.println(strlen(postRequest));
    Serial.print("SIZE: ");
    Serial.println(strlen(postRequest));
    delay(1000);
    if (mySerial.find(">")) {
        Serial.println("--Posting data..");
        Serial.println("Sending: ");
        Serial.print(postRequest);
        mySerial.print(postRequest);
        if (mySerial.find("SEND OK")) {
            Serial.println("\nPost OK");
            //waitForResponse("CLOSED",10000);
            while(1) {
                char c = mySerial.read() ;
                Serial.print(c);
            }
            mySerial.println("AT+CIPCLOSE");
        } else {
          Serial.println("Sending error");
        }
    }
  }
}

void sendData(){
  if(startTCPConn()){
    Data data;
    //Send data
    char *hello = "GET /posts/99 HTTP/1.1\r\nHost: jsonplaceholder.typicode.com\r\n\r\n";
    String sendCmd = "AT+CIPSEND="; //determine the number of caracters to be sent.
    mySerial.print(sendCmd);
    mySerial.println(strlen(hello));
    Serial.print("SIZE: ");
    Serial.println(strlen(hello));
    delay(500);
    if (mySerial.find(">")) {
        Serial.println("--Sending data..");
        mySerial.print(hello);
        if (mySerial.find("SEND OK")) {
            Serial.println("Packet sent");
            while(mySerial.available()){
              Serial.println(mySerial.readString());
            }
            mySerial.println("AT+CIPCLOSE");
          } else {
            Serial.println("Sending error");
          }
    }
  }
}

void showIPStatus(){
  Serial.println(wifi.getIPStatus());
}

void createTCPConnection(){
  if (wifi.createTCP(HOST_NAME, HOST_PORT)) {
      Serial.print("create tcp ok\r\n");
  } else {
      Serial.print("create tcp err\r\n");
  }
}

bool connectWifi(){
  Serial.println("\nConnecting\n");
    Serial.print("Setting AP + Station mode: ");
    if (wifi.setOprToStationSoftAP()) {
        Serial.println("OK");
    } else {
        Serial.println("ERR");
    }

    Serial.print("\nJoining Access Point: ");
    if (wifi.joinAP(SSID, PASSWORD)) {
      Serial.println("OK");
      Serial.println("IP: ");       
      Serial.println(wifi.getLocalIP().c_str());
      delay(1500);
      disableMux();
      return true;
    } else {
      Serial.print("ERROR\r\n");
      return false;
    }
}

bool disableMux(){
  Serial.print("\n--Disabling MUX: ");
  if (wifi.disableMUX()) {
      Serial.println("OK");
      return true;
  } else {
      Serial.println("ERR");
      return false;
  }
}

boolean waitForResponse(String target, unsigned long timeout)
{
  unsigned long startTime = millis();
  String responseBuffer;
  char charIn;
  
  //keep checking for ESP response until timeout expires
  while ((millis() - startTime) < timeout)
  {
    if (mySerial.available())
    {
      charIn = mySerial.read();
      responseBuffer += charIn;
    }
    if (responseBuffer.endsWith(target))
    {
      return 1; //true
    }
  }
  if (!responseBuffer.endsWith(target))
  {
    Serial.print("---ERROR ");
    Serial.println(responseBuffer);
    return 0; //false
  } else {
    Serial.print("---SUCCESS ");
    Serial.println(responseBuffer);
    return 1; //true
  } 
}

//reset the esp8266 module
void reset() {
  mySerial.println("AT+RST");
  delay(3000);

  if (mySerial.find("OK"))
    Serial.println("Module Reset");
}

When I execute this code (sendData()):

void loop() {
  // put your main code here, to run repeatedly:
  if(setupSuccess){
    sendData();
    //postData();
  }
  while(1);
}

It works fine and I receive:

+IPD,874:HTTP/1.1 200 OK
Date: Thu, 29 Jun 2017 02:53:52 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 224
Connection: keep-alive
Set-Cookie: __cfduid=d0292901803486d2d3b179def5ac2485c1498704832; expires=Fri, 29-Jun-18 02:53:52 GMT; path=/; domain=.typicode.com; HttpOnly
X-Powered-By: Express
Vary: Origin, Accept-Encoding
Access-Control-Allow-Credentials: true
Cache-Control: public, max-age=14400
Pragma: no-cache
Expires: Thu, 29 Jun 2017 06:53:52 GMT
X-Content-Type-Options: nosniff
Etag: W/"e0-aXopzb0YfAN1tmSD/RVNZPaEz8g"
Via: 1.1 vegur
CF-Cache-Status: HIT
Server: cloudflare-nginx
CF-RAY: 37659910f45e6575-SYD

{
  "userId": 10,
  "id": 99,
  "title": "temporibus sit alias delectus eligendi possimus magni",
  "body": "quo deleniti praesentium dicta non quod\naut est molestias\nmolestias et officia quis nihil\nitaque dolorem quia"
}

The problem is when I execute this (postData()):

void loop() {
  // put your main code here, to run repeatedly:
  if(setupSuccess){
    //sendData();
    postData();
  }
  while(1);
}

When I get the response and I read it in this way:

if (mySerial.find("SEND OK")) {
            Serial.println("\nPost OK");
            //waitForResponse("CLOSED",10000);
            while(1) {
                char c = mySerial.read() ;
                Serial.print(c);
            }
            mySerial.println("AT+CIPCLOSE");
        } else {
          Serial.println("Sending error");
        }

I receive this:

--Starting TCP connection: OK
--Checking TCP connection: OK
SIZE: 144
--Posting data..
Sending: 
POST /posts HTTP/1.1
Host: jsonplaceholder.typicode.com
Content-Type: application/json

{"title":"testing","body":"arduinogato","userId":89}
Post OK

⸮⸮⸮⸮⸮⸮
+IPD,630:HTTP/1.1 201 Created
Date: Thu, 29 Jun 2017 02:56:18 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 15
Connection: keep-alive
Set-Cookie: __cfduid=d3f5421b925be79ab723b48bc4a7c80ea1498704977; expires=Fri, 29-Jun-18 02:56:17 GMT; path=/; domain=.typicode.com; HttpOnly
X-Powered-By: Express
Vary: Origin, X-HTTP-Method-Override, Accept-Encoding
Access-Control-Allow-Credentials: true
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
X-Content-Type-Options: nosniff
Etag: W/"f-4jjw4Y8q22Yv1PV9m28FczJgjzk"
Via: 1.1 vegur
Server: cloudflare-nginx
CF-RAY: 37659c9ed5790b14-SYD

{
  "id": 101
}
+IPD,334:HTTP/1.1 400 Bad Request
Date: Thu, 29 Jun 2017 02:56:18 GMT
Content-Type: text/html
Content-Length: 177
Connection: close
Server: -nginx
CF-RAY: -

<html>
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>cloudflare-nginx</center>
</body>
</html>
CLOSED
⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮

If I send the same request through postman:

POST /posts HTTP/1.1
Host: jsonplaceholder.typicode.com
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 27da982b-4471-d125-d8bf-7ce74ed48271

{"title":"testing","body":"arduinogato","userId":89}

I receive this:

{
    "title": "testing",
    "body": "arduinogato",
    "userId": 89,
    "id": 101
}

Do you know why it is happening?

Cheers,

Lucas.

  I had to remove some code because I get this from the forum:
  The message exceeds the maximum allowed length (9000 characters).

I had to remove some of my answer because it was too long.

What you need to do is . Hope that helps.

(You could have read the stickies at the top of the forum, and learned how to attach your code if it is too long).

Do you know why it is happening?

Probably has something to do with the code you didn't post.

Just a thought:
It might help to add a Content-Length header to your POST request.
With GET this is not needed because there is no payload.
With POST it may be needed so that the server knows where your message ends.

PaulS:

  I had to remove some code because I get this from the forum:

The message exceeds the maximum allowed length (9000 characters).



I had to remove some of my answer because it was too long.

What you need to do is <snipped the part that was too long>. Hope that helps.

(You could have read the stickies at the top of the forum, and learned how to attach your code if it is too long).
Probably has something to do with the code you didn't post.

I am sorry bro, I didn't know how to do it, I've just modified it.

Jobi-Wan:
Just a thought:
It might help to add a Content-Length header to your POST request.
With GET this is not needed because there is no payload.
With POST it may be needed so that the server knows where your message ends.

I added Content-Length and It is working as a charm now.

Thank you guys