Coder Social home page Coder Social logo

taymindis / backcurl Goto Github PK

View Code? Open in Web Editor NEW
28.0 10.0 8.0 194 KB

C++ http client, pure libcurl based with customized set_easy_opt for different kind of requests for Mobile, NON BLOCK UI SYNC http request.

License: MIT License

CMake 21.38% C++ 76.35% Shell 0.09% Makefile 2.17%
cpp c android ios httpclient libcurl setopt nonblocking-sockets

backcurl's Introduction

backcurl

C++, pure libcurl based with customized set_easy_opt for different kind of requests for Mobile, NON BLOCK UI SYNC http request.

Run All the tests and mobile development build, if you do not need mobile development build, please go for second option.

cd build
cmake ..
cmake --build .
ctest -VV
sudo make install

Skip all the tests and mobile development build, just install backcurl core lib into system

cd backcurl-core
mkdir build
cd build
cmake ..
make
sudo make install
int main() {
    bcl::init(); // init when using

    bcl::execute<std::string>([&](bcl::Request *req) {
        bcl::setOpts(req, CURLOPT_URL , "http://www.google.com",
                 CURLOPT_FOLLOWLOCATION, 1L,
                 CURLOPT_WRITEFUNCTION, &bcl::writeContentCallback,
                 CURLOPT_WRITEDATA, req->dataPtr,
                 CURLOPT_USERAGENT, "libcurl-agent/1.0",
                 CURLOPT_RANGE, "0-200000"
                );
    }, [&](bcl::Response * resp) {
        std::string ret =  std::string(resp->getBody<std::string>()->c_str());
        printf("Sync === %s\n", ret.c_str());
    });


    bcl::cleanUp(); // clean up when no more using
}

For future non blocking sync

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

bcl::FutureResponse frp;

frp = bcl::execFuture<std::string>(simpleGetOption);
bool uiRunning = true;
while (uiRunning)  {
    if (bcl::hasRequestedAndReady(frp)) {
        bcl::FutureResp r = frp.get();
        printf("The data content is = %s\n", r->getBody<std::string>()->c_str());
        printf("Got Http Status code = %ld\n", r->code);
        printf("Got Content Type = %s\n", r->contentType.c_str());
        printf("Total Time Consume = %f\n", r->totalTime);
        printf("has Error = %s\n", !r->error.empty() ? "Yes" : "No");

        // Exit App
        uiRunning = false;
    }
    printf("\r Future Sync ==%s ----%d", "Drawing Graphiccccc with count elapsed ", countUI++);

}

if (!bcl::isProcessing(frp)) printf("no data process now, no more coming data\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

// Derived from example/main.cpp
void doGuiWork() {
    printf("\r %s --- %d", "Drawing thousand Pieces of Color with count elapsed ", countUI++);
}

void doUpdate() {
    bcl::LoopBackFire();
}

void doRunOnUI () {
    bool gui_running = true;
    std::cout << "Game is running thread: ";

    bcl::executeOnUI<std::string>([](bcl::Request * req) -> void {
        bcl::setOpts(req, CURLOPT_URL , "http://www.google.com",
        CURLOPT_FOLLOWLOCATION, 1L,
        CURLOPT_WRITEFUNCTION, &bcl::writeContentCallback,
        CURLOPT_WRITEDATA, req->dataPtr,
        CURLOPT_USERAGENT, "libcurl-agent/1.0",
        CURLOPT_RANGE, "0-200000"
                    );
    }, [&](bcl::Response * resp) {
        printf("On UI === %s\n", resp->getBody<std::string>()->c_str());
        printf("Done , stop gui running with count ui %d\n", countUI );
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        gui_running = false;
    });

    while (gui_running) {
        doGuiWork();
        doUpdate();
        std::this_thread::sleep_for(std::chrono::milliseconds(1000 / 16));
    }
}

For different kind of data type request, by default is std::string based

struct myType {
    std::string s;
    float f;
};

size_t myMemoryCallBack(void *contents, size_t size, size_t nmemb, void *contentWrapper) {
    size_t realsize = size * nmemb;
    myType *memBlock = (myType *)contentWrapper;

    // do your jobs

    return realsize;
}


int main() {
    bcl::init(); // init when using

    bcl::execute<myType>([&](bcl::Request *req) {
        bcl::setOpts(req, CURLOPT_URL , "http://www.google.com",
                 CURLOPT_FOLLOWLOCATION, 1L,
                 CURLOPT_WRITEFUNCTION, &myMemoryCallBack,
                 CURLOPT_WRITEDATA, req->dataPtr,
                 CURLOPT_USERAGENT, "libcurl-agent/1.0",
                 CURLOPT_RANGE, "0-200000"
                );
    }, [&](bcl::Response * resp) {
        myType* ret =  resp->getBody<myType>();
    });


    bcl::cleanUp(); // clean up when no more using
}

Set Opts in 1 line to customized request

bcl::setOpts(req, CURLOPT_URL , "http://www.google.com",
                 CURLOPT_FOLLOWLOCATION, 1L,
                 CURLOPT_WRITEFUNCTION, &myMemoryCallBack,
                 CURLOPT_WRITEDATA, req->dataPtr,
                 CURLOPT_USERAGENT, "libcurl-agent/1.0",
                 CURLOPT_RANGE, "0-200000"
                );

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

Set your http header in your request scope if needed, it is depended on libcurl CURLOPT_HTTPHEADER.

bcl::execute<myType>([&](bcl::Request *req) {
        req->headers->emplace_back("Authorization", res::mySetting[MY_BASIC_AUTH].asString());

        bcl::setOpts(req, CURLOPT_URL , "http://www.google.com",
                 CURLOPT_FOLLOWLOCATION, 1L,
                 CURLOPT_WRITEFUNCTION, &myMemoryCallBack,
                 CURLOPT_WRITEDATA, req->dataPtr,
                 CURLOPT_USERAGENT, "libcurl-agent/1.0",
                 CURLOPT_RANGE, "0-200000"
                );
    }, [&](bcl::Response * resp) {
        myType* ret =  resp->getBody<myType>();
    });

Download image

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

struct MyFileAgent {
    FILE *fd;
    struct stat fileInfo;
};

size_t write_data(void *ptr, size_t size, size_t nmemb, void *userData) {
    MyFileAgent* fAgent = (MyFileAgent*)userData;
    size_t written = fwrite((FILE*)ptr, size, nmemb, fAgent->fd);
    return written;
}
const char *url = "http://wallpapercave.com/wp/LmOgKXz.jpg";
    char outfilename[] = "husky_dog_wallpaper.jpeg";
    bcl::execute<MyFileAgent>([&](bcl::Request * req) -> void {
        MyFileAgent* fAgent = (MyFileAgent*)req->dataPtr;
        fAgent->fd = fopen(outfilename, "ab+");
        bcl::setOpts(req, CURLOPT_URL,url,
        CURLOPT_WRITEFUNCTION, write_data,
        CURLOPT_WRITEDATA, req->dataPtr,
        CURLOPT_FOLLOWLOCATION, 1L
                    );
    }, [&](bcl::Response * resp) {
        printf("Response content type = %s\n", resp->contentType.c_str());
        fclose(resp->getBody<MyFileAgent>()->fd);
    });

Get Image bytes into Memory

bcl::execute<bcl::MemoryByte>([](bcl::Request * req) {
    bcl::setOpts(req, CURLOPT_URL , "http://wallpapercave.com/wp/LmOgKXz.jpg",
                 CURLOPT_FOLLOWLOCATION, 1L,
                 CURLOPT_WRITEFUNCTION, &bcl::writeByteCallback,
                 CURLOPT_WRITEDATA, req->dataPtr,
                 CURLOPT_USERAGENT, "libcurl-agent/1.0",
                 CURLOPT_RANGE, "0-20000000"
                );
}, [&](bcl::Response * resp) {
    printf("Downloaded content 0x%02hx\n", (const unsigned char*)resp->getBody<bcl::MemoryByte>()->c_str());
    printf("bcl::MemoryByte size is %ld\n", resp->getBody<bcl::MemoryByte>()->size());
    double dl;
    if (!curl_easy_getinfo(resp->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &dl)) {
        printf("Downloaded %.0f bytes\n", dl);
    }
    long headerSize;
    if (!curl_easy_getinfo(resp->curl, CURLINFO_HEADER_SIZE, &headerSize)) {
        printf("Downloaded header size %ld bytes\n", headerSize);
    }
});

Using extra args for tracking information(alternative of lambda copy)

for (std::vector<std::string>::iterator it =
     urls.begin();
     it != urls.end(); ++it) {
    std::string url = *it;
    static int count = 0;
    bcl::executeOnUI<bcl::MemoryByte>([](bcl::Request * req) -> void {
        log::messageln("Submitted Url is %s ", req->args[0].getStr);
        bcl::setOpts(req, CURLOPT_URL ,req->args[0].getStr,
                     CURLOPT_FOLLOWLOCATION, req->args[1].getLong,
                     CURLOPT_WRITEFUNCTION, &bcl::writeByteCallback,
                     CURLOPT_WRITEDATA, req->dataPtr,
                     CURLOPT_USERAGENT, req->args[2].getStr,
                     CURLOPT_RANGE, req->args[3].getStr
                     );
    }, [&](bcl::Response * resp) {
        int imageCount = resp->args[4].getInt;
        bcl::MemoryByte *byte = resp->getBody<bcl::MemoryByte>();
        log::messageln("Image byte size is %lu",byte->size());
        spSprite nvgSprite = new NVGImageSprite((unsigned char*) byte->c_str(), static_cast<int>(byte->size()),  3.0f, 0);
        nvgSprite->setPosition(60 * imageCount, 60 * imageCount);
        nvgSprite->setSize(getStage()->getSize()/5);
        //            nvgSprite->setPriority(200);
        log::messageln("The count is %d", imageCount);
        addChild(nvgSprite);
    }, bcl::args(url.c_str(), 1L, "libbackcurl-agent/1.0", "0-20000000", ++count));
}

backcurl's People

Contributors

cdgwoon avatar moddx avatar nabijaczleweli avatar taymindis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

backcurl's Issues

C++11 Compilation fails on Ubuntu 18.04 (cmake 3.10.2)

error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options

Compilation fails with above message. The master CMakeLists.txt file does not enable c++11 support correcty for cmake 3.10.x. The following check fails:

if(NOT ${CMAKE_VERSION} LESS 3.2)
    set(CMAKE_CXX_STANDARD 11)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
else()

Apparently cmake sees cmake 3.10.x as lower than 3.2.0.
This behavior can befixed by comparing against version 3.1.0 (which is the minimum version for the CMAKE_CXX_STANDARD flag afaik, but don't quote me on that).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.