{"id":15394947,"url":"https://github.com/kassane/picohttpasio","last_synced_at":"2026-05-10T16:35:18.630Z","repository":{"id":191032018,"uuid":"683744417","full_name":"kassane/picohttpasio","owner":"kassane","description":"This is a simple HTTP server implemented in C++ using the picohttpparser library for HTTP parsing and the Asio library for network communication.","archived":false,"fork":false,"pushed_at":"2026-03-11T22:46:24.000Z","size":69,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-12T03:42:28.259Z","etag":null,"topics":["asio","cplusplus","cpp","http-client","http-server","web"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kassane.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-08-27T15:11:29.000Z","updated_at":"2025-07-15T10:37:51.000Z","dependencies_parsed_at":"2023-08-27T20:05:16.694Z","dependency_job_id":null,"html_url":"https://github.com/kassane/picohttpasio","commit_stats":null,"previous_names":["kassane/picohttpasio"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/kassane/picohttpasio","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kassane%2Fpicohttpasio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kassane%2Fpicohttpasio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kassane%2Fpicohttpasio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kassane%2Fpicohttpasio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kassane","download_url":"https://codeload.github.com/kassane/picohttpasio/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kassane%2Fpicohttpasio/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32863976,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-10T13:40:02.631Z","status":"ssl_error","status_checked_at":"2026-05-10T13:40:02.145Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asio","cplusplus","cpp","http-client","http-server","web"],"created_at":"2024-10-01T15:25:00.545Z","updated_at":"2026-05-10T16:35:18.620Z","avatar_url":"https://github.com/kassane.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# picohttpasio\n\n[![CI](https://github.com/kassane/picohttpasio/actions/workflows/ci.yml/badge.svg)](https://github.com/kassane/picohttpasio/actions/workflows/ci.yml)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/kassane/picohttpasio)\n\nA lightweight, user-friendly C++23 HTTP/1.1 built on\n[standalone ASIO](https://github.com/chriskohlhoff/asio) and\n[picohttpparser](https://github.com/h2o/picohttpparser).\n\nAn accessible alternative to `boost::beast` — combining beast's async ASIO foundation\nwith an Express-style developer experience.\n\n## Features\n\n- **Express-like router** — path parameters (`/users/:id`), wildcards (`/static/*`),\n  HTTP method dispatch (GET, POST, PUT, DELETE, PATCH, …)\n- **Middleware chain** — global or prefix-scoped; short-circuit or pass-through\n- **Fluent Response builder** — status, headers, body, JSON, HTML, redirect\n- **Keep-alive / HTTP pipelining** — reuse connections for multiple requests\n- **WebSocket** — full client and server support; RFC-compliant handshake (SHA-1)\n  with masked client frames and complete frame codec\n- **HTTPS/TLS** — optional; wraps ASIO SSL with OpenSSL for both `HTTPServer` and\n  `CoroServer` (enabled by `-DPICO_ENABLE_TLS=ON`)\n- **Crypto primitives** — SHA-256/512, BLAKE2b, Ed25519 signatures, AES-256-GCM AEAD,\n  X25519 key exchange; all via OpenSSL EVP (no extra dependency beyond TLS)\n- **Static file serving** — 30+ MIME types, directory-traversal protection,\n  ETag/Last-Modified caching (HTTP 304), Range requests (HTTP 206/416),\n  optional gzip compression, optional directory listing, configurable extra MIME types\n- **Async HTTP client** — plain (`HTTPClient`) and TLS (`HTTPSClient`), `RequestBuilder`,\n  keep-alive connection reuse\n- **Async WebSocket client** — `WebSocketClient` with proper RFC 6455 masked frames,\n  handshake validation, ping/pong handling\n- **Cross-platform** — Linux, macOS, Windows (MSVC 19.35+ / GCC 13+ / Clang 16+)\n- **Catch2 v3 test suite** — unit tests + localhost integration tests\n\n## Prerequisites\n\n| | Required | Optional |\n|---|---|---|\n| Compiler | C++23 (GCC 13+, Clang 16+, MSVC 19.35+) | |\n| Build | CMake 3.14+ | |\n| TLS / Crypto | — | OpenSSL 1.1.1+ (`libssl-dev` on Ubuntu, `brew install openssl` on macOS) |\n| Compression | — | zlib (`zlib1g-dev` on Ubuntu, bundled on macOS/Windows) |\n| Network | First build fetches ASIO + Catch2 via FetchContent | |\n\n## Using picohttpasio in your project (FetchContent)\n\nAdd the following to your `CMakeLists.txt`:\n\n```cmake\ninclude(FetchContent)\n\nFetchContent_Declare(picohttpasio\n    GIT_REPOSITORY https://github.com/kassane/picohttpasio.git\n    GIT_TAG        main\n    GIT_SHALLOW    TRUE)\nFetchContent_MakeAvailable(picohttpasio)\n\nadd_executable(my_app main.cpp)\ntarget_link_libraries(my_app PRIVATE picohttpasio)\n```\n\nEnable TLS/crypto support (requires OpenSSL):\n\n```cmake\nset(PICO_ENABLE_TLS ON CACHE BOOL \"\" FORCE)\nFetchContent_Declare(picohttpasio ...)\nFetchContent_MakeAvailable(picohttpasio)\n```\n\nEnable gzip compression for static files (requires zlib):\n\n```cmake\nset(PICO_ENABLE_COMPRESSION ON CACHE BOOL \"\" FORCE)\n```\n\n## Building (tests \u0026 examples)\n\n```sh\ngit clone https://github.com/kassane/picohttpasio\ncd picohttpasio\n\n# Default (TLS on — requires OpenSSL)\ncmake -B build -DCMAKE_BUILD_TYPE=Debug\ncmake --build build --parallel\nctest --test-dir build --output-on-failure\n\n# Without TLS/crypto\ncmake -B build -DPICO_ENABLE_TLS=OFF\ncmake --build build --parallel\n\n# With gzip compression (requires zlib)\ncmake -B build -DPICO_ENABLE_COMPRESSION=ON\ncmake --build build --parallel\n```\n\n### macOS\n\n```sh\nbrew install openssl\ncmake -B build -DOPENSSL_ROOT_DIR=$(brew --prefix openssl)\ncmake --build build --parallel\n```\n\n### Windows (MSVC)\n\n```bat\nchoco install openssl\ncmake -B build -DOPENSSL_ROOT_DIR=\"C:/Program Files/OpenSSL-Win64\"\ncmake --build build --parallel\n```\n\n### Release build\n\n```sh\ncmake -B build -DCMAKE_BUILD_TYPE=Release\ncmake --build build --parallel\n```\n\n## Quick Start — Server\n\n```cpp\n#include \u003cserver.hpp\u003e\n\nint main() {\n    asio::io_context io;\n    pico::HTTPServer server(io, 8080, \"./www\");  // static files from ./www\n\n    // Middleware\n    server.router().use(pico::logging_middleware());\n    server.router().use(pico::cors_middleware());\n\n    // Routes\n    server.router()\n        .get(\"/hello\", [](pico::Request\u0026, pico::Response\u0026 res) {\n            res = pico::Response::ok(\"Hello, World!\\n\");\n        })\n        .get(\"/users/:id\", [](pico::Request\u0026 req, pico::Response\u0026 res) {\n            res = pico::Response::make()\n                .json(R\"({\"id\":\")\" + std::string(req.param(\"id\")) + R\"(\"})\");\n        })\n        .post(\"/echo\", [](pico::Request\u0026 req, pico::Response\u0026 res) {\n            res = pico::Response::ok(req.body);\n        });\n\n    // WebSocket upgrade\n    server.on_websocket([](std::shared_ptr\u003cpico::ws::WebSocketConnection\u003e conn) {\n        conn-\u003eon_message([conn](pico::ws::Frame f) {\n            conn-\u003esend(f.payload);  // echo\n        });\n    });\n\n    io.run();\n}\n```\n\n## Quick Start — HTTPS Server\n\n### Callback-based (`HTTPServer` + `use_tls`)\n\n```cpp\n#include \u003cserver.hpp\u003e   // requires PICO_ENABLE_TLS\n\nint main() {\n    asio::io_context io;\n    asio::ssl::context ssl(asio::ssl::context::tls_server);\n    ssl.use_certificate_chain_file(\"cert.pem\");\n    ssl.use_private_key_file(\"key.pem\", asio::ssl::context::pem);\n\n    pico::HTTPServer server(io, 8443, \"./www\");\n    server.use_tls(std::move(ssl));   // enable TLS on this server\n\n    server.router().get(\"/\", [](pico::Request\u0026, pico::Response\u0026 res) {\n        res = pico::Response::ok(\"Hello over TLS!\\n\");\n    });\n\n    io.run();\n}\n```\n\n### Coroutine-based (`CoroServer`)\n\n```cpp\n#include \u003ccoro_server.hpp\u003e   // requires PICO_ENABLE_TLS\n\nint main() {\n    asio::io_context io;\n    asio::ssl::context ssl(asio::ssl::context::tls_server);\n    ssl.use_certificate_chain_file(\"cert.pem\");\n    ssl.use_private_key_file(\"key.pem\", asio::ssl::context::pem);\n\n    pico::CoroServer server(io, 8443, \"./www\");\n    server.use_tls(std::move(ssl));\n\n    server.router().get(\"/\", [](pico::Request\u0026, pico::Response\u0026 res) {\n        res = pico::Response::ok(\"Hello over TLS!\\n\");\n    });\n\n    io.run();\n}\n```\n\n## Quick Start — Static File Configuration\n\nBoth `HTTPServer` and `CoroServer` expose `static_config()` to tune static file serving:\n\n```cpp\n#include \u003cserver.hpp\u003e\n\nint main() {\n    asio::io_context io;\n    pico::HTTPServer server(io, 8080, \"./www\");\n\n    auto\u0026 cfg = server.static_config();\n    cfg.caching          = true;    // ETag + Last-Modified / 304 Not Modified\n    cfg.range_requests   = true;    // HTTP 206 Partial Content / 416 Range Not Satisfiable\n    cfg.directory_listing = true;   // auto-generated HTML index for directories\n#ifdef PICO_ENABLE_COMPRESSION\n    cfg.compression      = true;    // gzip (requires -DPICO_ENABLE_COMPRESSION=ON)\n#endif\n    // Register extra MIME types (merged with the 30+ built-in ones)\n    cfg.extra_mime_types[\".ts\"]   = \"application/typescript\";\n    cfg.extra_mime_types[\".wasm\"] = \"application/wasm\";\n\n    io.run();\n}\n```\n\n## Quick Start — HTTPS Client\n\n```cpp\n#include \u003cclient.hpp\u003e\n#include \u003cssl_context.hpp\u003e   // requires PICO_ENABLE_TLS\n\nint main() {\n    asio::io_context io;\n\n    // make_client_context(true)  → verify peer certificate\n    // make_client_context(false) → skip verification (self-signed / dev)\n    auto ctx = pico::ssl::make_client_context(true);\n\n    pico::HTTPSClient client(io, \"example.com\", 443, ctx);\n    client.get(\"/api/data\", [](std::optional\u003cHTTPResponse\u003e resp) {\n        if (!resp) { std::cerr \u003c\u003c \"request failed\\n\"; return; }\n        std::cout \u003c\u003c resp-\u003estatusCode() \u003c\u003c \" \" \u003c\u003c resp-\u003estatusMessage() \u003c\u003c \"\\n\";\n        for (const auto\u0026 [k, v] : resp-\u003eheaders())\n            std::cout \u003c\u003c \"  \" \u003c\u003c k \u003c\u003c \": \" \u003c\u003c v \u003c\u003c \"\\n\";\n    });\n\n    io.run();\n}\n```\n\n## Quick Start — WebSocket Client\n\n```cpp\n#include \u003cwebsocket.hpp\u003e\n#include \u003casio.hpp\u003e\n// See examples/websocket_client.cpp for the full WebSocketClient class\n\nint main() {\n    asio::io_context io;\n    auto client = std::make_shared\u003cWebSocketClient\u003e(io, \"localhost\", 8080);\n\n    client-\u003eon_open([\u0026client]() {\n        client-\u003esend(\"Hello, server!\");\n    });\n\n    client-\u003eon_message([](pico::ws::Frame frame) {\n        std::cout \u003c\u003c \"Echo: \" \u003c\u003c frame.payload \u003c\u003c \"\\n\";\n    });\n\n    client-\u003eon_close([]() { std::cout \u003c\u003c \"closed\\n\"; });\n\n    client-\u003econnect(\"/ws\");\n    io.run();\n}\n```\n\nKey points:\n- `WebSocketClient` handles the HTTP upgrade handshake, validates\n  `Sec-WebSocket-Accept` (RFC 6455 §4.1)\n- All frames sent by the client are properly **masked** (RFC 6455 §5.3 requirement)\n- Supports ping/pong, opcode dispatch, and a graceful close handshake\n- Works with the bundled `websocket_echo` server and any RFC-compliant server\n\n## Quick Start — Crypto\n\nRequires `PICO_ENABLE_TLS=ON`. All primitives are backed by OpenSSL EVP.\n\n```cpp\n#include \u003ccrypto.hpp\u003e\n\n// Hashing\nauto h256  = pico::crypto::sha256(\"hello\");           // SHA-256 → 32 bytes\nauto h512  = pico::crypto::sha512(\"hello\");           // SHA-512 → 64 bytes\nauto hb2b  = pico::crypto::blake2b(\"hello\");          // BLAKE2b-512 → 64 bytes\nauto hb2bk = pico::crypto::blake2b(\"hello\", \"key\");  // HMAC-SHA-512 keyed variant\n\nstd::string hex = pico::crypto::to_hex(h256);         // → \"2cf24dba...\"\n\n// Secure random bytes\nauto bytes  = pico::crypto::random_bytes(32);\nauto secret = pico::crypto::random_string(16);\n\n// AES-256-GCM symmetric AEAD\nauto key = pico::crypto::secretbox::generate_key();   // 32-byte key\nauto ct  = pico::crypto::secretbox::encrypt(\"hello\", key);  // IV+tag+ciphertext\nauto pt  = pico::crypto::secretbox::decrypt(ct, key); // → optional\u003cstring\u003e\n\n// X25519 + AES-256-GCM public-key AEAD\nauto alice = pico::crypto::box::generate_keypair();\nauto bob   = pico::crypto::box::generate_keypair();\nauto enc   = pico::crypto::box::encrypt(\"secret\", bob.pk, alice.sk);\nauto dec   = pico::crypto::box::decrypt(enc, alice.pk, bob.sk);\n\n// Ed25519 digital signatures\nauto kp  = pico::crypto::sign::generate_keypair();\nauto sig = pico::crypto::sign::sign_detached(\"message\", kp.sk);\nbool ok  = pico::crypto::sign::verify_detached(\"message\", sig, kp.pk);\n```\n\n## Quick Start — Client\n\n```cpp\n#include \u003cclient.hpp\u003e\n\nint main() {\n    asio::io_context io;\n    pico::HTTPClient client(io, \"httpbin.org\", 80);\n\n    auto req = pico::RequestBuilder{}\n        .get(\"/get\")\n        .host(\"httpbin.org\")\n        .keep_alive(false)\n        .build();\n\n    client.request(req, [](std::optional\u003cHTTPResponse\u003e resp) {\n        if (resp) {\n            std::cout \u003c\u003c resp-\u003estatusCode() \u003c\u003c \" \" \u003c\u003c resp-\u003estatusMessage() \u003c\u003c \"\\n\";\n        }\n    });\n\n    io.run();\n}\n```\n\n## Benchmark\n\n`examples/techempower_bench.cpp` implements\n[TechEmpower Web Framework Benchmark](https://www.techempower.com/benchmarks/#section=code)\ncategories:\n\n| Category | Endpoint | Description |\n|---|---|---|\n| 1 — JSON | `GET /json` | `{\"message\":\"Hello, World!\"}` |\n| 6 — Plaintext | `GET /plaintext` | `Hello, World!` |\n\n```sh\ncmake -B build -DCMAKE_BUILD_TYPE=Release \u0026\u0026 cmake --build build --parallel\n./build/examples/techempower_bench \u0026\nwrk -t4 -c128 -d10s --latency http://localhost:8080/plaintext\nwrk -t4 -c128 -d10s --latency http://localhost:8080/json\n```\n\n## API Reference\n\n### `pico::Response` builder\n\n```cpp\npico::Response::ok(\"body\")\npico::Response::not_found()\npico::Response::bad_request(\"msg\")\npico::Response::no_content()\npico::Response::redirect(\"/new-url\")\npico::Response::make(pico::StatusCode::Created)\n    .header(\"X-Custom\", \"value\")\n    .json(R\"({\"ok\":true})\")\n    .serialize()  // → HTTP/1.1 wire string\n```\n\n### `pico::Router`\n\n```cpp\nrouter.get   (\"/path\",         handler)\nrouter.post  (\"/path\",         handler)\nrouter.put   (\"/path/:id\",     handler)\nrouter.del   (\"/path/:id\",     handler)   // HTTP DELETE (Method::DEL)\nrouter.patch (\"/path/:id\",     handler)\nrouter.any   (\"/path\",         handler)   // all methods\nrouter.use   (middleware)                  // global\nrouter.use   (\"/prefix\", middleware)       // prefix-scoped\n```\n\n### `pico::Request` (inside handlers)\n\n```cpp\nreq.method          // pico::Method::GET / POST / DEL / …\nreq.path            // \"/users/42\"\nreq.body            // request body string\nreq.header(\"Host\")  // header value (string_view)\nreq.param(\"id\")     // path parameter (string_view)\nreq.query_param(\"q\")// query parameter (string_view)\nreq.keepAlive()     // bool\n```\n\n### `pico::RequestBuilder`\n\n```cpp\npico::RequestBuilder{}\n    .get(\"/path\")\n    .host(\"example.com\")\n    .header(\"Authorization\", \"Bearer token\")\n    .keep_alive(true)\n    .build()  // → wire-format string\n```\n\n### `pico::StaticConfig`\n\nControls static file serving behaviour for `HTTPServer` and `CoroServer`:\n\n```cpp\nstruct StaticConfig {\n    bool caching          = true;   // ETag + Last-Modified / 304 Not Modified\n    bool range_requests   = true;   // HTTP 206 Partial Content, 416 Range Not Satisfiable\n    bool directory_listing = false; // auto HTML index for directories (off by default)\n    bool compression      = false;  // gzip (requires PICO_ENABLE_COMPRESSION)\n    // Extra MIME types merged with 30+ built-ins (.html .css .js .json .png .jpg …)\n    std::unordered_map\u003cstd::string, std::string\u003e extra_mime_types;\n};\n\n// Access via:\nserver.static_config().compression = true;\nserver.static_config().extra_mime_types[\".ts\"] = \"application/typescript\";\n```\n\n### `HTTPServer` / `CoroServer`\n\n```cpp\n// Shared API\nserver.router()                      // → Router\u0026 for registering routes/middleware\nserver.on_websocket(handler)         // register WebSocket upgrade handler\nserver.static_config()               // → StaticConfig\u0026 for static file options\n\n// TLS (requires PICO_ENABLE_TLS)\nserver.use_tls(asio::ssl::context)   // enable TLS; call before io.run()\n```\n\n### `pico::HTTPClient` / `pico::HTTPSClient`\n\n```cpp\n// Plain HTTP\npico::HTTPClient client(io, \"example.com\", 80);\nclient.get(\"/path\", callback);\nclient.request(wire_string, callback);\n\n// HTTPS (requires PICO_ENABLE_TLS)\nauto ctx = pico::ssl::make_client_context(/*verify_peer=*/true);\npico::HTTPSClient client(io, \"example.com\", 443, ctx);\nclient.get(\"/path\", callback);\nclient.request(wire_string, callback);\n\n// Callback signature:\n//   void(std::optional\u003cHTTPResponse\u003e)\n//   HTTPResponse is in the global namespace (picohttpparser wrapper)\n```\n\n### WebSocket (`pico::ws`)\n\n```cpp\n// Server-side helpers\npico::ws::ws_accept_key(client_key)   // compute Sec-WebSocket-Accept\npico::ws::encode(frame)               // server→client frame (unmasked)\npico::ws::decode(buffer, frame_out)   // bytes → frame (0 = incomplete)\n\n// WebSocketConnection (server-side, created automatically on upgrade)\nconn-\u003esend(\"hello\")\nconn-\u003esend(data, pico::ws::Opcode::Binary)\nconn-\u003eclose()\nconn-\u003eon_message([](pico::ws::Frame f) { … })\nconn-\u003eon_close([]() { … })\n\n// WebSocketClient (see examples/websocket_client.cpp)\n// Client frames are RFC 6455 §5.3 masked automatically.\nclient-\u003eon_open([]() { … })\nclient-\u003eon_message([](pico::ws::Frame f) { … })\nclient-\u003eon_close([]() { … })\nclient-\u003econnect(\"/ws\")\nclient-\u003esend(\"text\")\nclient-\u003eclose()\n```\n\n### Built-in middleware\n\n```cpp\npico::logging_middleware()         // prints METHOD path -\u003e STATUS to stderr\npico::cors_middleware(\"*\")         // CORS headers (permissive default)\n```\n\n## Project Layout\n\n```\ninclude/\n  http_types.hpp        Method enum (DEL = HTTP DELETE), StatusCode enum\n  picohttpwrapper.hpp   HTTPRequest + HTTPResponse parsers (picohttpparser wrapper)\n  request.hpp           Request value type + parse_request() factory\n  response.hpp          Response fluent builder + serializer\n  router.hpp            Router, path matching, middleware chain\n  websocket.hpp         WS handshake (SHA-1), frame codec, WebSocketConnection\n  server.hpp            HTTPServer (keep-alive, WS dispatch, TLS, static files)\n  coro_server.hpp       Coroutine-based HTTPS/HTTP server (TLS optional)\n  client.hpp            HTTPClient + HTTPSClient + RequestBuilder\n  static_files.hpp      serve_static(), StaticConfig, ETag/Range/gzip helpers\n  crypto.hpp            Crypto primitives via OpenSSL EVP (requires PICO_ENABLE_TLS)\ntests/\n  test_types.cpp        Method/StatusCode unit tests\n  test_parser.cpp       Request/response parser tests\n  test_response.cpp     Response builder + Request factory tests\n  test_router.cpp       Routing, path params, middleware tests\n  test_websocket.cpp    SHA-1 key, frame encode/decode tests\n  test_integration.cpp  Real localhost server+client round-trip tests\n  test_crypto.cpp       Crypto primitives tests (requires PICO_ENABLE_TLS)\n  test_coro.cpp         TLS coroutine server tests (requires PICO_ENABLE_TLS)\n  test_static_files.cpp Static file serving: ETag, Range, 304, 206, MIME, gzip\nexamples/\n  simple_server.cpp     Basic server with routes and middleware\n  rest_api.cpp          CRUD REST API demo\n  websocket_echo.cpp    WebSocket echo server\n  websocket_client.cpp  WebSocket client (masked frames, handshake validation)\n  coro_server.cpp       Coroutine HTTPS server demo\n  https_server.cpp      Full HTTPS + WebSocket + crypto demo\n  https_client.cpp      Async HTTPS client demo (requires PICO_ENABLE_TLS)\n  techempower_bench.cpp TechEmpower benchmark server (cat. 1 JSON + cat. 6 Plaintext)\n.github/workflows/\n  ci.yml                Build + test matrix: Linux / macOS / Windows × TLS × compression\n  bench.yml             TechEmpower-style wrk benchmark (Linux, informational)\n```\n\n## Comparison with boost::beast\n\n| Feature                        | boost::beast     | picohttpasio          |\n|-------------------------------|------------------|-----------------------|\n| Routing                       | Manual           | Built-in router       |\n| Middleware                    | None             | Chain system          |\n| Response builder              | Manual           | Fluent API            |\n| WebSocket server              | Yes (low-level)  | Yes (high-level)      |\n| WebSocket client              | Yes (low-level)  | Yes (high-level)      |\n| HTTPS/TLS server              | Yes              | Yes (OpenSSL)         |\n| HTTPS/TLS client              | Yes              | Yes (OpenSSL)         |\n| Crypto primitives             | No               | Yes (OpenSSL EVP)     |\n| Static files — MIME types     | Manual           | 30+ built-in          |\n| Static files — ETag/304       | Manual           | Automatic             |\n| Static files — Range/206      | Manual           | Automatic             |\n| Static files — gzip           | Manual           | Optional (zlib)       |\n| Keep-alive                    | Manual           | Automatic             |\n| Windows support               | Yes              | Yes                   |\n| Boost dependency              | Required         | None                  |\n| C++ standard                  | C++11+           | C++23                 |\n| Learning curve                | Steep            | Express-like          |\n\n## License\n\nMIT License. See [LICENSE](LICENSE) for details.\n\n### Acknowledgments\n\n- [picohttpparser](https://github.com/h2o/picohttpparser): Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase, Shigeo Mitsunari (MIT)\n- [ASIO](https://github.com/chriskohlhoff/asio): Christopher M. Kohlhoff (BSL-1.0)\n- [Catch2](https://github.com/catchorg/Catch2): Martin Hořeňovský et al. (BSL-1.0)\n- [OpenSSL](https://www.openssl.org): OpenSSL Project (Apache-2.0)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkassane%2Fpicohttpasio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkassane%2Fpicohttpasio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkassane%2Fpicohttpasio/lists"}