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
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?
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;
}
}
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"
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");
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.