400 Bad Request on WiFiClientSecure ESP8266 - arduino

I tried to test the request with ESP8266, I want the request to use
HTTPS but the request result is always 400 bad requests, so what makes
the code I write wrong ???
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#ifndef STASSID
#define STASSID "xxxxxxx"
#define STAPSK "xxxxxxxxx"
#endif
const char* ssid = "xxxxx";
const char* password = "xxxxxxxx";
const char* host = "webhook.site";
const int httpsPort = 443;
const char fingerprint[] PROGMEM = "09:F6:00:C3:67:B0:80:14:34:E3:08:D7:4A:64:20:85:83:F4:80:A1";
void setup() {
Serial.begin(115200);
Serial.println();
Serial.print("connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
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());
// Use WiFiClientSecure class to create TLS connection
WiFiClientSecure client;
Serial.print("connecting to ");
Serial.println(host);
Serial.printf("Using fingerprint '%s'\n", fingerprint);
client.setFingerprint(fingerprint);
if (!client.connect(host, httpsPort)) {
Serial.println("connection failed");
return;
}
delay(500);
if (client.verify(fingerprint, host)) {
Serial.println("certificate matches");
} else {
Serial.println("certificate doesn't match");
}
delay(500);
String url = "/4cf42a06-5df4-4459-b8f3-5d29f1ed319d";
Serial.print("requesting URL: ");
Serial.println(url);
String request = String("GET ") + url + " HTTP/1.0 \r\n" +
"Host: " + host + "\r\n" +
"Accept: *" + "/" + "*\r\n" +
"User-Agent: BuilderFailureDetectorESP8266\r\n" +
"Connection: close\r\n\r\n";
Serial.println(request);
client.print(request);
Serial.println("request sent");
int waitcount = 0;
while (!client.available() && waitcount++ ) {
delay(10);
}
while(client.available()){
String line = client.readStringUntil('\r');
Serial.print(line);
}
while (client.connected()) {
String line = client.readStringUntil('\r');
Serial.println("headers received"+line);
if (line == "\r") {
Serial.println("headers received"+line);
break;
}
}
}
void loop() {
}
and the following is the output of the program above
connecting to xxxx
.....
WiFi connected
IP address:
192.168.1.13
connecting to webhook.site
Using fingerprint '09:F6:00:C3:67:B0:80:14:34:E3:08:D7:4A:64:20:85:83:F4:80:A1'
certificate matches
requesting URL: /4cf42a06-5df4-4459-b8f3-5d29f1ed319d
GET /4cf42a06-5df4-4459-b8f3-5d29f1ed319d HTTP/1.0
Host: webhook.site
Accept: */*
User-Agent: BuilderFailureDetectorESP8266
Connection: close
request sent
HTTP/1.0 400 Bad request
Cache-Control: no-cache
Connection: close
Content-Type: text/html
<html><body><h1>400 Bad request</h1>
Your browser sent an invalid request.
</body></html>
is there a problem with my code ? Can everyone help me ???...
I am looking for following examples from several posts on Google

HTTP can be very persnickety about whitespace. In your line
String request = String("GET ") + url + " HTTP/1.0 \r\n" +
there's an unnecessary space after HTTP/1.0. Remove the space and you should get past the "400 Bad request" response.
String request = String("GET ") + url + " HTTP/1.0\r\n" +

Related

How to post to a MS-teams webhook from Esp8266?

I have an ESP8266 and want to send messages to a MS-Teams channel. In the future I want to send temperature data but for now I am okay with whatever.
Right now I can connect to the host but it will not send any data to the team and it gives no error.
It works without any problems from Postman and the webhook also works from Python.
Here is my code:
#include "ESP8266HTTPClient.h"
#include "ESP8266WiFi.h"
#include <ArduinoJson.h>
#include <WiFiClientSecure.h>
void setup() {
Serial.begin(9600); //Serial connection
WiFi.begin("", ""); //WiFi connection
while (WiFi.status() != WL_CONNECTED) { //Wait for the WiFI connection completion
delay(500);
Serial.println("Waiting for connection");
}
}
void MicrosoftTeams() {
char host[] = "outlook.office.com"; //Specify request destination";
WiFiClient client;
if (client.connect(host, 443)) {
Serial.println("connected");
String url = "/webhook/Webhookcode";
char json[] = "{ \"#context\":
\"https://schema.org/extensions\",\"#type\":
\"MessageCard\",\"themeColor\": \"0072C6\",\"title\":
\"meddelande\",\"text\": \"Hello!!\"}";
int len = strlen(json);
String Output = "POST " + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Content-Type: application/json\r\n" +
"User-Agent: arduino/1.0\r\n" +
"Content-Length: " + len + "\r\n" +
"\r\n" +
json + "\n";
client.print(Output);
while (client.available()) {
String line = client.readStringUntil('\r');
Serial.print(line);
}
}
}
void loop() {
if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status
MicrosoftTeams();
} else {
Serial.println("Error in WiFi connection");
}
delay(30000); //Send a request every 30 seconds
}
Update:
Ive tested the following function and it works in this test example but not the real case. If i change the WiFiClient to WiFiClientSecure everything stops working.
void WifiCliwaySecure()
{
//Work
WiFiClient client;
const int httpPort = 80;
// //Doenst work
// WiFiClientSecure client;
// const int httpPort = 443;
char host[] = "ptsv2.com";
if (!client.connect(host, httpPort)) {
Serial.println("connection failed");
return;
}
String url = "/t/erzs7-1555484154/post";
Serial.print("Requesting POST: ");
// Send request to the server:
String data = "{ \"title\": \"meddelande\",\"text\": \"Hallå alla bk!!\"}";
client.print(String("POST ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"User-Agent: BuildFailureDetectorESP8266\r\n" +
"Content-Length: " + data.length() + "\r\n" +
"Content-Type: application/json\r\n" +
"\r\n" +
data +
"\r\n");
Serial.print("url Send");
delay(500); // Can be changed
if (client.connected()) {
client.stop(); // DISCONNECT FROM THE SERVER
}
Serial.println();
Serial.println("closing connection");
}
By 2021, you should do the following:
#include <WiFi.h>
#include <HTTPClient.h>
void notifyTeams() {
// === Check WiFi connection status
if (WiFi.status()== WL_CONNECTED) {
HTTPClient http;
// == The incoming webhooks as given by Microsoft Teams
String url = "https://XXXXX.webhook.office.com/webhookb2/YYYYY/IncomingWebhook/ZZZZ/AAAA";
http.begin(url);
http.addHeader("Content-Type", "application/json");
// Send request to the server:
String data = "{ \"title\": \"Slug’s here!\", \"text\": \"Quickly go catch her!\"}";
int httpResponseCode = http.POST(data);
if(httpResponseCode>0) {
// === Get the response to the request
String response = http.getString();
Serial.println(httpResponseCode);
Serial.println(response);
}
else {
Serial.print("Error on sending POST: ");
Serial.println(httpResponseCode);
}
http.end();
}
else {
Serial.println("Error in WiFi connection");
}
}

Calling nest api with esp8266 using arduinoEDK

I'm trying to connect to the nest_API (thermostat) using ESP8266 and the Arduino EDK. But so far with no result.
I've seen somebody asking the same question here before. But the answer to his problem didn't help me.
So here's my code:
Code
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
const char* ssid = "xxxxx";
const char* password = "xxxxx";
const char* host = "developer-api.nest.com";
const int httpsPort = 443;
const char* BearerKey = "xxxxxxxuB0QSbgw2nsT85dJEHRpwvR7rSyrLHm2E54QpC9vnSzB5PV8OtGDPm0mAh96wgM0MwApmS";
//declaring GPIO's
int gpio13Led = 13;
int gpio12Relay = 12;
// Use web browser to view and copy
// SHA1 fingerprint of the certificate
const char* fingerprint = "87:CB:F2:E6:44:C0:AA:F2:4C:28:B2:97:85:70:18:92:45:1B:A4:57";
void setup() {
// preparing GPIOs
pinMode(gpio13Led, OUTPUT);
digitalWrite(gpio13Led, HIGH);
pinMode(gpio12Relay, OUTPUT);
digitalWrite(gpio12Relay, HIGH);
Serial.begin(115200);
Serial.println();
Serial.print("connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
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());
// Use WiFiClientSecure class to create TLS connection
WiFiClientSecure client;
Serial.print("connecting to ");
Serial.println(host);
if (!client.connect(host, httpsPort)) {
Serial.println("connection failed");
return;
}
if (client.verify(fingerprint, host)) {
Serial.println("certificate matches");
digitalWrite(gpio13Led, LOW);
} else {
Serial.println("certificate doesn't match");
}
String url = "/";
Serial.print("requesting URL: ");
Serial.println(url);
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Content-Type: application/json\r\n" +
"Authorization: Bearer " + BearerKey + "\r\n\r\n"
);
Serial.println("request sent");
while (client.connected()) {
String line = client.readStringUntil('\n');
Serial.println(line);
if (line == "\r") {
Serial.println("headers received");
break;
}
}
while (client.available()) {
String line = client.readStringUntil('\n');
Serial.println("reply was:");
Serial.println("==========");
Serial.println(line);
Serial.println("==========");
Serial.println("closing connection");
}
}
void loop() {
}
I never get any result from the server. But when I'm using postman, it works. So I wonder. Do I need to use the "host: " + host + ... line?
And is there a way to catch some errors with the WiFiClientSecure.h library.
I also once changed the url for host in the get string.
Then I received one error from the server. I was already happy there was a response after all.
Serial output
connecting to xxxxx
........
WiFi connected
IP address:
xxxxx
connecting to developer-api.nest.com
certificate matches
requesting URL: /
request sent
HTTP/1.1 307 Temporary Redirect
Content-Type: application/json; charset=UTF-8
Access-Control-Allow-Origin: *
Cache-Control: private, no-cache, no-store, max-age=0
Pragma: no-cache
Location: https://firebase-apiserver10-tah01-iad01.dapi.production.nest.com:9553/
Connection: close
Authorization: Bearer xxxxx
content-length: 0
headers received
reply was:
==========
==========
closing connection
Now I'm completely stuck. It would be nice if somebody could help me further out. thx
Wow. Holy smoke! I've got a response! You're tip made it work #gre_gor.
I've changed the host name and the port because my reply said something like this.
Here's my final code:
CODE:
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
const char* ssid = "xxxxx";
const char* password = "xxxxx";
const char* host = "firebase-apiserver10-tah01-iad01.dapi.production.nest.com";
const int httpsPort = 9553; //443;
const char* BearerKey = "xxxxx";
//declaring GPIO's
int gpio13Led = 13;
int gpio12Relay = 12;
// Use web browser to view and copy
// SHA1 fingerprint of the certificate
const char* fingerprint = "87:CB:F2:E6:44:C0:AA:F2:4C:28:B2:97:85:70:18:92:45:1B:A4:57";
void setup() {
// preparing GPIOs
pinMode(gpio13Led, OUTPUT);
digitalWrite(gpio13Led, HIGH);
pinMode(gpio12Relay, OUTPUT);
digitalWrite(gpio12Relay, HIGH);
Serial.begin(115200);
Serial.println();
Serial.print("connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
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());
// Use WiFiClientSecure class to create TLS connection
WiFiClientSecure client;
Serial.print("connecting to ");
Serial.println(host);
if (!client.connect(host, httpsPort)) {
Serial.println("connection failed");
return;
}
if (client.verify(fingerprint, host)) {
Serial.println("certificate matches");
digitalWrite(gpio13Led, LOW);
} else {
Serial.println("certificate doesn't match");
}
String url = "/";
Serial.print("requesting URL: ");
Serial.println(url);
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Content-Type: application/json\r\n" +
"Authorization: Bearer " + BearerKey + "\r\n\r\n"
);
Serial.println("request sent");
while (client.connected()) {
String line = client.readStringUntil('\n');
Serial.println(line);
if (line == "\r") {
Serial.println("headers received");
break;
}
}
while (client.available()) {
String line = client.readStringUntil('\n');
Serial.println("reply was:");
Serial.println("==========");
Serial.println(line);
Serial.println("==========");
Serial.println("closing connection");
}
}
void loop() {
}
Serial monitor:
connecting to xxxxx
...........
WiFi connected
IP address:
xxxxx
connecting to firebase-apiserver10-tah01-iad01.dapi.production.nest.com
certificate doesn't match
requesting URL: /
request sent
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Access-Control-Allow-Origin: *
Cache-Control: private, no-cache, no-store, max-age=0
Pragma: no-cache
Connection: close
content-length: 8060
headers received
reply was:
==========
{"devices":{"thermostats":{"exxx":{"humidity":40,"locale":"nl-NL","temperature_scale":"C","is_using_emergency_heat":false,"has_fan":false,"software_version":"5.6.6-4","has_leaf":true,"where_id":"YygkopgUUc_cIFnCNG7GRDIIQnENO0ScVx9Pa78qfG7XyH-9WDdVgA","device_id":"e97ayjdpIOkPa4vZFxHggZMXiHKfhsyU","name":"Downstairs","can_heat":true,"can_cool":false,"target_temperature_c":15.0,"target_temperature_f":59,"target_temperature_high_c":24.0,"target_temperature_high_f":75,"target_temperature_low_c":20.0,"target_temperature_low_f":68,"ambient_temperature_c":15.5,"ambient_temperature_f":61,"away_temperature_high_c":24.0,"away_temperature_high_f":76,"away_temperature_low_c":8.5,"away_temperature_low_f":48,"eco_temperature_high_c":24.0,"eco_temperature_high_f":76,"eco_temperature_low_c":8.5,"eco_temperature_low_f":48,"is_locked":false,"locked_temp_min_c":20.0,"locked_temp_min_f":68,"locked_temp_max_c":22.0,"locked_temp_max_f":72,"sunlight_correction_active":false,"sunlight_correction_enabled":true,"structure_id":"vEJb634MNif-xxx{"access_token":"xxxx","client_version":2,"user_id":"xxxx"}}
==========
closing connection
The weird thing is that my fingerprint doesn't match but that it still proceeds to give me information.
Next step is to read this response and use the data I want. :-)

Sending GET Request with NodeMCU ESP8266

I'm trying to send a standard http GET request to my website using the NodeMCU example client code however for some reason it is not working.
If I type into my browser: snackrefill.com/GetData.php?username=aaaa&pin=bbbb&cost=cccc then it will successfully connect with the php script and save a data base entry.
The problem is that when I try to do the same using the NodeMCU module it does not work. it seems to be connecting to WiFi and the server just fine but when it sends the request nothing seems to happen.
Am I structuring my request wrong?
#include <ESP8266WiFi.h>
const char* ssid = "BELL473";
const char* password = "XXXXXXX";
const char* host = "ns8451.hostgator.com";
void setup() {
Serial.begin(115200);
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password); //works!
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
int value = 0;
void loop() {
delay(5000);
++value;
Serial.print("connecting to ");
Serial.println(host);
// Use WiFiClient class to create TCP connections
WiFiClient client;
const int httpPort = 80;
if (!client.connect(host, httpPort)) { //works!
Serial.println("connection failed");
return;
}
// We now create a URI for the request
String url = "/GetData.php";
url += "?username=";
url += "aaaa";
url += "&pin=";
url += "bbbb";
url += "&cost=";
url += "cccc";
Serial.print("Requesting URL: ");
Serial.println(url);
// This will send the request to the server
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
Serial.println();
Serial.println("closing connection");
}
The reason it was not sending was because the host was wrong, i was pointing to my website nameserver when i should have pointed it to the regular website name. I changed const char* host = "ns8451.hostgator.com"; to const char* host = "snackrefill.com"; and now it works!

400 Bad Request arduino esp8266

Hi i am trying to test a value form nodemcu board i am using arduino ide to code and have modified the WIFIClient example to send a value to my localhost using GET. it gives me bad request error. any help or suggestion is appreciated
Modified WIFIClinet
#include <ESP8266WiFi.h>
const char* ssid = "ssid";
const char* password = "pwd";
const char* host = "http://10.0.0.39/edu/arduino.php";
void setup() {
Serial.begin(115200);
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
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());
}
int value = 0;
void loop() {
delay(5000);
++value;
Serial.print("connecting to ");
Serial.println(host);
// Use WiFiClient class to create TCP connections
WiFiClient client;
const int httpPort = 80;
if (!client.connect(host, httpPort)) {
Serial.println("connection failed");
return;
}
// We now create a URI for the request
String url ="?v=we";
//
//
Serial.print("Requesting URL: ");
Serial.println(url);
// This will send the request to the server
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
//
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
return;
}
}
// Read all the lines of the reply from server and print them to Serial
while(client.available()){
String line = client.readStringUntil('\r');
Serial.print(line);
}
Serial.println();
Serial.println("closing connection");
}
Output from serial monitor
connecting to http://10.0.0.39/edu/arduino.php
Requesting URL: ?v=we
HTTP/1.0 400 Bad Request
Server: httpd
Date: Sat, 01 Jan 2011 22:02:19 GMT
Content-Type: text/html
Connection: close
<HTML><HEAD><TITLE>400 Bad Request</TITLE></HEAD>
<BODY BGCOLOR="#cc9999"><H4>400 Bad Request</H4>
Bad filename.
</BODY></HTML>
I hope this is helpful for people running this on local host i changed
const char* host = "http://10.0.0.39/edu/arduino.php";
to
const char* host = "10.0.0.39";
and
String url ="?v=we";
to
String url ="/edu/arduino.php?v=we";

How to use esp8266WiFi Library GET request to obtain info from a website

I'm working on the ESP8266 ESP-01 WiFi module programmed with Arduino IDE to send GET request to a URL and read the contents.
Trying to modify the below code which uses the ESP8266WiFi library, I'm not clear what to replace for host. Should i put my URL in host or something else?
Also how to edit the line.
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
#include <ESP8266WiFi.h>
const char* ssid = "your-ssid";
const char* password = "your-password";
const char* host = "data.sparkfun.com";
const char* streamId = "....................";
const char* privateKey = "....................";
void setup() {
Serial.begin(115200);
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
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());
}
int value = 0;
void loop() {
delay(5000);
++value;
Serial.print("connecting to ");
Serial.println(host);
// Use WiFiClient class to create TCP connections
WiFiClient client;
const int httpPort = 80;
if (!client.connect(host, httpPort)) {
Serial.println("connection failed");
return;
}
// We now create a URI for the request
String url = "/input/";
url += streamId;
url += "?private_key=";
url += privateKey;
url += "&value=";
url += value;
Serial.print("Requesting URL: ");
Serial.println(url);
// This will send the request to the server
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
return;
}
}
// Read all the lines of the reply from server and print them to Serial
while(client.available()){
String line = client.readStringUntil('\r');
Serial.print(line);
}
Serial.println();
Serial.println("closing connection");
}
Your line client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); is OK. You don't need to change it.
For host you have to provide domain name or IP address. Eg. const char* host = "example.com";.
Example
If you want to get http://stackoverflow.com/questions/39707504/how-to-use-esp8266wifi-library-get-request-to-obtain-info-from-a-website you should have:
const char* host = "stackoverflow.com";
String url = "/questions/39707504/how-to-use-esp8266wifi-library-get-request-to-obtain-info-from-a-website";

Resources