400 Bad Request Error from GET Request (ESP8266)

Hi All,

I’ve searched through many of the other threads on this issue but I’m still stuck. Can someone help me understand what I’m doing wrong? I’m attempting to make a call to the Dark Sky API directly from my ESP. I’m able to connect to the host, create the GET request, but I keep getting a “400 Bad Request” error. Something might be of interest is the fact that I have to comment out "Host: " + host + "\r\n" + just to get a response which is unlike other calls I’ve made to other APIs. If I leave that line in the SendGetRequest function, the client is always unavailable, which tells me I don’t need that line? But maybe without that line, that’s what’s throwing me the 400 error? So that is really confusing to me: with that line - nothing; without it - the error. What am I missing?

Here’s my code:

#include <ESP8266WiFi.h>
#include <WiFiClient.h>

const char* ssid = "mySSID";
const char* password = "myPassword";
const char* api_key = "myKey";
const char* host = "api.darksky.net";
String url = "https://api.darksky.net/forecast/myKey/38.8951,-77.0367?exclude=minutely,hourly,daily,alerts,flags";
const int httpPort = 80;
WiFiClient client;

void setup() {
  Serial.begin(115200);
  delay(1000);
  ConnectToWifi(ssid, password);
}

void loop() {
  ConnectToHost(host, httpPort, client);
  SendGetRequest(url, host, api_key, client);
  ReadGetResponse(client);
  delay(10000);
}


//this works...
void ConnectToWifi(const char* ssid, const char* password) {
  Serial.print("Connecting to ");
  Serial.print(ssid);
  WiFi.disconnect();
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("Wifi connected.");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}
//this works too...
void ConnectToHost(const char* host, const int httpPort, WiFiClient& client) {
  Serial.print("Connecting to ");
  Serial.println(host);

  client.connect(host, httpPort);

  if (!client.connect(host, httpPort)) {
    Serial.println("Connection failed!");
    return;
  }
}
//if I uncomment out the "Host: " + host +"\r\n" line, the client is always unavailable and no response is received. 
void SendGetRequest(String url, const char* host, const char* api_key, WiFiClient& client) {
  Serial.print("Requesting URL: ");
  Serial.print(url);
  client.println(String("GET ") + url + " HTTP/1.1\r\n" +
               //"Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");
  Serial.println();
  delay(500);
}

void ReadGetResponse(WiFiClient& client) {
  if (client.available()) {
    Serial.println("client is available");
    while (client.connected()) {
      String line = client.readStringUntil('\r');
      Serial.print(line);
      delay(10);
    }
     Serial.println();
     Serial.println("closing connection");
  } else {
    Serial.println("client NOT avaialable");
  }
}

Here is the output to my serial monitor (when that line above is commented out):

Connecting to api.darksky.net
Requesting URL: https://api.darksky.net/forecast/myKey/38.8951,-77.0367?exclude=minutely,hourly,daily,alerts,flags
client is available
HTTP/1.1 400 Bad Request
Server: nginx/1.10.0 (Ubuntu)
Date: Fri, 16 Dec 2016 20:42:39 GMT
Content-Type: text/html
Content-Length: 182
Connection: close

400 Bad Request

400 Bad Request


nginx/1.10.0 (Ubuntu)

closing connection

Here is the output when the line is active:

Connecting to api.darksky.net
Requesting URL: https://api.darksky.net/forecast/myKey/38.8951,-77.0367?exclude=minutely,hourly,daily,alerts,flags
client NOT available

closing connection

You may have a problem because you are using https:// (tls ). Can you try for testing to find a server which uses an http:// URL?

You're using the client class to try to make an https request. This is not supported, you need to use the secure client class. See the ESP8266 Arduino library documentation.

A GET request is made AFTER connecting to a server. So, the protocol (http:// or https://) is NOT part of the GET request.

You can’t connect to one server, and make a GET request to execute a script on a different server, so the server is NOT part of the GET request.

Once you understand what a GET request should look like, making a proper one is easy.

Hey buddy. Use this code.
You will never face the 400 bad request

#include <Arduino.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

#include <ESP8266HTTPClient.h>

#define USE_SERIAL Serial

ESP8266WiFiMulti WiFiMulti;

void setup() {

USE_SERIAL.begin(115200);
// USE_SERIAL.setDebugOutput(true);

USE_SERIAL.println();
USE_SERIAL.println();
USE_SERIAL.println();

for(uint8_t t = 4; t > 0; t–) {
USE_SERIAL.printf("[SETUP] WAIT %d…\n", t);
USE_SERIAL.flush();
delay(1000);
}

WiFi.mode(WIFI_STA);
WiFiMulti.addAP(“ssid”, “pwd”);

}

void loop() {
// wait for WiFi connection
if((WiFiMulti.run() == WL_CONNECTED)) {

HTTPClient http;

USE_SERIAL.print("[HTTP] begin…\n");
// configure traged server and url
//http.begin(“https://192.168.1.12/test.html”, “7a 9c f4 db 40 d3 62 5a 6e 21 bc 5c cc 66 c8 3e a1 45 59 38”); //HTTPS
http.begin(“https://192.168.1.12/test.html”); //HTTP

USE_SERIAL.print("[HTTP] GET…\n");
// start connection and send HTTP header
int httpCode = http.GET();

// httpCode will be negative on error
if(httpCode > 0) {
// HTTP header has been send and Server response header has been handled
USE_SERIAL.printf("[HTTP] GET… code: %d\n", httpCode);

// file found at server
if(httpCode == HTTP_CODE_OK) {
String payload = http.getString();
USE_SERIAL.println(payload);
}
} else {
USE_SERIAL.printf("[HTTP] GET… failed, error: %s\n", http.errorToString(httpCode).c_str());
}

http.end();
}

delay(10000);
}

hi all, i also get this trouble, someone help me please…
my nodeMcu work fine connect to my database before i use software serial…
but when i try get data from arduino Mega with softwareSerial to nodemcu… softwareSerial work fine but can’t send data to my database
when i combine both, i receive

<head><title>400 Bad Request</title></head>

1. my arduino mega code

/*
Measuring AC Current Using ACS712
*/
int mVperAmp = 100; // use 185 for 5A module 100 for 20A Module and 66 for 30A Module
int limit = 50;
int CT1 = 600.0 ; 
String ALLIN ;
const int sensorIn1R = A1; const int sensorIn1S = A2; const int sensorIn1T = A3; //RAK 1

// RAK 1
double Voltage1R = 0; double VRMS1R = 0; double AmpsRMS1R = 0; double calibrasi1R = 0; String SR1 ;
double Voltage1S = 0; double VRMS1S = 0; double AmpsRMS1S = 0; double calibrasi1S = 0; String SS1 ;
double Voltage1T = 0; double VRMS1T = 0; double AmpsRMS1T = 0; double calibrasi1T = 0; String ST1 ;



void setup(){ 
 Serial.begin(115200);
 Serial1.begin(115200);
}

void loop(){

 Voltage1R = getVPP1R();
 VRMS1R = ((Voltage1R/2.0) *0.707106781); 
 AmpsRMS1R = ((VRMS1R * 1000)/mVperAmp)-0.110;
 if (AmpsRMS1R<0.00) AmpsRMS1R = 0.00 ;
 calibrasi1R = (CT1*AmpsRMS1R/5.0);

 Voltage1S = getVPP1S();
 VRMS1S = ((Voltage1S/2.0) *0.707106781); 
 AmpsRMS1S = ((VRMS1S * 1000)/mVperAmp)-0.110;
 if (AmpsRMS1S<0.00) AmpsRMS1S = 0.00 ;
 calibrasi1S = (CT1*AmpsRMS1S/5.0);

 Voltage1T = getVPP1T();
 VRMS1T = ((Voltage1T/2.0) *0.707106781); 
 AmpsRMS1T = ((VRMS1T * 1000)/mVperAmp)-0.110;
 if (AmpsRMS1T<0.00) AmpsRMS1T = 0.00 ;
 calibrasi1T = (CT1*AmpsRMS1T/5.0);

 SR1 = (String) calibrasi1R;
 SS1 = (String) calibrasi1S;
 ST1 = (String) calibrasi1T;

 ALLIN += SR1;
 ALLIN += ",";
 ALLIN += SS1;
 ALLIN += "," ; 
 ALLIN += ST1 ; 
 
Serial.println(ALLIN);
Serial1.println(ALLIN);

 ALLIN ="";
}

/*==================1R===================*/
float getVPP1R()
{
  float result1R;
  float readValue1R;            
  float maxValue1R = 0;          
  float minValue1R = 1024;          
   uint32_t start_time1R = millis();
   while((millis()-start_time1R) < limit) 
   {
       readValue1R = analogRead(sensorIn1R);
       
       if (readValue1R > maxValue1R) 
       {maxValue1R = readValue1R;}
       
       if (readValue1R < minValue1R) 
       {minValue1R = readValue1R;}
   }
   result1R = ((maxValue1R - minValue1R) * 5.0)/1024.0;
   return result1R;
 }
/*==================1S===================*/
 float getVPP1S()
{
  float result1S;
  float readValue1S;             
  float maxValue1S = 0;          
  float minValue1S = 1024;          
   uint32_t start_time1S = millis();
   while((millis()-start_time1S) < limit)
   {
       readValue1S = analogRead(sensorIn1S);
       
       if (readValue1S > maxValue1S) 
       {maxValue1S = readValue1S;}
       
       if (readValue1S < minValue1S) 
       {minValue1S = readValue1S;}
   }
   result1S = ((maxValue1S - minValue1S) * 5.0)/1024.0;
   return result1S;
 }
 /*==================1T===================*/
 float getVPP1T()
{
  float result1T;
  float readValue1T;             
  float maxValue1T = 0;          
  float minValue1T = 1024;          
   uint32_t start_time1T = millis();
   while((millis()-start_time1T) < limit)
   {
       readValue1T = analogRead(sensorIn1T);
       
       if (readValue1T > maxValue1T) 
       {maxValue1T = readValue1T;}
       
       if (readValue1T < minValue1T) 
       {minValue1T = readValue1T;}
   }
   result1T = ((maxValue1T - minValue1T) * 5.0)/1024.0;
   return result1T;
 }

2. my nodeMcu code

#include<SoftwareSerial.h>
#include "StringSplitter.h"
#include <ESP8266WiFi.h>

SoftwareSerial SUART( 4, 5); //SRX  = DPin-2; STX = DPin-3

String ir1 , is1, it1 ;
String data="", tanggal="", aa, bb, cc, dd, ee, ff, gg, hh, ii, jj, kk, ll, mm, nn, oo, pp, qq, rr, ss ;
const char* ssid     = " wifi2";
const char* password = " merdeka ";
const char* host = "microdpl.000webhostapp.com";



void setup() {
  
  WiFi.begin(ssid, password); 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("Netmask: ");
  Serial.println(WiFi.subnetMask());
  Serial.print("Gateway: ");
  Serial.println(WiFi.gatewayIP());

    
  Serial.begin(115200);
  SUART.begin(115200); 

}

void loop() {
serial1 ();
delay (1000);
Serial.print("connecting to ");
  Serial.println(host);

  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }

  String url = "/api/gardu1/insert.php?idmesin=100&vab=" + String (ir1) +"&vbc="+String (is1)+"&vca="+String (it1);
  Serial.print("Requesting URL: ");
  Serial.println(url);
  
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  delay(2000);
  
  while(client.available()){
   String line = client.readStringUntil('\r');
   Serial.print(line);
  }
  
  Serial.println();
  Serial.println("closing connection");
  delay(10000);
      data = "";
      
  ir1="";
  is1="";
  it1="";
  data="";


 Serial.println("test");
}
  void serial1 (){
    if(SUART.available()){
      data= SUART.readStringUntil('\n');
      StringSplitter *splitter = new StringSplitter (data, ',', 3);
      int itemCount = splitter->getItemCount();

      ir1 = splitter->getItemAtIndex(0);
      is1 = splitter->getItemAtIndex(1);
      it1 = splitter->getItemAtIndex(2);
      

      
      SUART.flush ();
    }
}