A simple JSON capable REST HTTP Client for ESP32 IDF

readme

# HTTP REST Client A Client library for ESP32 and [ESP-IDF](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/). **This library is far from complete! It's missing some core features for REST (like authentication...) and its probably full of lurking C rookie mistakes, security holes, and more bugs than the amazon rainforest. I only created it to abstract away some of the boilerplate of working with REST endpoints based on the ESP-IDF docs** _feel free to open a Pull Request to add or fix things_ # Why? ESP-IDF provides a robust [HTTP Client library](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/protocols/esp_http_client.html) already, why would I need this library too? The answer is you don't need it. You probably don't even want it. But because the provided client library is robust, it also means its a bit complicated and for most people, we only need some simple http operations for interacting with REST endpoints. You shouldn't need to know how to manage chunked vs non-chunked responses or how to construct the required connection config to post a json object. I just want the ENTIRE response body loaded in a buffer I provide to do with what I want. And i don't want to copy around 40 lines of code for every request to do it! I made this for me. If you find use in it, GREAT! If you want to improve it for you, EVEN BETTER! # Requirements This was developed and tested on ESP-IDF 5.0.2 and 5.1 (no guarantee it will work in earlier or future versions) You will also will likely need to update your Max HTTP Request Header Length in the menuconfig or `sdkconfig` to something a bit higher than the default `512`. _Note: Most modern browsers use something between `4096` and `8192` for reference. I find that `2048` is about right for most standard REST services out in the wild, but tune this for your requirements._ # Installation Using the IDF Component Registry (Recommended) ``` idf.py add-dependency "parabuzzle/http_rest_client^0.1.4" ``` Clone a local copy to your project ``` mkdir components cd components git clone https://github.com/parabuzzle/idf_http_rest_client.git ## OR Use Git Submodules git submodule add https://github.com/parabuzzle/idf_http_rest_client.git ``` # Configuration All configuration is provided through `menuconfig` and the Kconfig.projbuild file. # Usage You can find a runnable working example in the [examples](/examples) directory This is a basic idea of how it works: _yes, its literally a single line to load the buffer with the response!_ ```c #include "http_rest_client.h" void app_main(void) { while (1) { http_rest_recv_buffer_t response_buffer = {0}; // do the request ESP_ERROR_CHECK(http_rest_client_get("https://catoftheday.com/", &response_buffer)); // print response status sprintf("Status Code %d", response_buffer.status_code); // do something with the data printf(response_buffer.buffer); // clean up http_rest_client_cleanup(&response_buffer); // wait and loop vTaskDelay(1000 / portTICK_PERIOD_MS); } } ``` ## HTTPS? Yep! If you have the mbed-tls certificate bundle enabled for the chip in sdkconfig, I just load it in automatically. You don't need to do anything to do https requests aside from make sure `CONFIG_MBEDTLS_CERTIFICATE_BUNDLE` is enabled. What if you want to provide your own cert bundle pem or you can't use the mbed-tls bundle? I got you beau! You just need to initialize the pem in the library like this: ```c #include "http_rest_client.h" void app_main(void) { char *cert = "----begin certificate--- etc" // initialize a cert bundle ESP_ERROR_CHECK(http_rest_client_init_cert(cert, strlen(cert))); // go about your business... // remove the attached bundle ... why? I don't know... but you _can_ ESP_ERROR_CHECK(http_rest_client_deinit_cert()); } ``` ## Do you have a JSON Example? You Betcha' You can send that response object directly to cJSON: ```c #include "http_rest_json_client.h" void app_main(void) { http_rest_recv_json_t response_buffer = {0}; // do the request ESP_ERROR_CHECK(http_rest_client_get_json("https://rickandmortyapi.com/api/character/1", &response_buffer)); if (response_buffer.status_code != 200){ ESP_LOGE(TAG, "an http error occured: %d", response_buffer.status_code); } else { char *jsonString = cJSON_Print(response_buffer.json); ESP_LOGI(TAG, "Response: %s", jsonString); free(jsonString); } http_rest_client_cleanup_json(&response_buffer); } ``` What if you want to post json data? yea, it does that too: ```c #include "http_rest_json_client.h" void app_main(void) { http_rest_recv_json_t response_buffer = {0}; cJSON *json_body = cJSON_CreateObject(); cJSON_AddStringToObject(json_body, "hello", "world"); // do the request ESP_ERROR_CHECK(http_rest_client_post_json("https://httpbin.org/anything", json_body, &response_buffer)); if (response_buffer.status_code != 200){ ESP_LOGE(TAG, "an http error occured: %d", response_buffer.status_code); } else { char *jsonString = cJSON_Print(response_buffer.json); ESP_LOGI(TAG, "Response: %s", jsonString); free(jsonString); cJSON_Delete(json_body); } http_rest_client_cleanup_json(&response_buffer); } ``` # License MIT License Copyright (c) 2023 Michael Heijmans Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

changelog

# Change Log ## Version 0.1.4 - Fixed documentation - Cleaned up configuration - Added Changelog ## Version 0.1.3 - Fix bug that didn't return an `ESP_OK` on 2xx status codes ## Version 0.1.2 - Removed dist dir from repo ## Version 0.1.1 Initial available version ## Version 0.1.0 Yanked because version mismatch

readme of http_get_and_parse_json example

# HTTP REST Client Get and Parse JSON example This is an example of getting json from the internet and parsing it. In this example, we create a wifi connection using your ssid and password (edit this in the main.c file) and then get an https endpoint every second. # Configure the Project - open the project config menu (`idf.py menuconfig`) - Configure the buffers under "HTTP REST Client" # Build and Flash ``` idf.py -p PORT flash monitor ``` # Example Log Output ``` rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:2 load:0x3fff0030,len:7076 load:0x40078000,len:15576 load:0x40080400,len:4 0x40080400: _init at ??:? load:0x40080404,len:3876 entry 0x4008064c I (29) boot: ESP-IDF v5.1 2nd stage bootloader I (29) boot: compile time Jul 16 2023 18:11:40 I (29) boot: Multicore bootloader I (33) boot: chip revision: v3.0 I (37) boot.esp32: SPI Speed : 40MHz I (42) boot.esp32: SPI Mode : DIO I (46) boot.esp32: SPI Flash Size : 16MB I (51) boot: Enabling RNG early entropy source... I (56) boot: Partition Table: I (60) boot: ## Label Usage Type ST Offset Length I (67) boot: 0 nvs WiFi data 01 02 00009000 00006000 I (75) boot: 1 phy_init RF data 01 01 0000f000 00001000 I (82) boot: 2 factory factory app 00 00 00010000 00100000 I (90) boot: End of partition table I (94) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=391e0h (233952) map I (187) esp_image: segment 1: paddr=00049208 vaddr=3ffb0000 size=03804h ( 14340) load I (193) esp_image: segment 2: paddr=0004ca14 vaddr=40080000 size=03604h ( 13828) load I (199) esp_image: segment 3: paddr=00050020 vaddr=400d0020 size=a0f14h (659220) map I (439) esp_image: segment 4: paddr=000f0f3c vaddr=40083604 size=12030h ( 73776) load I (481) boot: Loaded app from partition at offset 0x10000 I (481) boot: Disabling RNG early entropy source... I (492) cpu_start: Multicore app I (493) cpu_start: Pro cpu up. I (493) cpu_start: Starting app cpu, entry point is 0x400813a4 0x400813a4: call_start_cpu1 at C:/Users/parab/esp-v5.1/esp-idf/components/esp_system/port/cpu_start.c:154 I (0) cpu_start: App cpu up. I (511) cpu_start: Pro cpu start user code I (511) cpu_start: cpu freq: 160000000 Hz I (511) cpu_start: Application information: I (515) cpu_start: Project name: http-client-test I (521) cpu_start: App version: 1 I (525) cpu_start: Compile time: Jul 16 2023 18:11:06 I (532) cpu_start: ELF file SHA256: 1a6f2bf9890316e4... I (538) cpu_start: ESP-IDF: v5.1 I (542) cpu_start: Min chip rev: v0.0 I (547) cpu_start: Max chip rev: v3.99 I (552) cpu_start: Chip rev: v3.0 I (557) heap_init: Initializing. RAM available for dynamic allocation: I (564) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM I (570) heap_init: At 3FFB8448 len 00027BB8 (158 KiB): DRAM I (576) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM I (582) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM I (589) heap_init: At 40095634 len 0000A9CC (42 KiB): IRAM I (597) spi_flash: detected chip: generic I (600) spi_flash: flash io: dio I (605) app_start: Starting scheduler on CPU0 I (609) app_start: Starting scheduler on CPU1 I (609) main_task: Started on CPU0 I (619) main_task: Calling app_main() I (619) main: Starting app_main... I (679) wifi:wifi driver task: 3ffc057c, prio:23, stack:6656, core=0 I (709) wifi:wifi firmware version: b2f1f86 I (709) wifi:wifi certification version: v7.0 I (709) wifi:config NVS flash: enabled I (709) wifi:config nano formating: disabled I (709) wifi:Init data frame dynamic rx buffer num: 32 I (719) wifi:Init management frame dynamic rx buffer num: 32 I (719) wifi:Init management short buffer num: 32 I (729) wifi:Init dynamic tx buffer num: 32 I (729) wifi:Init static rx buffer size: 1600 I (739) wifi:Init static rx buffer num: 10 I (739) wifi:Init dynamic rx buffer num: 32 I (749) wifi_init: rx ba win: 6 I (749) wifi_init: tcpip mbox: 32 I (749) wifi_init: udp mbox: 6 I (759) wifi_init: tcp mbox: 6 I (759) wifi_init: tcp tx win: 5744 I (759) wifi_init: tcp rx win: 5744 I (769) wifi_init: tcp mss: 1440 I (769) wifi_init: WiFi IRAM OP enabled I (779) wifi_init: WiFi RX IRAM OP enabled I (779) phy_init: phy_version 4670,719f9f6,Feb 18 2021,17:07:07 I (889) wifi:mode : sta (b8:d6:1a:01:e7:a8) I (889) wifi:enable tsf I (889) main: Waiting for WiFi connection... I (889) WIFI_EVENT: WiFi station connecting... I (909) wifi:new:<4,0>, old:<1,0>, ap:<255,255>, sta:<4,0>, prof:1 I (909) wifi:state: init -> auth (b0) I (919) wifi:state: auth -> assoc (0) I (929) wifi:state: assoc -> run (10) I (959) wifi:connected with <redacted>, aid = 18, channel 4, BW20, bssid = 9a:9e:43:b5:87:70 I (959) wifi:security: WPA2-PSK, phy: bgn, rssi: -62 I (969) wifi:pm start, type: 1 I (969) wifi:AP's beacon interval = 102400 us, DTIM period = 1 I (979) wifi:<ba-add>idx:0 (ifx:0, 9a:9e:43:b5:87:70), tid:0, ssn:0, winSize:64 I (6469) esp_netif_handlers: sta ip: <redacted>, mask: <redacted>, gw: <redacted> I (6469) main: WiFi connected I (6469) main: Starting Main Loop... I (6469) main: Fetching Data from URL: https://jsonplaceholder.typicode.com/todos/1 I (7749) esp-x509-crt-bundle: Certificate validated I (8879) main: Raw Response string: { "userId": 1, "id": 1, "title": "delectus aut autem", "completed": false } I (8879) main: Parsed correctly! I (8879) main: Response JSON: { "userId": 1, "id": 1, "title": "delectus aut autem", "completed": false } I (8889) main: Looping in 1 sec... ```

Supports all targets

License: MIT

To add this component to your project, run:

idf.py add-dependency "parabuzzle/http_rest_client^0.1.4"

or download archive

Examples:

http_get_and_parse_json

more details

Stats

  • Downloaded in total
    Downloaded in total 19 times
  • Downloaded this version
    This version: 13 times

Badge

parabuzzle/http_rest_client version: 0.1.4 |