C++ HTTP/HTTPS client library for Raspberry Pi Pico W / Pico 2 W using Pico SDK + lwIP (+ mbedTLS for HTTPS).
- HTTP and HTTPS support
- Works with both polling and FreeRTOS-based Pico SDK architectures
- Custom request headers
- Lightweight API for embedded projects
- Raspberry Pi Pico SDK
- Pico W / Pico 2 W board support
- lwIP
- mbedTLS (for HTTPS)
http_library/HttpClient.h/http_library/HttpClient.cppMain client implementationhttp_library/wifi_helper.h/http_library/wifi_helper.cppWi-Fi helper functionshttp_library/CMakeLists.txtCMake configuration for integrating the library
The application using this library must provide:
lwipopts.hmbedtls_config.h
#include "HttpClient.h"
#include "wifi_helper.h"
#include "pico/cyw43_arch.h"
int main() {
stdio_init_all();
if (cyw43_arch_init()) {
printf("WiFi init failed\n");
return 1;
}
if (!connect_wifi_helper("YOUR_WIFI_SSID", "YOUR_WIFI_PASSWORD", 15000)) {
printf("Wi-Fi connect failed\n");
return 1;
}
HttpClient client = HttpClient(); //create httpclient object
client.set_ca_cert(PICOHTTPS_CA_GTS_ROOT4,sizeof(PICOHTTPS_CA_GTS_ROOT4)); //set cert
const char* path = "/";
client.connect_to_server("server_ip_or_domain");
while (!client.ready()) {
client.keep_alive(); //needed for lwIP poll architecture
}
if (!client.is_connected()){ //check connection status
return 1;
}
client.send_http_request("GET", path, nullptr, nullptr,nullptr,0);
while (!client.ready()) {
client.keep_alive(); //needed for lwIP poll architecture
}
//Check whether the request failed:
if (!client.request_succeeded()) {
return 1;
}
//get response:
printf("%s", client.get_buffer());
return 0;
}Your main project should include Pico SDK, add this library as subdirectory, and define mbedTLS config:
cmake_minimum_required(VERSION 3.12)
set(PICO_BOARD pico2_w)
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(my_app C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
# Make lwipopts.h visible for lwIP build
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR})
pico_sdk_init()
set(HTTP_LIBRARY_USE_FREERTOS OFF) #Use polling architecture (set ON for FreeRTOS)
add_subdirectory(http_library)
add_executable(${PROJECT_NAME}
main.cpp
)
target_compile_definitions(${PROJECT_NAME} PRIVATE
MBEDTLS_CONFIG_FILE="mbedtls_config.h"
)
target_link_libraries(${PROJECT_NAME}
pico_stdlib
pico_mbedtls
pico_lwip_mbedtls
http_library
)
pico_add_extra_outputs(${PROJECT_NAME})void send_https_request(const char* method,const char* path,const char* body = nullptr,const char* content_type = nullptr,const HttpHeader* headers = nullptr,size_t header_count = 0);
HttpHeader rheaders[1] = {0};
strcpy(rheaders[0].key, "Header_key");
strcpy(rheaders[0].value, "value");
client.send_http_request("POST", path, nullptr, nullptr,rheaders,1);
By default, received data is stored in an internal buffer and parsed automatically.
You can override this by registering callbacks. This is useful for streaming large responses (for example firmware updates) without buffering the entire response.
set_data_callback() is called for each received data chunk:
client.set_data_callback([](const uint8_t* data, size_t len, void* arg) {
static_cast<FirmwareUpdater*>(arg)->feed(data, len);
}, &updater);set_done_callback() is called once when the response is complete:
client.set_done_callback([](void* arg) {
static_cast<FirmwareUpdater*>(arg)->finalize();
});Note: If callbacks are registered,
get_buffer()will be empty. If no callbacks are registered, the response is available viaget_buffer()afterready()returnstrue.
//google gts root 4
#define PICOHTTPS_CA_GTS_ROOT4 "-----BEGIN CERTIFICATE-----\n\
MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD\n\
VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG\n\
A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw\n\
WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz\n\
IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi\n\
AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi\n\
QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR\n\
HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW\n\
BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D\n\
9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8\n\
p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD\n\
-----END CERTIFICATE-----\n"
-
lwipopts.hmust be available in the include path. The current setup expects it at the project root. -
mbedtls_config.his selected via:target_compile_definitions(... MBEDTLS_CONFIG_FILE="mbedtls_config.h")
-
By default, the library uses the lwIP polling architecture (
pico_cyw43_arch_lwip_poll). -
To use the FreeRTOS architecture, set the following in your top-level
CMakeLists.txtbefore callingadd_subdirectory(http_library):set(HTTP_LIBRARY_USE_FREERTOS ON) #(ON/OFF)
Set it to
OFFto use the default polling architecture.
The following configuration defines are defined in HttpClient.h:
#define RECV_BUF_SIZE
#define MAX_CERTIFICATE_LEN
#define MAX_REQUEST_METHOD_LEN
#define PATH_MAX
#define MAX_REQUEST_LEN
#define MAX_CONTEN_TYPE_LEN
#define MAX_REQUEST_BODY_LEN
#define MAX_HEADERS This project depends on third-party libraries (such as Pico SDK, lwIP, and mbedTLS), which are distributed under their own licenses.