RepoPilotOpen in app →

yhirose/cpp-httplib

A C++ header-only HTTP/HTTPS server and client library

Healthy

Healthy across all four use cases

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit today
  • 7 active contributors
  • MIT licensed
Show 3 more →
  • CI configured
  • Tests present
  • Single-maintainer risk — top contributor 93% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/yhirose/cpp-httplib)](https://repopilot.app/r/yhirose/cpp-httplib)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/yhirose/cpp-httplib on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: yhirose/cpp-httplib

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/yhirose/cpp-httplib shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across all four use cases

  • Last commit today
  • 7 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Single-maintainer risk — top contributor 93% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live yhirose/cpp-httplib repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/yhirose/cpp-httplib.

What it runs against: a local clone of yhirose/cpp-httplib — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in yhirose/cpp-httplib | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 30 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>yhirose/cpp-httplib</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of yhirose/cpp-httplib. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/yhirose/cpp-httplib.git
#   cd cpp-httplib
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of yhirose/cpp-httplib and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "yhirose/cpp-httplib(\\.git)?\\b" \\
  && ok "origin remote is yhirose/cpp-httplib" \\
  || miss "origin remote is not yhirose/cpp-httplib (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "httplib.h" \\
  && ok "httplib.h" \\
  || miss "missing critical file: httplib.h"
test -f "CMakeLists.txt" \\
  && ok "CMakeLists.txt" \\
  || miss "missing critical file: CMakeLists.txt"
test -f ".github/workflows/test.yaml" \\
  && ok ".github/workflows/test.yaml" \\
  || miss "missing critical file: .github/workflows/test.yaml"
test -f "README.md" \\
  && ok "README.md" \\
  || miss "missing critical file: README.md"
test -f "docs-src/pages/en/cookbook/index.md" \\
  && ok "docs-src/pages/en/cookbook/index.md" \\
  || miss "missing critical file: docs-src/pages/en/cookbook/index.md"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 30 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~0d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/yhirose/cpp-httplib"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

cpp-httplib is a C++11 header-only HTTP/HTTPS server and client library that allows developers to build both sides of HTTP communication in a single file include (httplib.h). It supports multiple TLS backends (OpenSSL, Mbed TLS, wolfSSL), streaming APIs, WebSocket, and Server-Sent Events, making it suitable for anything from embedded systems to full application servers. Single-header library structure: the core httplib.h contains all functionality (Client, Server, SSLServer, Request, Response classes). Supporting structure includes CMakeLists.txt and Meson build configs for integration, docker/ with example server, benchmark/ comparing against Crow, and docs-src/ with markdown cookbooks covering SSL, streaming, WebSocket, proxy, multipart uploads, etc.

👥Who it's for

C++ developers building networked applications (embedded systems, microservices, testing tools) who need straightforward HTTP/HTTPS communication without heavyweight dependencies or async complexity. Also used by library authors who want to ship HTTP capabilities without external linking requirements.

🌱Maturity & risk

Production-ready and actively maintained. The library has CI across 10+ test workflows (test.yaml, test-32bit.yml, test_proxy.yaml, etc.), comprehensive documentation in docs-src/, and regular releases. However, it explicitly does NOT support HTTP/2 or HTTP/3, and uses blocking socket I/O only—design choices that fit its niche but limit its scope.

Single-file design means the entire codebase lives in httplib.h (~2.7M C++) with no modular separation—large changes could affect many users. Maintains only one primary maintainer (yhirose). Does NOT support 32-bit platforms and explicitly closes security reports for 32-bit environments. The 'blocking I/O only' constraint means it's unsuitable for high-concurrency servers without threading overhead.

Active areas of work

Active maintenance with CI workflows validating against multiple TLS backends and platforms. Recent work visible in workflows for ABI checking (abidiff.yaml), libFuzzer integration (cifuzz.yaml), and benchmarking (test_benchmark.yaml). Documentation is being built with docs-gen, and there are cookbooks for emerging patterns like chunked uploads and compression.

🚀Get running

git clone https://github.com/yhirose/cpp-httplib.git
cd cpp-httplib
# For header-only use: just include httplib.h in your project
# For building examples/tests:
make
# Or with CMake:
mkdir build && cd build && cmake .. && make
# Or with Meson:
meson setup builddir && meson compile -C builddir

Daily commands: This is a library, not an application. To verify it works: make test runs the test suite. To see a working server: cd docker && docker-compose up starts example servers. For manual testing: compile one of the examples in benchmark/cpp-httplib/main.cpp or write a simple .cpp file with #include "httplib.h" and link with appropriate TLS library flags.

🗺️Map of the codebase

  • httplib.h — The single header-only entry point containing all HTTP/HTTPS server and client implementation; every contributor must understand this monolithic core
  • CMakeLists.txt — Build configuration defining how the header-only library is packaged and tested; critical for setting up development environments
  • .github/workflows/test.yaml — Primary CI pipeline that validates HTTP/HTTPS functionality across platforms; defines the contract for what must pass before merge
  • README.md — Defines library scope (HTTP/1.1 only, blocking I/O, header-only, no HTTP/2), design constraints, and common use patterns
  • docs-src/pages/en/cookbook/index.md — Central documentation hub mapping all common patterns (server, client, TLS, WebSocket, SSE); reference for API surface
  • .github/workflows/test_no_exceptions.yaml — Validates header-only compilation without exceptions; critical constraint for embedded/safety-critical use cases

🛠️How to make changes

Add a new HTTP request handler (server-side)

  1. Open httplib.h and locate the Server class (search 'class Server') (httplib.h)
  2. Use Server::Post/Get/Put/Delete to register your route handler, e.g., server.Post("/api/users", handler_function) (httplib.h)
  3. Define handler as void(const Request&, Response&) signature matching callback pattern in httplib.h (httplib.h)
  4. Reference docs-src/pages/en/cookbook/s01-handlers.md for handler patterns and request/response APIs (docs-src/pages/en/cookbook/s01-handlers.md)
  5. Add test case in .github/workflows/test.yaml CI config to validate new endpoint (.github/workflows/test.yaml)

Enable HTTPS/TLS for server or client

  1. Read docs-src/pages/en/tour/05-tls-setup.md for TLS backend selection (OpenSSL, mbedTLS) (docs-src/pages/en/tour/05-tls-setup.md)
  2. Install TLS library (OpenSSL/mbedTLS) and update CMakeLists.txt with find_package() call (CMakeLists.txt)
  3. For server: use SSLServer class instead of Server in httplib.h; pass cert/key paths (httplib.h)
  4. For client: use SSLClient class; optionally set custom CA cert with set_ca_cert_path() (httplib.h)
  5. Reference docs-src/pages/en/cookbook/t03-ssl-server.md and t02-cert-verification.md for examples (docs-src/pages/en/cookbook/t03-ssl-server.md)

Add WebSocket endpoint or upgrade handler

  1. Read README-websocket.md for WebSocket API and upgrade flow (README-websocket.md)
  2. In httplib.h, use set_post_routing_handler() or route middleware to intercept upgrade requests (httplib.h)
  3. Call Request::upgrade() to initiate WebSocket handshake; manage connection with socket send/recv (httplib.h)
  4. Reference docs-src/pages/en/cookbook/w01-websocket-echo.md for concrete example (docs-src/pages/en/cookbook/w01-websocket-echo.md)
  5. Add integration test to .github/workflows/test.yaml validating WebSocket frames (.github/workflows/test.yaml)

Implement Server-Sent Events (SSE) stream response

  1. Read README-sse.md for SSE event format and streaming patterns (README-sse.md)
  2. In handler, set Content-Type: text/event-stream response header in httplib.h Response object (httplib.h)
  3. Use Response::set_content() or chunked write to stream events in 'data: ...\n\n' format (httplib.h)
  4. Optionally set event IDs and reconnect-time with id: and retry: fields; reference docs-src/pages/en/cookbook/e02-sse-event-names.md (docs-src/pages/en/cookbook/e02-sse-event-names.md)

🔧Why these technologies

  • C++11 header-only design — Zero build/linking overhead; drop-in usage via single #include; enables vendoring and embedding in diverse projects
  • Blocking socket I/O (not async/non-blocking) — Simplicity and clarity for typical use cases; avoids complexity of event loops; README explicitly acknowledges this limitation
  • Optional TLS backends (OpenSSL, mbedTLS, native Win32) — Maximizes platform support and licensing flexibility; developers choose backend per project requirements
  • Optional compression (Brotli, gzip, deflate) — Reduces bandwidth for large payloads; optional to keep core lightweight; integrated via Content-Encoding negotiation
  • WebSocket and SSE built-in — Supports modern bidirectional and streaming patterns without external libraries; HTTP/1.1 upgrade protocol native support

⚖️Trade-offs already made

  • Single-file header-only vs. traditional library split

    • Why: Eliminates build/linking complexity and version mismatches
    • Consequence: Compile times may increase; code organization less granular; harder to patch in production without recompilation
  • Blocking socket I/O vs. async/non-blocking

    • Why: Dramatically simpler API and mental model; avoids callback hell and event loop complexity
    • Consequence: Cannot scale to thousands of concurrent connections; each connection uses one thread; unsuitable for high-conc

🪤Traps & gotchas

Blocking I/O only—no async/await; if you need thousands of concurrent connections, use threading or a different library. 32-bit support is explicitly unsupported; compilation may work but is not tested or secured. Multiple TLS backends are mutually exclusive at compile time; you must choose one via #define (not runtime-switchable). Exception handling can be disabled at compile time (test_no_exceptions.yaml workflow); code must handle errors differently in that mode. Proxy support requires manual setup via set_connection_adapter(); it's not automatic.

🏗️Architecture

💡Concepts to learn

  • Blocking Socket I/O — cpp-httplib's core design choice—each request blocks a thread; understanding this constraint helps you decide whether to use thread pools, select async alternatives, or accept single-threaded bottlenecks
  • Server-Sent Events (SSE) — One of cpp-httplib's advertised features (README-sse.md); essential for unidirectional real-time push from server to client without WebSocket complexity
  • Chunked Transfer Encoding — Used for streaming large responses without knowing Content-Length upfront; cookbook c09-chunked-upload.md and README-stream.md show cpp-httplib's streaming API relies on this HTTP/1.1 feature
  • TLS Backend Abstraction — cpp-httplib abstracts OpenSSL, Mbed TLS, and wolfSSL behind preprocessor directives—learning this pattern is valuable for writing portable crypto code without hard dependencies
  • Keep-Alive (HTTP Persistent Connections) — Cookbook c14-keep-alive.md demonstrates cpp-httplib's connection pooling and reuse; critical for performance in scenarios with many sequential requests
  • WebSocket Protocol Upgrade — cpp-httplib supports WebSocket (README-websocket.md) via HTTP 101 Upgrade mechanism; understanding the upgrade handshake helps you implement real-time two-way communication correctly
  • Content Negotiation & Compression — Cookbook c15-compression.md shows brotli/gzip support; understanding Accept-Encoding and Content-Encoding headers is essential for optimizing bandwidth
  • nlohmann/json — Companion library frequently paired with cpp-httplib for parsing/generating JSON in HTTP request/response bodies (see cookbook c02-json.md)
  • zaphoyd/websocketpp — Alternative WebSocket implementation; cpp-httplib's WebSocket support (README-websocket.md) overlaps but websocketpp is more feature-complete for WebSocket-only applications
  • Corvusoft/restbed — Similar header-only HTTP server library for C++, but uses async networking; direct competitor in the header-only C++ HTTP server space
  • CrowCpp/Crow — Lightweight C++ web framework that cpp-httplib benchmarks itself against (benchmark/crow/); represents the mid-weight alternative with routing and middleware
  • openssl/openssl — One of three supported TLS backends; understanding OpenSSL 3.x API is required if using CPPHTTPLIB_OPENSSL_SUPPORT

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add missing 32-bit platform documentation and validation tooling

The README explicitly warns that 32-bit platforms are NOT supported and may have security issues, but there's no specific documentation about this limitation, no CI workflow to detect 32-bit incompatibilities, and no validation guide for users. Adding a dedicated doc and CI check would help users avoid silent failures and security risks.

  • [ ] Create docs-src/pages/en/cookbook/c20-platform-support.md documenting 32-bit limitations, known issues (integer truncation, pointer sizes), and supported architectures
  • [ ] Add a new GitHub Actions workflow .github/workflows/test-32bit-validation.yml that explicitly documents why 32-bit testing exists and what to watch for
  • [ ] Add a CMake check in CMakeLists.txt that warns users when configuring for 32-bit targets with a link to the platform support docs

Add comprehensive WebSocket integration tests

README-websocket.md exists but there's no visible dedicated test suite file for WebSocket functionality (only generic test.yaml workflow). WebSocket is a critical feature that needs specific test coverage for edge cases like connection upgrades, frame parsing, and client/server disconnections.

  • [ ] Create test/websocket_test.cpp with dedicated tests for WebSocket handshake, frame parsing, ping/pong, and connection lifecycle
  • [ ] Add .github/workflows/test-websocket.yaml CI workflow to run WebSocket tests separately, validating both client and server implementations
  • [ ] Document WebSocket test coverage in docs-src/pages/en/cookbook/ws01-testing.md with examples of how to test WebSocket applications

Add OpenSSL/TLS configuration documentation and validation tests

The library supports HTTPS but there's no specific cookbook entry for common TLS/SSL scenarios (certificate validation, custom CA bundles, TLS version pinning, cipher selection). The test.yaml workflow exists but doesn't visibly validate different TLS configurations.

  • [ ] Create docs-src/pages/en/cookbook/c20-ssl-configuration.md documenting certificate validation, custom CA setup, disabling verification, TLS version selection, and cipher configuration with code examples
  • [ ] Add test/ssl_config_test.cpp testing certificate validation, custom CA chains, and TLS version requirements
  • [ ] Add a .github/workflows/test-ssl-config.yaml workflow validating HTTPS with different certificate scenarios (self-signed, CA-signed, expired certs)

🌿Good first issues

  • Add HTTP/2 upgrade detection and graceful fallback documentation: Currently httplib.h has no handling for clients requesting HTTP/2 or servers advertising upgrade availability—a cookbook page (docs-src/pages/en/cookbook/c17-http2-detection.md) explaining why HTTP/2 is not supported and how users should choose alternatives would help new users avoid frustration.
  • Extend the benchmark suite (benchmark/) with compression and streaming comparisons: The benchmark currently compares basic throughput against Crow; adding brotli/gzip compression and streaming response benchmarks would showcase cpp-httplib's Stream API advantages and guide performance-conscious users.
  • Add examples for graceful shutdown and signal handling: Neither docker/main.cc nor benchmark examples show how to cleanly stop the server on SIGINT/SIGTERM; a cookbook entry (c18-graceful-shutdown.md) with a complete runnable example would be valuable for production use cases.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 600d220 — Release v0.43.4 (yhirose)
  • 87d62db — Reject malformed chunk-size in chunked decoder (yhirose)
  • a1fdc07 — Guard nullptr res in KeepAliveTest proxy template (#2443) (yhirose)
  • eb49a30 — Use vswhere to locate VS install in 32-bit Windows CI (#2442) (yhirose)
  • a9bfe59 — Fix #2441 (yhirose)
  • ec5ce17 — Release v0.43.3 (yhirose)
  • f6524c0 — Drop Str2tagTest unit test that broke split / no-exceptions builds (yhirose)
  • 35c4026 — Make fuzz_test robust to missing corpus files (yhirose)
  • 40e1846 — Document str2tag_core's compile-time-only role (yhirose)
  • 92aecf8 — Fix OSS-Fuzz #508087118: avoid stack overflow in str2tag (yhirose)

🔒Security observations

  • High · Docker Container Runs as Root with Exposed Port — Dockerfile, docker-compose.yml. The Dockerfile uses 'scratch' base image without specifying a non-root user, which means the HTTP server runs as root (UID 0). Combined with the exposed port 80 in docker-compose.yml and ENTRYPOINT configuration, this creates a privilege escalation risk if the HTTP server is compromised. Fix: Create a non-root user in the builder stage and switch to it before running the server. For example: 'RUN useradd -m -u 1000 appuser' and 'USER appuser'. Consider running on a high-numbered port (>1024) and using a reverse proxy with appropriate privilege separation.
  • High · Static Binary Without ASLR/PIE Protections — Dockerfile (RUN g++ command). The Dockerfile compiles with '-static' flag and '-O2' optimization without explicit security flags like '-fPIE', '-fstack-protector-strong', or '-D_FORTIFY_SOURCE=2'. Static compilation combined with lack of position-independent code reduces the effectiveness of ASLR and other modern mitigations against code injection attacks. Fix: Add security compilation flags: '-fPIE -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wl,-z,relro -Wl,-z,now'. Consider using '-fsanitize=address' or '-fsanitize=bounds' during development for buffer overflow detection.
  • High · Missing Input Validation and Buffer Overflow Risks — httplib.h (not fully provided). As a header-only HTTP library, cpp-httplib is responsible for parsing HTTP requests. The README warning about 32-bit platforms suggests potential integer truncation vulnerabilities. Without seeing the full httplib.h code, common HTTP parsing libraries are vulnerable to buffer overflows, integer overflows, and malformed request handling. Fix: Implement comprehensive input validation for all HTTP headers, request bodies, and URL parameters. Add size limits for requests. Use safe string handling functions. Conduct a formal security audit of the HTTP parsing code, particularly for buffer management.
  • Medium · World-Readable Static Assets with No Cache Control — docker-compose.yml, docker/html directory. The docker-compose.yml mounts './docker/html:/html' which serves static files. The Dockerfile exposes port 80 without any security headers configuration visible. No cache control, CSP, or X-Frame-Options headers are mentioned, which could allow MIME type sniffing or caching of sensitive content. Fix: Configure appropriate HTTP security headers in the server code or reverse proxy: 'Cache-Control: no-store', 'X-Content-Type-Options: nosniff', 'X-Frame-Options: DENY', 'Content-Security-Policy'. Validate file paths to prevent directory traversal attacks.
  • Medium · No TLS/HTTPS Configured in Docker Deployment — Dockerfile (EXPOSE 80), docker-compose.yml. The Dockerfile and docker-compose.yml only expose HTTP (port 80), with no HTTPS/TLS configuration visible. This means all traffic between clients and the server is unencrypted and vulnerable to MITM attacks. Fix: Enable HTTPS with valid certificates. Use TLS 1.2+ with strong ciphers. In docker-compose, expose port 443 and configure SSL/TLS in the application or via a reverse proxy (nginx, caddy). For production, use certificate management solutions like Let's Encrypt.
  • Medium · Compilation with Optimizations May Obscure Security Issues — Dockerfile (RUN g++ command). The Dockerfile uses '-O2' optimization flag during compilation of a security-critical HTTP library. While necessary for performance, aggressive optimizations can obscure buffer overflow detection and make debugging security issues more difficult. Fix: For production builds, consider using '-O2' with security flags. For development and security testing, use '-O0 -g' with sanitizers (-fsanitize=address, -fsanitize=undefined). Maintain separate debug symbols for crash analysis.
  • Medium · No Security Headers or Request Size Limits Visible — docker/. The provided configuration files do not show any explicit request size limits, rate limiting, or timeout configurations. This could allow DoS attacks via large payloads or slow client attacks. Fix: undefined

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · yhirose/cpp-httplib — RepoPilot