How to get cookies from a server using Arduino

I would like to obtain a CSRF cookie from a website on my arduino similarly to this issue: https://github.com/esp8266/Arduino/issues/1368

But I am not able to read any part of the header.

My relevant code:

String httpGETRequest(const char* serverName) {
  WiFiClientSecure client;
  client.setInsecure();
  HTTPClient http;
  const char * headerkeys[] = {"User-Agent","Set-Cookie","Cookie","Date","Content-Type","Connection"} ;
  size_t headerkeyssize = sizeof(headerkeys)/sizeof(char*);
  // serverName is the website I want to parse 
  http.begin(client, serverName);
   

  http.collectHeaders(headerkeys,headerkeyssize);
  Serial.printf("Header count: %d\r\n", http.headers());
  for (int i=0; i < http.headers(); i++) {
    Serial.printf("%s = %s\r\n", http.headerName(i).c_str(), http.header(i).c_str());
  }
  Serial.printf("Cookie: %s\r\n", http.header("Cookie").c_str());
  Serial.printf("Set-Cookie: %s\r\n", http.header("Set-Cookie").c_str());
  String payload = "{}"; 
  http.end();

  return payload;
}

However all fields are empty, nothing is returned. What am I doing wrong?

Can you post all of the code and what you see in the serial monitor?

This way we can reproduce your issue.

[edit] I do not see a request, so then I guess there are no response headers to collect.

So basically I would like to gather a CSRF token in order to be able to POST request.

I have codes in python, and there I only need an request session so I though it is similar here.

My full code:

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

const char* ssid = "my_ess_id";
const char* password = "my_password";

//Your Domain name with URL path or IP address with path
const char* serverName = "https://user.gravitybudapest.com";


// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastTime = 0;
// Timer set to 10 minutes (600000)
//unsigned long timerDelay = 600000;
// Set timer to 5 seconds (5000)
unsigned long timerDelay = 5000;

String sensorReadings;
float sensorReadingsArr[3];

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

  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
 
  Serial.println("Timer set to 5 seconds (timerDelay variable), it will take 5 seconds before publishing the first reading.");
}

void loop() {
  // Send an HTTP POST request depending on timerDelay
  if ((millis() - lastTime) > timerDelay) {
    //Check WiFi connection status
    if(WiFi.status()== WL_CONNECTED){
              
      sensorReadings = httpGETRequest(serverName);
      Serial.println(sensorReadings);
      JSONVar myObject = JSON.parse(sensorReadings);
  
      // JSON.typeof(jsonVar) can be used to get the type of the var
      if (JSON.typeof(myObject) == "undefined") {
        Serial.println("Parsing input failed!");
        return;
      }
    
      Serial.print("JSON object = ");
      Serial.println(myObject);
    
      // myObject.keys() can be used to get an array of all the keys in the object
      JSONVar keys = myObject.keys();
    
      for (int i = 0; i < keys.length(); i++) {
        JSONVar value = myObject[keys[i]];
        Serial.print(keys[i]);
        Serial.print(" = ");
        Serial.println(value);
        sensorReadingsArr[i] = double(value);
      }
    }
    else {
      Serial.println("WiFi Disconnected");
    }
    lastTime = millis();
  }
}

String httpGETRequest(const char* serverName) {
  WiFiClientSecure client;
  client.setInsecure();
  HTTPClient http;
  String jsondata=("{\"nfc_id\": \"5365e544\"}");
  const char * headerkeys[] = {"User-Agent","Set-Cookie","Cookie","Date","Content-Type","Connection"} ;
  size_t headerkeyssize = sizeof(headerkeys)/sizeof(char*);
  // Your IP address with path or Domain name with URL path 
  http.begin(client, serverName);
  //http.addHeader("Content-Type", "Content-Type: application/json"); 

  http.collectHeaders(headerkeys,headerkeyssize);
  Serial.printf("Header count: %d\r\n", http.headers());
  for (int i=0; i < http.headers(); i++) {
    Serial.printf("%s = %s\r\n", http.headerName(i).c_str(), http.header(i).c_str());
  }
  Serial.printf("Cookie: %s\r\n", http.header("Cookie").c_str());
  Serial.printf("Set-Cookie: %s\r\n", http.header("Set-Cookie").c_str());
  String payload = "{}"; 
//  int httpResponseCode = http.POST(jsondata); //Send the actual POST request
  int httpResponseCode = http.GET(); //Send the actual POST request

  
  if (httpResponseCode>0) {
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    payload = http.getString();
  }
  else {
    Serial.print("Error code: ");
    Serial.println(httpResponseCode);
  }
  // Free resources
  http.end();

  return payload;
}

Thank you. Can you also share the output of the serial monitor?

I am sorry, this is my first time working on chips.

The output:

Connected to WiFi network with IP Address: 192.168.1.5
Timer set to 5 seconds (timerDelay variable), it will take 5 seconds before publishing the first reading.
Header count: 6
User-Agent = 
Set-Cookie = 
Cookie = 
Date = 
Content-Type = 
Connection = 
Cookie: 
Set-Cookie: 
HTTP Response code: 200

Parsing input failed!
Header count: 6
User-Agent = 
Set-Cookie = 
Cookie = 
Date = 
Content-Type = 
Connection = 
Cookie: 
Set-Cookie: 
HTTP Response code: 200

As for the parsing input failed it is fine, I was able to parse JSON data from certain sources where only a GET request was required. I want to set up a POST request this time, but the server requires a CSRF token, which should be in the cookies of the header.

I am using a NodeMCU board if that matters!

I am not familiar with this library, but what happens when you change this:

  Serial.printf("Header count: %d\r\n", http.headers());
  for (int i=0; i < http.headers(); i++) {
    Serial.printf("%s = %s\r\n", http.headerName(i).c_str(), http.header(i).c_str());
  }
  Serial.printf("Cookie: %s\r\n", http.header("Cookie").c_str());
  Serial.printf("Set-Cookie: %s\r\n", http.header("Set-Cookie").c_str());
  String payload = "{}"; 
//  int httpResponseCode = http.POST(jsondata); //Send the actual POST request
  int httpResponseCode = http.GET(); //Send the actual POST request

to this:

  int httpResponseCode = http.GET(); //Send the actual POST request
  Serial.printf("Header count: %d\r\n", http.headers());
  for (int i=0; i < http.headers(); i++) {
    Serial.printf("%s = %s\r\n", http.headerName(i).c_str(), http.header(i).c_str());
  }
  Serial.printf("Cookie: %s\r\n", http.header("Cookie").c_str());
  Serial.printf("Set-Cookie: %s\r\n", http.header("Set-Cookie").c_str());
  String payload = "{}"; 
//  int httpResponseCode = http.POST(jsondata); //Send the actual POST request

(only moved one line).

Ohh man thanks a lot. now I get the correct headers! Sorry fo the noob question, I thought http.begin already sets up a session much like in Python!

Thanks a lot!

No problem. You can use the solution tickbox to indicate that the issue was solved to prevent other people spending time reading it.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.