{"id":14990021,"url":"https://github.com/taymindis/backcurl","last_synced_at":"2025-04-12T02:02:06.291Z","repository":{"id":40680378,"uuid":"92811000","full_name":"Taymindis/backcurl","owner":"Taymindis","description":"C++ http client, pure libcurl based with customized set_easy_opt for different kind of requests for Mobile, NON BLOCK UI SYNC http request.","archived":false,"fork":false,"pushed_at":"2018-10-31T15:43:16.000Z","size":194,"stargazers_count":29,"open_issues_count":0,"forks_count":8,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-03-25T21:47:12.841Z","etag":null,"topics":["android","c","cpp","httpclient","ios","libcurl","nonblocking-sockets","setopt"],"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/Taymindis.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}},"created_at":"2017-05-30T08:05:26.000Z","updated_at":"2024-11-27T07:11:56.000Z","dependencies_parsed_at":"2022-09-02T13:10:54.032Z","dependency_job_id":null,"html_url":"https://github.com/Taymindis/backcurl","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Taymindis%2Fbackcurl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Taymindis%2Fbackcurl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Taymindis%2Fbackcurl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Taymindis%2Fbackcurl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Taymindis","download_url":"https://codeload.github.com/Taymindis/backcurl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248505861,"owners_count":21115354,"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":["android","c","cpp","httpclient","ios","libcurl","nonblocking-sockets","setopt"],"created_at":"2024-09-24T14:19:20.806Z","updated_at":"2025-04-12T02:02:06.249Z","avatar_url":"https://github.com/Taymindis.png","language":"C++","readme":"# backcurl\nC++, pure libcurl based with customized set_easy_opt for different kind of requests for Mobile, NON BLOCK UI SYNC http request.\n\n\n### Run All the tests and mobile development build, if you do not need mobile development build, please go for second option.\n```\ncd build\ncmake ..\ncmake --build .\nctest -VV\nsudo make install\n```\n\n### Skip all the tests and mobile development build, just install backcurl core lib into system\n```\ncd backcurl-core\nmkdir build\ncd build\ncmake ..\nmake\nsudo make install\n```\n\n\n```cpp\nint main() {\n    bcl::init(); // init when using\n\n    bcl::execute\u003cstd::string\u003e([\u0026](bcl::Request *req) {\n        bcl::setOpts(req, CURLOPT_URL , \"http://www.google.com\",\n                 CURLOPT_FOLLOWLOCATION, 1L,\n                 CURLOPT_WRITEFUNCTION, \u0026bcl::writeContentCallback,\n                 CURLOPT_WRITEDATA, req-\u003edataPtr,\n                 CURLOPT_USERAGENT, \"libcurl-agent/1.0\",\n                 CURLOPT_RANGE, \"0-200000\"\n                );\n    }, [\u0026](bcl::Response * resp) {\n        std::string ret =  std::string(resp-\u003egetBody\u003cstd::string\u003e()-\u003ec_str());\n        printf(\"Sync === %s\\n\", ret.c_str());\n    });\n\n\n    bcl::cleanUp(); // clean up when no more using\n}\n```\n\n\n## For future non blocking sync\n### this is different with runOnUI method, you need to hold the FutureResponse in your mainthread and do verify bcl::hasRequestedAndReady(frp) for every update until the result is read\n\n```cpp\nbcl::FutureResponse frp;\n\nfrp = bcl::execFuture\u003cstd::string\u003e(simpleGetOption);\nbool uiRunning = true;\nwhile (uiRunning)  {\n    if (bcl::hasRequestedAndReady(frp)) {\n        bcl::FutureResp r = frp.get();\n        printf(\"The data content is = %s\\n\", r-\u003egetBody\u003cstd::string\u003e()-\u003ec_str());\n        printf(\"Got Http Status code = %ld\\n\", r-\u003ecode);\n        printf(\"Got Content Type = %s\\n\", r-\u003econtentType.c_str());\n        printf(\"Total Time Consume = %f\\n\", r-\u003etotalTime);\n        printf(\"has Error = %s\\n\", !r-\u003eerror.empty() ? \"Yes\" : \"No\");\n\n        // Exit App\n        uiRunning = false;\n    }\n    printf(\"\\r Future Sync ==%s ----%d\", \"Drawing Graphiccccc with count elapsed \", countUI++);\n\n}\n\nif (!bcl::isProcessing(frp)) printf(\"no data process now, no more coming data\\n\\n\" );\n```\n\n\n\n## For run on ui and call back to Main thread, this need to be done by put `bcl::LoopBackFire();` in your update scope\n```cpp\n// Derived from example/main.cpp\nvoid doGuiWork() {\n    printf(\"\\r %s --- %d\", \"Drawing thousand Pieces of Color with count elapsed \", countUI++);\n}\n\nvoid doUpdate() {\n    bcl::LoopBackFire();\n}\n\nvoid doRunOnUI () {\n    bool gui_running = true;\n    std::cout \u003c\u003c \"Game is running thread: \";\n\n    bcl::executeOnUI\u003cstd::string\u003e([](bcl::Request * req) -\u003e void {\n        bcl::setOpts(req, CURLOPT_URL , \"http://www.google.com\",\n        CURLOPT_FOLLOWLOCATION, 1L,\n        CURLOPT_WRITEFUNCTION, \u0026bcl::writeContentCallback,\n        CURLOPT_WRITEDATA, req-\u003edataPtr,\n        CURLOPT_USERAGENT, \"libcurl-agent/1.0\",\n        CURLOPT_RANGE, \"0-200000\"\n                    );\n    }, [\u0026](bcl::Response * resp) {\n        printf(\"On UI === %s\\n\", resp-\u003egetBody\u003cstd::string\u003e()-\u003ec_str());\n        printf(\"Done , stop gui running with count ui %d\\n\", countUI );\n        std::this_thread::sleep_for(std::chrono::milliseconds(500));\n        gui_running = false;\n    });\n\n    while (gui_running) {\n        doGuiWork();\n        doUpdate();\n        std::this_thread::sleep_for(std::chrono::milliseconds(1000 / 16));\n    }\n}\n```\n\n\n## For different kind of data type request,  by default is std::string based\n```cpp\nstruct myType {\n    std::string s;\n    float f;\n};\n\nsize_t myMemoryCallBack(void *contents, size_t size, size_t nmemb, void *contentWrapper) {\n    size_t realsize = size * nmemb;\n    myType *memBlock = (myType *)contentWrapper;\n\n    // do your jobs\n\n    return realsize;\n}\n\n\nint main() {\n    bcl::init(); // init when using\n\n    bcl::execute\u003cmyType\u003e([\u0026](bcl::Request *req) {\n        bcl::setOpts(req, CURLOPT_URL , \"http://www.google.com\",\n                 CURLOPT_FOLLOWLOCATION, 1L,\n                 CURLOPT_WRITEFUNCTION, \u0026myMemoryCallBack,\n                 CURLOPT_WRITEDATA, req-\u003edataPtr,\n                 CURLOPT_USERAGENT, \"libcurl-agent/1.0\",\n                 CURLOPT_RANGE, \"0-200000\"\n                );\n    }, [\u0026](bcl::Response * resp) {\n        myType* ret =  resp-\u003egetBody\u003cmyType\u003e();\n    });\n\n\n    bcl::cleanUp(); // clean up when no more using\n}\n```\n\n\n## Set Opts in 1 line to customized request\n```cpp\nbcl::setOpts(req, CURLOPT_URL , \"http://www.google.com\",\n                 CURLOPT_FOLLOWLOCATION, 1L,\n                 CURLOPT_WRITEFUNCTION, \u0026myMemoryCallBack,\n                 CURLOPT_WRITEDATA, req-\u003edataPtr,\n                 CURLOPT_USERAGENT, \"libcurl-agent/1.0\",\n                 CURLOPT_RANGE, \"0-200000\"\n                );\n```\n### for e.g, proxy request, proxy authenthication Get, Post, Head, Put, Basic Auth, please refer to libcurl for more details : https://curl.haxx.se/libcurl/c/curl_easy_setopt.html\n\n\n\n\n## Set your http header in your request scope if needed, it is depended on libcurl CURLOPT_HTTPHEADER.\n```cpp\nbcl::execute\u003cmyType\u003e([\u0026](bcl::Request *req) {\n        req-\u003eheaders-\u003eemplace_back(\"Authorization\", res::mySetting[MY_BASIC_AUTH].asString());\n\n        bcl::setOpts(req, CURLOPT_URL , \"http://www.google.com\",\n                 CURLOPT_FOLLOWLOCATION, 1L,\n                 CURLOPT_WRITEFUNCTION, \u0026myMemoryCallBack,\n                 CURLOPT_WRITEDATA, req-\u003edataPtr,\n                 CURLOPT_USERAGENT, \"libcurl-agent/1.0\",\n                 CURLOPT_RANGE, \"0-200000\"\n                );\n    }, [\u0026](bcl::Response * resp) {\n        myType* ret =  resp-\u003egetBody\u003cmyType\u003e();\n    });\n```\n\n\n## Download image\n### this needed to be done by wrapped file in the struct or class so it will be auto free the object. However, fd stream need to be closed at response scope\n```cpp\nstruct MyFileAgent {\n    FILE *fd;\n    struct stat fileInfo;\n};\n\nsize_t write_data(void *ptr, size_t size, size_t nmemb, void *userData) {\n    MyFileAgent* fAgent = (MyFileAgent*)userData;\n    size_t written = fwrite((FILE*)ptr, size, nmemb, fAgent-\u003efd);\n    return written;\n}\nconst char *url = \"http://wallpapercave.com/wp/LmOgKXz.jpg\";\n    char outfilename[] = \"husky_dog_wallpaper.jpeg\";\n    bcl::execute\u003cMyFileAgent\u003e([\u0026](bcl::Request * req) -\u003e void {\n        MyFileAgent* fAgent = (MyFileAgent*)req-\u003edataPtr;\n        fAgent-\u003efd = fopen(outfilename, \"ab+\");\n        bcl::setOpts(req, CURLOPT_URL,url,\n        CURLOPT_WRITEFUNCTION, write_data,\n        CURLOPT_WRITEDATA, req-\u003edataPtr,\n        CURLOPT_FOLLOWLOCATION, 1L\n                    );\n    }, [\u0026](bcl::Response * resp) {\n        printf(\"Response content type = %s\\n\", resp-\u003econtentType.c_str());\n        fclose(resp-\u003egetBody\u003cMyFileAgent\u003e()-\u003efd);\n    });\n```\n\n\n\n## Get Image bytes into Memory\n```cpp\nbcl::execute\u003cbcl::MemoryByte\u003e([](bcl::Request * req) {\n    bcl::setOpts(req, CURLOPT_URL , \"http://wallpapercave.com/wp/LmOgKXz.jpg\",\n                 CURLOPT_FOLLOWLOCATION, 1L,\n                 CURLOPT_WRITEFUNCTION, \u0026bcl::writeByteCallback,\n                 CURLOPT_WRITEDATA, req-\u003edataPtr,\n                 CURLOPT_USERAGENT, \"libcurl-agent/1.0\",\n                 CURLOPT_RANGE, \"0-20000000\"\n                );\n}, [\u0026](bcl::Response * resp) {\n    printf(\"Downloaded content 0x%02hx\\n\", (const unsigned char*)resp-\u003egetBody\u003cbcl::MemoryByte\u003e()-\u003ec_str());\n    printf(\"bcl::MemoryByte size is %ld\\n\", resp-\u003egetBody\u003cbcl::MemoryByte\u003e()-\u003esize());\n    double dl;\n    if (!curl_easy_getinfo(resp-\u003ecurl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, \u0026dl)) {\n        printf(\"Downloaded %.0f bytes\\n\", dl);\n    }\n    long headerSize;\n    if (!curl_easy_getinfo(resp-\u003ecurl, CURLINFO_HEADER_SIZE, \u0026headerSize)) {\n        printf(\"Downloaded header size %ld bytes\\n\", headerSize);\n    }\n});\n```\n\n\n## Using extra args for tracking information(alternative of lambda copy)\n```cpp\nfor (std::vector\u003cstd::string\u003e::iterator it =\n     urls.begin();\n     it != urls.end(); ++it) {\n    std::string url = *it;\n    static int count = 0;\n    bcl::executeOnUI\u003cbcl::MemoryByte\u003e([](bcl::Request * req) -\u003e void {\n        log::messageln(\"Submitted Url is %s \", req-\u003eargs[0].getStr);\n        bcl::setOpts(req, CURLOPT_URL ,req-\u003eargs[0].getStr,\n                     CURLOPT_FOLLOWLOCATION, req-\u003eargs[1].getLong,\n                     CURLOPT_WRITEFUNCTION, \u0026bcl::writeByteCallback,\n                     CURLOPT_WRITEDATA, req-\u003edataPtr,\n                     CURLOPT_USERAGENT, req-\u003eargs[2].getStr,\n                     CURLOPT_RANGE, req-\u003eargs[3].getStr\n                     );\n    }, [\u0026](bcl::Response * resp) {\n        int imageCount = resp-\u003eargs[4].getInt;\n        bcl::MemoryByte *byte = resp-\u003egetBody\u003cbcl::MemoryByte\u003e();\n        log::messageln(\"Image byte size is %lu\",byte-\u003esize());\n        spSprite nvgSprite = new NVGImageSprite((unsigned char*) byte-\u003ec_str(), static_cast\u003cint\u003e(byte-\u003esize()),  3.0f, 0);\n        nvgSprite-\u003esetPosition(60 * imageCount, 60 * imageCount);\n        nvgSprite-\u003esetSize(getStage()-\u003egetSize()/5);\n        //            nvgSprite-\u003esetPriority(200);\n        log::messageln(\"The count is %d\", imageCount);\n        addChild(nvgSprite);\n    }, bcl::args(url.c_str(), 1L, \"libbackcurl-agent/1.0\", \"0-20000000\", ++count));\n}\n```\n\n\n\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaymindis%2Fbackcurl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftaymindis%2Fbackcurl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaymindis%2Fbackcurl/lists"}