{"id":29188815,"url":"https://github.com/paul-caron/curling","last_synced_at":"2026-04-30T03:33:06.487Z","repository":{"id":300877726,"uuid":"1007456571","full_name":"paul-caron/curling","owner":"paul-caron","description":"A C++ libcurl wrapper","archived":false,"fork":false,"pushed_at":"2025-07-01T18:18:00.000Z","size":2259,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-01T18:23:15.739Z","etag":null,"topics":["cpp17","curl","easy","header-only","http-client","libcurl","mit-license","modern-cpp","rest-api","shared-library"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/paul-caron.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-24T03:10:29.000Z","updated_at":"2025-07-01T18:18:04.000Z","dependencies_parsed_at":"2025-06-24T04:24:21.205Z","dependency_job_id":"9056d042-7d2d-4ad0-8cd9-b8cfb0ad5faf","html_url":"https://github.com/paul-caron/curling","commit_stats":null,"previous_names":["paul-caron/curling"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/paul-caron/curling","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paul-caron%2Fcurling","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paul-caron%2Fcurling/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paul-caron%2Fcurling/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paul-caron%2Fcurling/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paul-caron","download_url":"https://codeload.github.com/paul-caron/curling/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paul-caron%2Fcurling/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32453748,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T22:27:22.272Z","status":"online","status_checked_at":"2026-04-30T02:00:05.929Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["cpp17","curl","easy","header-only","http-client","libcurl","mit-license","modern-cpp","rest-api","shared-library"],"created_at":"2025-07-01T23:00:43.475Z","updated_at":"2026-04-30T03:33:01.480Z","avatar_url":"https://github.com/paul-caron.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"![License: MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg) \n![Tests](https://img.shields.io/badge/tests-passing-brightgreen) \n[![Build and Test](https://github.com/paul-caron/curling/actions/workflows/build-and-test.yml/badge.svg)](https://github.com/paul-caron/curling/actions/workflows/build-and-test.yml) \n![C++17](https://img.shields.io/badge/C%2B%2B-17-blue) \n![GitHub release](https://img.shields.io/github/v/release/paul-caron/curling?include_prereleases\u0026sort=semver)\n\n# 🌀 Curling\n\nCurling is a modern C++17 wrapper around libcurl, designed to simplify HTTP/HTTPS requests using a clean, fluent API.\n\nIt supports JSON payloads, file uploads, cookie management, authentication, proxy configuration, and more — all with a RAII-safe design using smart pointers.\n\n\n---\n\n\n## 📚 Table of Contents\n\n- [✨ Features](#-features)\n- [🛠 Installation](#-installation)\n- [🚀 Basic Usage](#-basic-usage)\n- [✅ Example Test Case](#-example-test-case)\n- [🧠 Internals \u0026 Design](#-internals--design)\n- [🤔 Why Curling?](#-why-curling)\n- [⚖️ Comparisons](#️-comparisons-with-other-popular-c-libcurl-wrappers)\n- [📚 Documentation](#-documentation)\n- [🧪 Testing](#-testing)\n- [🤝 Contributing](#-contributing)\n- [📄 License](#-license)\n- [👤 Maintainer](#-maintainer)\n- [📌 Notes](#-notes)\n\n\n---\n\n## ✨ Features\n\n- 🔁 **Fluent API** — chainable and expressive request building  \n- 📤 **Multipart and MIME support** — for multipart forms and file uploads  \n- 🍪 **Cookie management** — with optional persistent storage  \n- 🛡 **Proxy and authentication support** — including Basic, Bearer, and Digest  \n- 🌐 **Full HTTP verb support** — GET, POST, PUT, DELETE, PATCH, HEAD\n- 🚀 **HTTP/2 and HTTP/3 support** — via libcurl\n- ⏳ **Progress callback support** — for monitoring request progress\n- 🧩 **Header-only library** — just include and go\n- 📦 **.deb packaging** — for easy installation on Debian-based systems  \n- 🧪 **CI-tested** — with [Doctest](https://github.com/doctest/doctest) and GitHub Actions\n\n\n\n---\n\n## 🛠 Installation\n\n### 🔧 Build shared library\n\n```bash\nmake\n```\n\nTo install and package as a Debian .deb:\n\n```bash\nmake install\nmake deb\n```\n\nInstall it locally:\n\n```bash\nsudo apt install ./curling_1.0_amd64.deb\nsudo ldconfig\n```\n\n### 🪶 Header-only version\n\n```bash\nmake header-only\n```\n\nThis produces a header-only version in:\n\n`curling/header-only/`\n\n\n---\n\n## 🚀 Basic Usage\n\n```cpp\n#include \"curling.hpp\"\n#include \u003ciostream\u003e\n\nint main() {\n    curling::Request req;\n\n    auto res = req.setMethod(curling::Request::Method::GET)\n                  .setURL(\"https://example.com\")\n                  .setUserAgent(\"Lizardzilla/6.9 (Reptilian Humanoid)\")\n                  .send();\n\n    std::cout \u003c\u003c res.toString();\n    return 0;\n}\n```\n\n### 🔨 Compile\n\nWith shared library:\n```bash\ng++ main.cpp -lcurling -std=c++17\n```\nWith header-only:\n```bash\ng++ main.cpp -lcurl -std=c++17\n```\n\n---\n\n## ✅ Example Test Case\n\nTests run automatically on every push via GitHub Actions.\n\n```cpp\nTEST_CASE(\"GET request to download image\") {\n    curling::Request req;\n    req.setURL(\"https://httpbin.org/image/png\")\n       .downloadToFile(\"out.png\");\n\n    auto res = req.send();\n\n    CHECK(res.httpCode == 200);\n    CHECK(std::filesystem::exists(\"out.png\"));\n}\n```\n\nRun tests locally:\n```bash\nmake test\n```\n\n---\n\n## 🧠 Design Philosophy\n\nCurling centers around the curling::Request class, which wraps libcurl functionality in a fluent, type-safe, modern C++ API.\n\nKey principles:\n\n- ✅ RAII \u0026 smart pointers — automatic resource cleanup\n\n- ✅ Fluent chaining — readable and efficient method calls\n\n- ✅ No global state — avoids curl_global_* leaks\n\n- ✅ Safe-by-default — redirects off by default, verbose off, etc.\n\n\n\n---\n\n## 🤔 Why Curling?\n\nLibcurl is powerful, but its C API is verbose and error-prone.\n\nCurling offers:\n\n|Feature                 |libcurl    |Curling|\n|------------------------|-----------|-------|\n|Fluent C++ API          |❌         |✅     |\n|RAII memory management\t |❌         |✅     |\n|Built-in test coverage\t |❌\t     |✅     |\n|Easy file \u0026 MIME upload |Manual     |✅     |\n|Modern build integration|❌         |✅     |\n\n\n---\n\n## ⚖️ Comparisons with Other Popular C++ libcurl Wrappers\n\nCurling aims to strike a balance between modern C++ design, fine-grained control, and ease of use. Here's how it compares to other popular libcurl wrappers:\n\n| Aspect              | CPR                           | curlpp                      | Curling (this project)                     |\n|---------------------|-------------------------------|-----------------------------|--------------------------------------------|\n| API Style           | High-level, intuitive          | Classic wrapper, less modern| Modern C++17 fluent API with chaining      |\n| Abstraction Level   | Heavy abstraction, hides internals | Moderate abstraction, outdated | Balanced abstraction, exposes fine control|\n| Memory Management   | Manual (raw pointers internally) | Manual                      | RAII with smart pointers                    |\n| Feature Completeness| Common HTTP (GET/POST/JSON/auth)| Full libcurl coverage, less ergonomic | Full HTTP verbs, MIME, advanced auth       |\n| File/MIME Upload    | Partial support, verbose       | Supported, clunky           | Fully integrated, fluent MIME support      |\n| Authentication      | Basic, Bearer                 | Basic, Digest               | Basic, Bearer, Digest (incl. SHA-256)      |\n| Build \u0026 Packaging   | Shared/static via CMake        | Static/shared library       | Header-only mode + Debian `.deb` packaging |\n| Test Coverage       | Minimal                      | Minimal                    | Full coverage with Doctest + CI             |\n| Thread Safety       | Not guaranteed                | Not guaranteed             | Not thread-safe (documented)                |\n| Customization       | Limited                      | Moderate                   | Extensive fine-tuned libcurl control        |\n| Docs \u0026 Examples     | Good docs, simple examples    | Sparse                     | Rich examples + auto-generated Doxygen docs|\n| Community           | Active, popular              | Aging, low activity        | Growing with CI, automation, and tests      |\n\n\n### Why Choose Curling Over CPR or curlpp?\n\nMore control, less complexity: Full access to advanced libcurl options via a modern interface.\n\nRAII-safe: Automatic cleanup prevents memory and resource leaks.\n\nRich MIME and auth support: Complex uploads and multiple authentication schemes are built-in.\n\nFlexible builds: Choose between header-only use or .deb packages for installation.\n\nCI and tests: Every commit is tested, ensuring high reliability.\n\nSafe defaults: Redirects and verbose logging are disabled by default, encouraging secure usage.\n\n\n\n---\n\n## 📚 Documentation\n\nGenerate API documentation with Doxygen:\n\n```bash\nmake doc\n```\n\nHTML output will appear in the doc/ folder.\n\nTo clean:\n\n```bash\nmake doc-clean\n```\n\n---\n\n## 🧪 Testing\n\nTests use Doctest and cover:\n\n- ✅ HTTP verbs: GET, POST, PUT, PATCH, DELETE, MIME\n\n- ✅ Authentication: Basic, Bearer, Digest (MD5, SHA-256, auth-int)\n\n- ✅ File download and upload\n\n- ✅ Header manipulation\n\n- ✅ JSON and form-data handling\n\n- ✅ Redirect handling\n\n\nRun locally:\n\n```bash\nmake test\n```\n\nGitHub Actions ensures tests pass on every push and pull request.\n\n\n---\n\n## 🤝 Contributing\n\nContributions are welcome! Please:\n\nFormat code consistently\n\nRun make test before pushing\n\nUse atomic and focused commits\n\n\n\n---\n\n## 📄 License\n\nThis project is licensed under the MIT License.\n\n\n---\n\n## 👤 Maintainer\n\nPaul Caron\n\n\n---\n\n## 📌 Notes\n\nCurl global init/cleanup is handled automatically.\n\nNot thread-safe — avoid sharing curling::Request across threads.\n\nMIME is a distinct HTTP method type (not used with POST/PUT).\n\n---\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaul-caron%2Fcurling","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpaul-caron%2Fcurling","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaul-caron%2Fcurling/lists"}