{"id":28970184,"url":"https://github.com/maximilianfeldthusen/integrate-asynchronous-i-o-using-modern-cpp","last_synced_at":"2025-06-24T10:40:38.389Z","repository":{"id":299391035,"uuid":"1002875314","full_name":"maximilianfeldthusen/Integrate-asynchronous-I-O-using-modern-Cpp","owner":"maximilianfeldthusen","description":"Integrate-asynchronous-I-O-using-modern-Cpp","archived":false,"fork":false,"pushed_at":"2025-06-16T09:32:22.000Z","size":11,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"TFD","last_synced_at":"2025-06-16T10:37:50.566Z","etag":null,"topics":["async","cpp","io"],"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/maximilianfeldthusen.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,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-16T09:24:04.000Z","updated_at":"2025-06-16T09:35:16.000Z","dependencies_parsed_at":"2025-06-16T10:39:51.770Z","dependency_job_id":"a99a05c5-fbb3-47cc-b001-683588e0c5c7","html_url":"https://github.com/maximilianfeldthusen/Integrate-asynchronous-I-O-using-modern-Cpp","commit_stats":null,"previous_names":["maximilianfeldthusen/integrate-asynchronous-i-o-using-modern-cpp"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/maximilianfeldthusen/Integrate-asynchronous-I-O-using-modern-Cpp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maximilianfeldthusen%2FIntegrate-asynchronous-I-O-using-modern-Cpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maximilianfeldthusen%2FIntegrate-asynchronous-I-O-using-modern-Cpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maximilianfeldthusen%2FIntegrate-asynchronous-I-O-using-modern-Cpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maximilianfeldthusen%2FIntegrate-asynchronous-I-O-using-modern-Cpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maximilianfeldthusen","download_url":"https://codeload.github.com/maximilianfeldthusen/Integrate-asynchronous-I-O-using-modern-Cpp/tar.gz/refs/heads/TFD","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maximilianfeldthusen%2FIntegrate-asynchronous-I-O-using-modern-Cpp/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261653786,"owners_count":23190530,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["async","cpp","io"],"created_at":"2025-06-24T10:40:35.500Z","updated_at":"2025-06-24T10:40:38.372Z","avatar_url":"https://github.com/maximilianfeldthusen.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Documentation \n\n### Integrate-asynchronous-I-O-using-modern-Cpp\n\n### 1. Header Inclusions and Type Alias\n\n```cpp\n#include \u003ciostream\u003e\n#include \u003cstdexcept\u003e\n#include \u003ccstdlib\u003e\n#include \u003cstring\u003e\n#include \u003cfuture\u003e\n#include \u003ccurl/curl.h\u003e\n#include \u003cnlohmann/json.hpp\u003e\n```\n\n- **`\u003ciostream\u003e`:** Provides input/output capabilities, allowing the code to print messages to the console.\n- **`\u003cstdexcept\u003e`:** Offers standard exception classes (like `std::runtime_error`), which are used here for error handling.\n- **`\u003ccstdlib\u003e`:** Contains utility functions such as `std::getenv` to access environment variables.\n- **`\u003cstring\u003e`:** Enables the use of C++'s `std::string` for text manipulation.\n- **`\u003cfuture\u003e`:** Supports asynchronous operations using `std::async` and `std::future`, letting the code perform a network call without blocking the main thread.\n- **`\u003ccurl/curl.h\u003e`:** Is the header for libcurl, which handles HTTP requests.\n- **`\u003cnlohmann/json.hpp\u003e`:** Is a popular header-only JSON library that makes it easy to build, parse, and manipulate JSON objects in C++.\n\nThe statement:\n```cpp\nusing json = nlohmann::json;\n```\ndefines an alias so that we can refer to `nlohmann::json` simply as `json` throughout the code.\n\n---\n\n### 2. The WriteCallback Function\n\n```cpp\nstatic size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {\n    size_t totalSize = size * nmemb;\n    std::string* mem = static_cast\u003cstd::string*\u003e(userp);\n    mem-\u003eappend(static_cast\u003cchar*\u003e(contents), totalSize);\n    return totalSize;\n}\n```\n\n- **Purpose:**  \n  This callback is used by libcurl to process chunks of data received from an HTTP request.\n\n- **How It Works:**\n  - **Parameters:**\n    - `contents`: Points to the raw data received.\n    - `size` **and** `nmemb`: Together they determine the total size of the incoming data (`totalSize = size * nmemb`).\n    - `userp`: A pointer that we expect to be a `std::string` where the data will be appended.\n  - **Operation:**  \n    The function casts `userp` to a `std::string*` and appends the new data to it. Finally, it returns the number of bytes processed which tells libcurl that the data was handled correctly.\n\n---\n\n### 3. The `callOpenAICompletionAPI` Function\n\nThis function builds and sends an asynchronous HTTP POST request to the OpenAI API and returns the response as a string.\n\n```cpp\nstd::string callOpenAICompletionAPI(const std::string\u0026 prompt) {\n    // Retrieve the API key securely from an environment variable.\n    const char* api_key = std::getenv(\"OPENAI_API_KEY\");\n    if (!api_key) {\n        throw std::runtime_error(\"Environment variable OPENAI_API_KEY not set.\");\n    }\n```\n\n- **API Key Retrieval:**  \n  It uses `std::getenv` to retrieve the API key from the environment variable `OPENAI_API_KEY`. If the key isn’t found, it throws a runtime error. This keeps sensitive credentials out of the source code.\n\n```cpp\n    CURL* curl = curl_easy_init();\n    if (!curl) {\n        throw std::runtime_error(\"Failed to initialize CURL.\");\n    }\n\n    std::string readBuffer;\n    CURLcode res;\n    struct curl_slist* headers = nullptr;\n```\n\n- **Initialization:**\n  - A CURL handle is initialized with `curl_easy_init()`. Failure to initialize results in an exception.\n  - `readBuffer` is declared to store the response.\n  - `headers` will hold custom HTTP headers.\n\n#### Inside the Try Block\n\n```cpp\n    try {\n        const std::string url = \"https://api.openai.com/v1/completions\";\n\n        json requestData = {\n            {\"model\", \"text-davinci-003\"},\n            {\"prompt\", prompt},\n            {\"max_tokens\", 150},\n            {\"temperature\", 0.7}\n        };\n\n        std::string requestBody = requestData.dump();\n```\n\n- **Request Preparation:**  \n  - **URL:** The API endpoint is defined as a constant string.\n  - **JSON Request:**  \n    A JSON object, `requestData`, is created containing parameters such as the model name, prompt, maximum allowed tokens for the response, and temperature. The JSON object is then converted (serialized) to a string called `requestBody`.\n\n```cpp\n        // Set CURL options.\n        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());\n        curl_easy_setopt(curl, CURLOPT_POST, 1L);\n        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, requestBody.c_str());\n```\n\n- **Setting Request Options:**  \n  These options instruct libcurl:\n  - To use the specified URL.\n  - To use the POST method.\n  - To set the body of the POST request to be the JSON string.\n\n```cpp\n        // Build and set HTTP headers.\n        std::string authHeader = \"Authorization: Bearer \" + std::string(api_key);\n        headers = curl_slist_append(headers, authHeader.c_str());\n        headers = curl_slist_append(headers, \"Content-Type: application/json\");\n        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);\n```\n\n- **HTTP Headers:**\n  - An Authorization header is built including the bearer token.\n  - A Content-Type header is added to specify the JSON format.\n  - These headers are then attached to the request.\n\n```cpp\n        // Register callback for writing received data.\n        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);\n        curl_easy_setopt(curl, CURLOPT_WRITEDATA, \u0026readBuffer);\n```\n\n- **Registering the Callback:**  \n  The callback (`WriteCallback`) is set so that the received data is written into `readBuffer`.\n\n```cpp\n        // Enforce secure TLS certificate verification.\n        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);\n        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);\n```\n\n- **TLS Security:**  \n  These options enforce verification of the SSL/TLS certificate, ensuring a secure connection.\n\n```cpp\n        // Execute the HTTP POST request.\n        res = curl_easy_perform(curl);\n        if (res != CURLE_OK) {\n            throw std::runtime_error(\"CURL error: \" + std::string(curl_easy_strerror(res)));\n        }\n```\n\n- **Executing the Request:**  \n  The API call is performed with `curl_easy_perform(curl)`. If any error occurs, an exception is thrown containing the relevant error message.\n\n```cpp\n        // Cleanup HTTP headers.\n        curl_slist_free_all(headers);\n        curl_easy_cleanup(curl);\n```\n\n- **Cleanup:**  \n  After the transaction, the allocated headers and CURL session are freed, which helps prevent memory leaks.\n\n#### Exception Handling\n\n```cpp\n    catch (...) {\n        if (headers) {\n            curl_slist_free_all(headers);\n        }\n        curl_easy_cleanup(curl);\n        throw;\n    }\n```\n\n- **Resource Management on Error:**  \n  If an exception is thrown, the catch block ensures that any allocated resources (like headers or the CURL handle) are properly cleaned up before rethrowing the exception.\n\n- **Return Value:**  \n  Finally, `readBuffer`, which now holds the response from the API, is returned.\n\n---\n\n### 4. The `main` Function\n\n```cpp\nint main() {\n    try {\n        std::string prompt = \"Explain best practices for writing secure C++ code with a focus on asynchronous I/O, including memory management, error handling, and secure API design.\";\n        std::cout \u003c\u003c \"Sending asynchronous request to OpenAI API...\\n\" \u003c\u003c std::endl;\n```\n\n- **Defining the Prompt:**  \n  A string `prompt` is defined which contains the question sent to the API.\n- **Output:**  \n  A message is printed to indicate that the asynchronous request is being sent.\n\n```cpp\n        // Launch the API call asynchronously.\n        std::future\u003cstd::string\u003e futureResponse = std::async(std::launch::async, callOpenAICompletionAPI, prompt);\n```\n\n- **Asynchronous Operation:**  \n  The API call is launched asynchronously using `std::async`. This creates a separate thread that will execute `callOpenAICompletionAPI` and returns a `std::future` that will eventually hold the result.\n\n```cpp\n        // Wait and get the result.\n        std::string response = futureResponse.get();\n```\n\n- **Waiting for the Response:**  \n  Using `futureResponse.get()` blocks until the asynchronous operation completes, then retrieves the response.\n\n```cpp\n        // Parse and pretty-print the JSON response.\n        json jsonResponse = json::parse(response);\n        std::cout \u003c\u003c \"Asynchronous OpenAI API Response:\\n\" \u003c\u003c jsonResponse.dump(4) \u003c\u003c std::endl;\n```\n\n- **JSON Parsing:**  \n  The response (assumed to be a JSON-formatted string) is parsed into a JSON object.\n- **Pretty Printing:**  \n  The JSON is printed to the console with an indentation of 4 spaces for readability.\n\n```cpp\n    }\n    catch (const std::exception\u0026 ex) {\n        std::cerr \u003c\u003c \"An error occurred: \" \u003c\u003c ex.what() \u003c\u003c std::endl;\n        return EXIT_FAILURE;\n    }\n    return EXIT_SUCCESS;\n}\n```\n\n- **Error Handling in `main`:**  \n  Any exceptions thrown during the process are caught, an error message is printed, and the program returns a failure code.\n- **Successful Exit:**  \n  If everything runs correctly, the program returns `EXIT_SUCCESS` (typically zero).\n\n---\n\n### Summary\n\n- **Security Practices:**  \n  - Retrieves API keys from environment variables.\n  - Enforces TLS verification when connecting to the API.\n\n- **Asynchronous Execution:**  \n  - Uses `std::async` and `std::future` to run the network call in a separate thread, keeping the application responsive.\n\n- **Libcurl and JSON:**  \n  - Utilizes libcurl to perform HTTP requests and employs a callback to accumulate the response.\n  - Uses nlohmann/json to build and parse JSON data effortlessly.\n\n- **Resource Management and Error Handling:**  \n  - Proper management of CURL resources (using cleanup calls) ensures no memory leaks.\n  - Try-catch blocks gracefully handle errors by releasing resources and providing informative error messages.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaximilianfeldthusen%2Fintegrate-asynchronous-i-o-using-modern-cpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaximilianfeldthusen%2Fintegrate-asynchronous-i-o-using-modern-cpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaximilianfeldthusen%2Fintegrate-asynchronous-i-o-using-modern-cpp/lists"}