Reading API Chunked Response in C
Posted: Wed Jun 05, 2024 2:36 pm
I'm building a Firebase API in C for esp32-c3
Currently I'm able to construct the url and perform a request but for some reason I can't read any data from the response and response len is always 0
here's the code and the output
Output
Any idea what am I doing wrong?
This is the equivalent of what I'm trying to do in Python, which works perfectly
Thanks.
Currently I'm able to construct the url and perform a request but for some reason I can't read any data from the response and response len is always 0
here's the code and the output
Code: Select all
void firebase_login_user(Firebase* self, char* email, char* password) {
char* url = malloc(strlen(self->api_key) + 78);
if (url == NULL) {
ESP_LOGE(TAG, "Error allocating memory for URL");
return;
}
strcpy(url, "https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=");
char *full_url = strjoin(url, self->api_key);
free(url); // Free the initial allocation
if (!full_url) {
ESP_LOGE(TAG, "Error joining URL");
return;
}
cJSON *root = cJSON_CreateObject();
cJSON_AddStringToObject(root, "email", email);
cJSON_AddStringToObject(root, "password", password);
cJSON_AddTrueToObject(root, "returnSecureToken");
char *data = cJSON_Print(root);
ESP_LOGI(TAG, "URL: %s", full_url);
ESP_LOGI(TAG, "JSON: %s", data);
esp_http_client_config_t config = {
.url = full_url,
.method = HTTP_METHOD_POST,
.transport_type = HTTP_TRANSPORT_OVER_SSL,
};
esp_http_client_handle_t client = esp_http_client_init(&config);
if (client == NULL) {
ESP_LOGE(TAG, "Failed to initialize HTTP client");
free(full_url);
cJSON_Delete(root);
free(data);
return;
}
esp_http_client_set_header(client, "Content-Type", "application/json; charset=UTF-8");
esp_http_client_set_post_field(client, data, strlen(data));
esp_err_t err = esp_http_client_perform(client);
if (err == ESP_OK) {
ESP_LOGI(TAG, "HTTP POST Status = %d, %s", err, esp_err_to_name(err));
int http_status = esp_http_client_get_status_code(client);
ESP_LOGI(TAG, "HTTP Status Code = %d", http_status);
int content_length = esp_http_client_get_content_length(client);
ESP_LOGI(TAG, "Content Length = %d", content_length);
if (http_status == 200) {
if (content_length == -1) {
// Handle chunked transfer encoding
ESP_LOGI(TAG, "Chunked response");
char *buffer = malloc(512);
if (buffer == NULL) {
ESP_LOGE(TAG, "Error allocating memory for buffer");
} else {
int total_data_read = 0;
int data_read;
do {
data_read = esp_http_client_read(client, buffer, 512);
if (data_read > 0) {
buffer[data_read] = '\0'; // Null-terminate the response
ESP_LOGI(TAG, "Chunk: %s", buffer);
total_data_read += data_read;
} else if (data_read < 0) {
ESP_LOGE(TAG, "Error reading data");
}
} while (data_read > 0);
ESP_LOGI(TAG, "Total data read: %d", total_data_read);
free(buffer);
}
} else {
// Handle non-chunked response
char *buffer = malloc(content_length + 1);
if (buffer == NULL) {
ESP_LOGE(TAG, "Error allocating memory for buffer");
} else {
int total_data_read = esp_http_client_read(client, buffer, content_length);
if (total_data_read >= 0) {
buffer[total_data_read] = '\0'; // Null-terminate the response
ESP_LOGI(TAG, "Response: %s", buffer);
} else {
ESP_LOGE(TAG, "Error reading data");
}
free(buffer);
}
}
} else {
ESP_LOGE(TAG, "Unexpected HTTP status code: %d", http_status);
}
} else {
ESP_LOGE(TAG, "Error performing HTTP request: %s", esp_err_to_name(err));
}
esp_http_client_cleanup(client);
cJSON_Delete(root);
free(data);
free(full_url);
}
Code: Select all
I (12824) netlog: HTTP POST Status = 0, ESP_OK
I (12824) netlog: HTTP Status Code = 200
I (12824) netlog: Content Length = -1
I (12824) netlog: Chunked response
I (12834) netlog: Total data read: 0
I (12834) main_task: Returned from app_main()
This is the equivalent of what I'm trying to do in Python, which works perfectly
Code: Select all
def login_user(self, email, password):
request_link = f"https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key={self.api_key}"
headers = {"content-type": "application/json; charset=UTF-8"}
data = json.dumps({"email": email, "password": password, "returnSecureToken": True})
request_data = self.requests.post(request_link, headers=headers, data=data)
self.error_http(request_data)
self.currentUser = request_data.json()
self.token = self.currentUser["idToken"]
return request_data.json()