-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Strange error from new httpclient #2092
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Did you try to initialize |
@chegewara Yes, I did. And just for triple-checking's sake, I tried again after your suggestion. Replacing
with this
makes no difference. I still get the Guru Meditation Error. I also tried to declare var as a const String. Same result. From the Exception Decoder output and the fact that the sketch works with the older commit just before httpclient update, it seems the reason for the error has to do with the new httpclient. But I cannot figure out why the new httpclient has a problem with a String that is not even passed to it. Maybe @Jeroen88 who has clear understanding of the library inner workings can shed some light... |
This is a strange error indeed. I had a quick glance and can not determine it's cause yet. Could you enable debugging and add the output? |
@Jeroen88 The response from my server is a 60 byte JSON. It should not be a problem. Besides, when I do not pass an irrelevant String to the function, this sketch works fine for payloads bigger than 1Kb. So, this is not the issue. I suppose you suggest the StreamHttpClient example to handle a possibly big payload, but this is not the case as my payload is very small. Besides, the StreamHttpClient example is identical to my sketch. Its changes start after calling the GET() method, while the crash happens earlier in begin(). If I run the example as-is, I'm sure it will have no problem running. But as soon as I convert the example to a function that accepts a String parameter it will crash. Regarding enabling debugging, if you mean adding: Serial.setDebugOutput(true); after: Serial.begin(115200); I tried it but the Serial output is exactly the same. |
Did any of you by any chance tried to flash my sketch in your dev boards and confirm the issue? Please feedback if you did because at this point I start questioning my sanity. This error makes no sense... maybe I'm doing something profoundly wrong in my setup. If I could get a "you're not the only one seeing this" it would help me decide the direction where I should search more for the solution. Thanks! |
OK - important new piece of info: I just move the following line: HTTPClient http; from inside the getPayloadFromServer() function to the top of the sketch just above setup(). This is kind of a reasonable workaround but it makes the http object global, occupying memory all the time. To sum up, for this example sketch:
I think it's best to keep this issue open for two reasons:
I hope all this helps to find the reason. |
No I meant
Thanks for the abundant information that helped to find the bug. |
@Jeroen88 You are the man! I confirm this not only fixes the sketch above but also my main app issue. Thanks! I guess your PR will be merged soon so I'm closing this. |
@mouridis that is good news :). Maybe it is better to reopen the issue and keep it open until the PR is merged? |
I hear you... |
Addressed in commit 0640964 |
I apologize for commenting on this thread so long after a fix was implemented, but I can't seem to get past this issue. I have the most recent versions of HTTPClient and have confirmed the It seems that the issue is happening in the P.S. I apologize for the state of my code, it is still in the very early stages! Hardware:
Error Info
Sketch: #include <stdint.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <Wire.h>
#include <HTTPClient.h>
#include <esp_log.h>
#define SERIAL_BAUDRATE 115200
#define WIFI_SSID "My WIFI Network"
#define WIFI_PASS "My Wifi Password"
#define WARZONE_USERNAME "My Call of Duy Account"
#define WARZONE_PASS "COD Password"
HTTPClient http;
String XSRF;
const char* getXSRFURL = "https://profile.callofduty.com/cod/login";
const char* postLoginURL = "https://profile.callofduty.com/do_login?new_SiteId=cod";
const char* getProfileURL = "https://www.callofduty.com/api/papi-client/crm/cod/v1/identities";
String warzoneUsername = WARZONE_USERNAME;
String warzonePass = WARZONE_PASS;
void setup() {
esp_log_level_set("*", ESP_LOG_DEBUG);
Serial.begin(115200);
begin();
updateXSRF();
login(); //This function call is where the ESP32 crashes and reboots.
}
void loop() {
}
void begin(){
WiFi.begin(WIFI_SSID, WIFI_PASS);
while(WiFi.status() != WL_CONNECTED) {
delay(500);
}
}
void updateXSRF(){
if(WiFi.status()== WL_CONNECTED){
http.begin(getXSRFURL);
int httpResponseCode = -1;
int timeout = 0;
while(httpResponseCode < 0 && timeout < 10){
httpResponseCode = http.GET();
delay(50);
timeout++;
}
if (httpResponseCode>0) {
String payload = http.getString();
XSRF = parseXSRF(payload);
}else{
XSRF = "";
}
// Free resources
http.end();
}
}
String getXSRF(){
return XSRF;
}
String parseXSRF(String payload){
int index = 0;
String token = "";
if(payload.indexOf("_csrf") > 0){
index = payload.indexOf("_csrf");
while(payload.charAt(index) != '='){
index++;
}
index += 2;
while(payload.charAt(index) != '"'){
token += payload.charAt(index);
index++;
}
}
return token;
}
void login(){
if(WiFi.status()== WL_CONNECTED){
http.begin(postLoginURL);
String httpRequestData = getLoginRequestData();
http.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
http.addHeader("Accept-Encoding", "gzip, deflate, br");
http.addHeader("Connection", "keep-alive");
http.addHeader("Content-Length", String(httpRequestData.length()));
http.addHeader("Cookie", "XSRF-TOKEN=" + getXSRF() + ";new_SiteId=cod;tfa_enrollment_seen=true;");
const char * headerKeys[] = {"Location"};
http.collectHeaders(headerKeys, 1);
int httpResponseCode = http.POST(httpRequestData);
if(httpResponseCode == 302){
//TODO
}
// Free resources
http.end();
}
}
String getLoginRequestData(){
String output = "username=";
output += warzoneUsername;
output += "&password=" + warzonePass;
output += "&remember_me=true";
output += "&_csrf="+getXSRF();
return output;
} |
please decode the backtrace with the ESP Exception Decoder :) |
Thanks for the tool! I have followed your instructions, but I'm able to determine what the issue is from the extra information provided. Here is the output from ESP Exception Decoder:
Does that mean anything to you? |
I am not sure if it will solve your problem, but an important issue is that you are trying to connect to a secure server (https) with a WiFiClient. This will never work! You should use a WiFiClientSecure (see this example). Using https requires you to pass a root certificate to the WiFiClientSecure and to set the time (like in the example). Further, you should use the new API, so one of the following:
instead of the Next, if you Finally, leave out
because HTTP client can not handle zipped or inflated data. |
Thank you for the help, but I'm not sure if this is an issue with the Call of Duty servers, or something else, but I only get the connection refused message with the HTTPClientSecure, even after updating the certificate to the DigiCert one.
I have tried this same GET request with Python on a Raspberry Pi and it seems to be working just fine, but it doesn't require any certificate configuration, so that is what I'm thinking I did wrong. Is there any specific process that I could be getting wrong when capturing the certificate? Thanks in advance! |
Did you set the ESP time? Certificates have a validity period that is checked using system time. The right certificate shoud be
You could try to call |
Thanks so much for the help, that certificate worked with the COD server. If I used this in my code, how often would I need to reflash the ESP32 with an updated certificate? On that note, how did you obtain this certificate, and is it not recommended to use the Thanks again for the help! |
I do not understand your question, you need to reflash the ESP after every change, and after that you can start it over and over again.
That's easy, click on the padlock in your browser and click some options until you find the .pem file.
The whole idea of https / TLS is to encrypt the exchange of information and to identify at least one of the communicating parties (mostly the client identifies the server). Using this function the server identify is not checked, and could be spoofed. This issue part of github is intended however to track issues in the libraries for the ESP32. Your questions are general user questions. Please read the examples with the libraries, find information on the internet or use e.g. gitter to get help. If any library issues retain please report them here. |
Hardware:
Board: WEMOS LOLIN32
Core Installation/update date: Commit c3ec91f
IDE name: Arduino IDE 1.8.6
Flash Frequency: 80Mhz
PSRAM enabled: NoUpload Speed: 921600
Computer OS: Windows 10 x64
Description:
Updating to the latest commit (c3ec91f) yesterday broke my app in a very strange way. After hours trying to figure out what's wrong, it seems that when a String object is passed in a function that uses httpclient it results in a Guru Meditation Error.
You should have no problem reproducing the issue using the following sketch:
Just edit APSSID and APPassphrase to your situation and this will cause a Guru Meditation Error with this trace:
Using ESP Exception Decoder with the above trace, I get this:
Now... somehow this problem doesn't happen if the String type parameter is removed from the getPayloadFromServer function. Allow me to offer the same sketch with only two changes in two lines to reflect the parameter removal from the getPayloadFromServer function:
This only changes lines 25 and 36 from the previous sketch and it executes fine!
Another way to avoid the issue is to fallback to commit b70737d, right before httpclient lib was updated to 1.2.
Can anybody offer any possible explanation why this happens?
I hope it's clear that I'm not looking for workarounds. In the above example sketch passing the String object as a parameter is useless (the message variable is not even used anywhere in the function). But in my full app I really need to pass a String object to the function. I am well aware that there are other ways to access a piece of text from the function (setting a global var, using char arrays etc).
I really can't understand how passing a String object that is not even used affects httpclient...
Thanks
The text was updated successfully, but these errors were encountered: