How to read chunked http response in ESP32 - http

Basically I want to develop code for sending a GET request to an API using ESP32 (Arduino framework).
However the HTTP response is going to be very large (JSON object), hence I have used the transfer encoding: chunked
header. My question is how to read and process the chunked response, the below code gives an the following
error:
Connecting to WiFi..
Connected to the WiFi network
-11
Error on HTTP request
-11
This error does not occour if the header is not added
#include<Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
const char* ssid = ""; // my access point
const char* password = ""; //my password
const String URL = ""; //the api url
void setup() {
Serial.begin(115200);
delay(4000);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connected to the WiFi network");
//sw.begin(115200);
}
void loop() {
if ((WiFi.status() == WL_CONNECTED)) { //Check the current connection status
HTTPClient http;
http.begin(URL); //Specify the URL
http.addHeader("Transfer-Encoding", "Chunked"); // for getting chunked data
int httpCode = http.GET(); //Make the request
if (httpCode > 0) { //Check for the returning code
String payload = http.getString();
Serial.println(httpCode);
Serial.println(payload);
}
else {
Serial.println(httpCode);
Serial.println("Error on HTTP request");
}
http.end();
}
delay(10000);
}

Related

Arduino: CORRUPT HEAP while running this sketch on ESP32

I've modified the WiFiClientSecure example, that comes with ESP32 core, to save the WiFiClientSecure object in a user-defined class Fetch as its property, then return Fetch object from a function, only to retrieve the WiFiClientSecure object from the fetch object by reading the property.
/*
Wifi secure connection example for ESP32
Running on TLS 1.2 using mbedTLS
2017 - Evandro Copercini - Apache 2.0 License.
*/
#include <WiFiClientSecure.h>
const char* ssid = "Mi Fimilia"; // your network SSID (name of wifi network)
const char* password = "muhsamali"; // your network password
const char* server = "www.howsmyssl.com"; // Server URL
// www.howsmyssl.com root certificate authority, to verify the server
// change it to your server root CA
// SHA1 fingerprint is broken now!
const char* test_root_ca= \
"-----BEGIN CERTIFICATE-----\n\
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n\
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n\
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4\n\
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu\n\
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY\n\
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc\n\
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+\n\
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U\n\
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW\n\
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH\n\
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC\n\
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv\n\
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn\n\
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn\n\
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw\n\
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI\n\
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV\n\
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq\n\
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL\n\
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ\n\
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK\n\
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5\n\
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur\n\
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC\n\
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc\n\
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq\n\
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA\n\
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\n\
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n\
-----END CERTIFICATE-----";
// You can use x.509 client certificates if you want
//const char* test_client_key = ""; //to verify the client
//const char* test_client_cert = ""; //to verify the client
class Fetch {
private:
WiFiClientSecure _client;
public:
Fetch(WiFiClientSecure client) : _client(client) {}
WiFiClientSecure getWiFiClientSecure() { return _client; }
};
Fetch getFetch() {
WiFiClientSecure client;
Fetch fetch(client);
return fetch;
}
void setup() {
Fetch fetch = getFetch();
WiFiClientSecure client = fetch.getWiFiClientSecure();
//Initialize serial and wait for port to open:
Serial.begin(115200);
delay(100);
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
// attempt to connect to Wifi network:
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
// wait 1 second for re-trying
delay(1000);
}
Serial.print("Connected to ");
Serial.println(ssid);
client.setCACert(test_root_ca);
//client.setCertificate(test_client_key); // for client verification
//client.setPrivateKey(test_client_cert); // for client verification
Serial.println("\nStarting connection to server...");
if (!client.connect(server, 443))
Serial.println("Connection failed!");
else {
Serial.println("Connected to server!");
// Make a HTTP request:
client.println("GET https://www.howsmyssl.com/a/check HTTP/1.0");
client.println("Host: www.howsmyssl.com");
client.println("Connection: close");
client.println();
while (client.connected()) {
String line = client.readStringUntil('\n');
if (line == "\r") {
Serial.println("headers received");
break;
}
}
// if there are incoming bytes available
// from the server, read them and print them:
while (client.available()) {
char c = client.read();
Serial.write(c);
}
client.stop();
}
}
void loop() {
// do nothing
}
This may look like some coding acrobatics but I need this to implement a library that I'm working on. As my understanding goes, WiFiClientSecure is being saved and retrieved by copy. Then why the Heap corruption?

Keep getting HTTP 400 errors using ESP8266HTTPClient

I'm trying to POST data to a URL using the ESP8266HTTPClient library, but I keep getting 400 errors. I verified that I can POST to that URL via Postman, so I'm not sure why it keeps failing with this sketch.
The output is:
Sending data to https://my-project.firebaseio.com/users/MY_USER_ID.json
{"timestamp":"2021-10-28 14:20:00","duration":"1"}
HTTP Response code: 400
Full code below:
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
// WiFi configuration
const char *ssid = "MY_SSID";
const char *password = "MY_PASSWORD";
// Database configuration
const String userId = "MY_USER_ID";
const String baseUrl = "https://my-project.firebaseio.com";
void setup()
{
delay(1000);
Serial.begin(9600);
Serial.print("Configuring access point...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(500);
}
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());
}
bool shouldSendData = true;
void loop()
{
if (shouldSendData)
{
Serial.println("Attempting to send data...");
if (WiFi.status() == WL_CONNECTED)
{
WiFiClient client;
HTTPClient http;
String url = baseUrl + "/users/" + userId + ".json";
http.begin(client, url);
http.addHeader("Content-Type", "application/json");
String data = "{\"timestamp\":\"2021-10-28 14:20:00\",\"duration\":\"1\"}";
int httpResponseCode = http.POST(data);
Serial.print("Sending data to ");
Serial.println(url);
Serial.println(data);
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
http.end();
}
else
{
Serial.println("Unable to send data. WiFi is not connected.");
}
shouldSendData = false;
}
}

HTTP get Request using ESP8266

Why I am unable to send get request. It always response 400.The URL are okay there is no problem in it. Actually I need to send data using get request. I have tried my best to find the solution but I didn't get any idea about it. Please anyone can help me with the code
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>//this header is used to send get request and see response
#include <WiFiClient.h>
const char* ssid = "myssid";
const char* password = "mypswd";
String host_url="https://api-test.technofield.net";
String url1="/api/data?token=TEST_TOKEN_123&data=";
int httpPort=80;
void setup() {
Serial.begin(9600);
WiFi.begin(ssid, password); //Connect to my WiFi router
Serial.println("");
Serial.print("Connecting"); //initiall step just displaying connecting
// Wait for connection
while (WiFi.status() != WL_CONNECTED) { //the llop wiil execute till wifi is not connected
delay(500);
Serial.print(".");
}
//If connection successful show IP address in serial monitor
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);// connected to given ssid
Serial.print("IP address: ");
Serial.println(WiFi.localIP()); //IP address assigned to your ESP
}
void loop(){
if(WiFi.status()==WL_CONNECTED){ //we will perform action if wifi is connected
HTTPClient http; //intialize object of HTTPclient which is importent
String data="Sunil Kumar Yadav";
//String token="TEST_TOKEN_123";
url1=url1+data;
//full APi url is created you can manipulate those above data and token vaiable.
http.begin(host_url,httpPort,url1);//specify the request,begin the request
int httpCode=http.GET(); //Send the request
// if (httpCode>0){ //lets see the response from server
// String payload = http.getString();//store response on payload variable
// Serial.print("==============");//just for seperating the wifi connection status and server response
// Serial.println(payload);//print the response payload
// }
Serial.print(httpCode);
http.end();//if there is begin there will be end ,it will Close the connection
}
delay(500); //send the request in every 2sec, you can change it according to your need
//you can also specify the time so that it will be easy to identify on which time data is send
}
Following is the output:
301
==============<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>
I dont know how to solve this.
There's one (of several) example how to do this with HTTPs here: https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266HTTPClient/examples/BasicHttpsClient/BasicHttpsClient.ino
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecure.h>
const char* ssid = "myssid";
const char* password = "mypswd";
String url = "https://api-test.technofield.net/api/data?token=TEST_TOKEN_123&data=";
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.println("");
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
if (WiFi.status() == WL_CONNECTED) {
WiFiClientSecure client;
client.setInsecure();
HTTPClient https;
String data = "Sunil%20Kumar%20Yadav";
String fullUrl = url + data;
Serial.println("Requesting " + fullUrl);
if (https.begin(client, fullUrl)) {
int httpCode = https.GET();
Serial.println("============== Response code: " + String(httpCode));
if (httpCode > 0) {
Serial.println(https.getString());
}
https.end();
} else {
Serial.printf("[HTTPS] Unable to connect\n");
}
}
delay(5000);
}
import WiFiClientSecure.h
note how I set client.setInsecure(); which you shouldn't in your real code, rather us the root certificate of your end point as shown here https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/HTTPSRequest/HTTPSRequest.ino#L29
you should URL-encode the data parameter like so String data = "Sunil%20Kumar%20Yadav"

POST request with ESP32 returns 301

I have a NGINX server on a raspberry pi. I want to send JSON file from my ESP32 board to the NGINX web-server.
In a first step, I have followed this tutorial :
https://techtutorialsx.com/2017/05/20/esp32-http-post-requests/
It gives this code :
#include <WiFi.h>
#include <HTTPClient.h>
const char* ssid = "yourNetworkName";
const char* password = "yourNetworkPassword";
void setup() {
Serial.begin(115200);
delay(4000); //Delay needed before calling the WiFi.begin
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { //Check for the connection
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connected to the WiFi network");
}
void loop() {
if(WiFi.status()== WL_CONNECTED){ //Check WiFi connection status
HTTPClient http;
http.begin("http://jsonplaceholder.typicode.com/posts"); //Specify destination for HTTP request
http.addHeader("Content-Type", "text/plain"); //Specify content-type header
int httpResponseCode = http.POST("POSTING from ESP32"); //Send the actual POST request
if(httpResponseCode>0){
String response = http.getString(); //Get the response to the request
Serial.println(httpResponseCode); //Print return code
Serial.println(response); //Print request answer
}else{
Serial.print("Error on sending POST: ");
Serial.println(httpResponseCode);
}
http.end(); //Free resources
}else{
Serial.println("Error in WiFi connection");
}
delay(10000); //Send a request every 10 seconds
}
No problem if I use this code with the following line
http.begin("http://jsonplaceholder.typicode.com/posts");
My serial monitor of the ARDUINO's IDE returns :
201
{
"id": 101
}
But, when I only replace the previous line by
http.begin("http://82.145.56.62:151/postfile");
I get on my serial monitor this :
301
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.10.3</center>
</body>
</html>
Would you have an idea of my problem ?
Thank you ,
EDIT
I have gone ahead a little more. I have created a php file in the directory posts. Now I get the HTTP code 200, so my webserver receive the POST request.
New problem : I cannot figure out how to display the POST content on my php file. Would you have an idea ?
Thank you,
I have solved my problem by replacing :
http.addHeader("Content-Type", "text/plain");
by
http.addHeader("Content-Type", "application/x-www-form-urlencoded");

Wemos D1 404 Not Found - but it is there

I am trying to connect my Wemos D1 to a website to get some data, but I am getting a 404 Not Found Error. I made sure that the url is correct, but I am stilling getting errors. I looked at the errors in the log, but they are empty.
#include <ESP8266WiFi.h>
const char* ssid = "SSID"; // SSID of local network
const char* password = "xxxxx"; // Password on network
String APIKEY = "xxxx";
WiFiClient client;
char servername[]="notreal.com"; // fake host for sample
String result;
int readKey;
int count;
int cursorPosition;
int button;
int x = 0;
void setup() {
//Setup Serial
Serial.begin(9600);
//Connecting to server and get current temperature and set temperature
lcd.print(" Connecting");
Serial.println("Connecting");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("NOT CONNECTED");
lcd.setCursor(cursorPosition,2);
lcd.print(".");
cursorPosition++;
}
getData();
//Serial.println("Connected");*/
delay(1000);
}
void loop() {
//Do Something
}
void getData() //client function to send/receive GET request data.
{
if (client.connect(servername, 80)) { //starts client connection, checks for connection
client.println("GET /data/getData.php?API="+APIKEY);
client.println("HTTP/1.1");
client.println("Host: notreal.com");
client.println("Connection: close");
client.println();
}
else {
Serial.println("connection failed"); //error message if no client connect
Serial.println();
}
while(client.connected() && !client.available()) delay(1); //waits for data
while (client.connected() || client.available()) { //connected or data available
char c = client.read(); //gets byte from ethernet buffer
result = result+c;
}
client.stop(); //stop client
result.replace('[', ' ');
result.replace(']', ' ');
Serial.println(result);
}
This is what I get in the serial:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /nest/getTemp.php was not found on this server.</p>
<p>Additionally, a 404 Not Found
error was encountered while trying to use an ErrorDocument to handle the request.</p>
</body></html>
This is in the error log:
[host.com] [Fri Aug 05 03:57:33 2016] [error] [client 24.28.29.44] client denied by server configuration: /home/domains/host.com/.htaccess
I checked the server setting and according to support, everything should be set for remote access.

Resources