This is a minimal, lightweight HTTP client written in pure C that supports HTTP/1.1, chunked transfer encoding, multiple request methods, and custom headers. The client is designed to be memory-efficient and well-suited for scenarios with constrained storage, such as IoT devices.
The project is designed to be as simple and compact as possible, providing only the core functionality necessary to interact with HTTP servers. It has been tested with scan-build and undergone memory safety checks to ensure robustness.
- HTTP/1.1 Support: Fully compliant with the HTTP/1.1 specification.
- Chunked Transfer Encoding: Supports streaming of large responses using chunked transfer.
- Multiple Request Methods: Supports the following HTTP methods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
- Custom Headers: You can easily customize request headers, including
HostandCookie. - HTTPS/TLS Support: Built-in BearSSL integration with optional verification and pinning.
- Minimalistic Design: Written with minimal lines of code, optimized for environments with limited resources.
- Memory Safety: Passes memory safety checks and has been validated using tools like
scan-build.
The project was originally developed to add communication capabilities to an IoT device. At the time, I found that HTTP clients written in languages like Go were too large and inefficient for embedded systems with limited memory. So, I decided to write a small, efficient HTTP client in C that would fit the requirements of such environments.
No installation is required. Simply clone the repository and include the source files in your project.
You can use musl-gcc if you need fully static linking (glibc static may warn about getaddrinfo).
git clone https://github.com/christarcher/tiny-c-http-client.git
musl-gcc test.c http.c -static -s -Os
./a.outThe HTTPS build expects BearSSL 0.6 sources under third_party/bearssl-0.6.
mkdir -p third_party
curl -L -o third_party/bearssl.tar.gz https://bearssl.org/bearssl-0.6.tar.gz
tar -xzf third_party/bearssl.tar.gz -C third_partyThis client uses BearSSL to support HTTPS. For size reasons, the example uses a single trust anchor (GTS Root R4) to validate www.cloudflare.com.
Build and run (Linux, HTTPS):
cd /data/workspace/tiny-c-http-client
gcc -Ithird_party/bearssl-0.6/inc -Ithird_party/bearssl-0.6/src -O2 -s test.c http.c $(find third_party/bearssl-0.6/src -name '*.c' -print) -o test_https
./test_httpsStatic + strip:
gcc -static -Ithird_party/bearssl-0.6/inc -Ithird_party/bearssl-0.6/src -O2 test.c http.c $(find third_party/bearssl-0.6/src -name '*.c' -print) -o test_https_static
strip -s test_https_static
./test_https_staticTLS options in HTTPRequestInfo:
use_tls, tls_verify, tls_sni, tls_trust_anchors, tls_trust_anchors_num, tls_pinned_key_type, tls_pinned_key.
Notes:
tls_verify=trueuses trust anchors to validate the server certificate.tls_verify=falsedisables validation; optionally settls_pinned_key_type+tls_pinned_keyfor public-key pinning.- If
tls_verify=falseand no pin is set, the connection is insecure (accepts any certificate).
Pinning uses BearSSL public key structures. Provide a known server key and set tls_verify=false.
static unsigned char PIN_RSA_N[] = { /* modulus bytes */ };
static unsigned char PIN_RSA_E[] = { 0x01, 0x00, 0x01 };
static const br_rsa_public_key PIN_RSA = {
PIN_RSA_N, sizeof PIN_RSA_N,
PIN_RSA_E, sizeof PIN_RSA_E
};
HTTPRequestInfo rq = {
/* ... */
.use_tls = true,
.tls_verify = false,
.tls_pinned_key_type = HTTP_TLS_PIN_RSA,
.tls_pinned_key = &PIN_RSA
};For EC keys, use br_ec_public_key and set tls_pinned_key_type = HTTP_TLS_PIN_EC.