C++ Web Framework REST API

Overview

wfrest: C++ Web Framework REST API

Fast, efficient, and easiest c++ async micro web framework based on C++ Workflow.

🌟 Contents

💥 Dicssussion

For more information, you can first see discussions:

https://github.com/chanchann/wfrest/discussions

⌛️ Build

Cmake

git clone https://github.com/chanchann/wfrest.git
cd wfrest
mkdir build && cd build
cmake ..
make -j 
make install

Docker

Use dockerfile

docker build -t wfrest .

Or you can Pull from DockerHub

docker pull wfrest/wfrest

🚀 Quick start

#include "wfrest/HttpServer.h"
using namespace wfrest;

int main()
{
    HttpServer svr;

    // curl -v http://ip:port/hello
    svr.GET("/hello", [](const HttpReq *req, HttpResp *resp)
    {
        resp->String("world\n");
    });
    // curl -v http://ip:port/data
    svr.GET("/data", [](const HttpReq *req, HttpResp *resp)
    {
        std::string str = "Hello world";
        resp->String(std::move(str));
    });

    // curl -v http://ip:port/post -d 'post hello world'
    svr.POST("/post", [](const HttpReq *req, HttpResp *resp)
    {
        std::string body = req->body();
        fprintf(stderr, "post data : %s\n", body.c_str());
    });

    if (svr.start(8888) == 0)
    {
        getchar();
        svr.stop();
    } else
    {
        fprintf(stderr, "Cannot start server");
        exit(1);
    }
    return 0;
}

🎆 API Examples

Parameters in path

#include "wfrest/HttpServer.h"
using namespace wfrest;

int main()
{
    HttpServer svr;

    // This handler will match /user/chanchan but will not match /user/ or /user
    // curl -v "ip:port/user/chanchan/"
    svr.GET("/user/{name}", [](HttpReq *req, HttpResp *resp)
    {
        std::string name = req->param("name");
        // resp->set_status(HttpStatusOK); // automatically
        resp->String("Hello " + name + "\n");
    });

    // wildcast/chanchan/action... (prefix)
    svr.GET("/wildcast/{name}/action*", [](HttpReq *req, HttpResp *resp)
    {
        std::string name = req->param("name");
        std::string message = name + " : path " + req->get_request_uri();

        resp->String("Hello " + message + "\n");
    });

    // request will hold the route definition
    svr.GET("/user/{name}/match*", [](HttpReq *req, HttpResp *resp)
    {
        std::string full_path = req->full_path();
        if (full_path == "/user/{name}/match*")
        {
            full_path += " match";
        } else
        {
            full_path += " dosen't match";
        }
        resp->String(full_path);
    });

    // This handler will add a new router for /user/groups.
    // Exact routes are resolved before param routes, regardless of the order they were defined.
    // Routes starting with /user/groups are never interpreted as /user/{name}/... routes
    svr.GET("/user/groups", [](HttpReq *req, HttpResp *resp)
    {
        resp->String(req->full_path());
    });

    if (svr.start(8888) == 0)
    {
        getchar();
        svr.stop();
    } else
    {
        fprintf(stderr, "Cannot start server");
        exit(1);
    }
    return 0;
}

Querystring parameters

#include "wfrest/HttpServer.h"
using namespace wfrest;

int main()
{
    HttpServer svr;

    // The request responds to a url matching:  /query_list?username=chanchann&password=yyy
    svr.GET("/query_list", [](HttpReq *req, HttpResp *resp)
    {
        std::unordered_map<std::string, std::string> query_list = req->query_list();
        for(auto& query : query_list)
        {
            fprintf(stderr, "%s : %s\n", query.first.c_str(), query.second.c_str());
        }
    });

    // The request responds to a url matching:  /query?username=chanchann&password=yyy
    svr.GET("/query", [](HttpReq *req, HttpResp *resp)
    {
        std::string user_name = req->query("username");
        std::string password = req->query("password");
        std::string info = req->query("info"); // no this field
        std::string address = req->default_query("address", "china");
        resp->String(user_name + " " + password + " " + info + " " + address + "\n");
    });

    // The request responds to a url matching:  /query_has?username=chanchann&password=
    // The logic for judging whether a parameter exists is that if the parameter value is empty, the parameter is considered to exist
    // and the parameter does not exist unless the parameter is submitted.
    svr.GET("/query_has", [](HttpReq *req, HttpResp *resp)
    {
        if(req->has_query("password"))
        {
            fprintf(stderr, "has password query\n");
        }
        if(req->has_query("info"))
        {
            fprintf(stderr, "has info query\n");
        }
    });

    if (svr.start(8888) == 0)
    {
        getchar();
        svr.stop();
    } else
    {
        fprintf(stderr, "Cannot start server");
        exit(1);
    }
    return 0;
}

Post Form

#include "wfrest/HttpServer.h"
using namespace wfrest;

int main()
{
    HttpServer svr;

    // Urlencoded Form
    // curl -v http://ip:port/post -H "body-type:application/x-www-form-urlencoded" -d 'user=admin&pswd=123456'
    svr.POST("/post", [](const HttpReq *req, HttpResp *resp)
    {
        if(req->content_type != APPLICATION_URLENCODED)
        {
            resp->set_status(HttpStatusBadRequest);
            return;
        }
        auto& form_kv = req->kv;
        for(auto& kv : form_kv)
        {
            fprintf(stderr, "key %s : vak %s\n", kv.first.c_str(), kv.second.c_str());
        }
    });

    // curl -X POST http://ip:port/form \
    // -F "file=@/path/file" \
    // -H "Content-Type: multipart/form-data"
    svr.POST("/form", [](const HttpReq *req, HttpResp *resp)
    {
        if(req->content_type != MULTIPART_FORM_DATA)
        {
            resp->set_status(HttpStatusBadRequest);
            return;
        }
        fprintf(stderr, "123\n");
        auto& form_kv = req->form;
        for(auto & it : form_kv)
        {
            fprintf(stderr, "%s : %s = %s",
                                it.first.c_str(),
                                it.second.body.c_str(),
                                it.second.filename.c_str());
        }
    });

    if (svr.start(8888) == 0)
    {
        getchar();
        svr.stop();
    } else
    {
        fprintf(stderr, "Cannot start server");
        exit(1);
    }
    return 0;
}

Header

#include "wfrest/HttpServer.h"
using namespace wfrest;

int main()
{
    HttpServer svr;

    svr.POST("/post", [](HttpReq *req, HttpResp *resp)
    {
        std::string host = req->header("Host");
        std::string content_type = req->header("Content-Type");
        if(req->has_header("User-Agent"))
        {
            fprintf(stderr, "Has User-Agent...");
        }
        resp->String(host + " " + content_type + "\n");
    });


    if (svr.start(8888) == 0)
    {
        getchar();
        svr.stop();
    } else
    {
        fprintf(stderr, "Cannot start server");
        exit(1);
    }
    return 0;
}

Send File

#include "wfrest/HttpServer.h"
using namespace wfrest;

int main()
{
    HttpServer svr;
    svr.mount("static");

    // single files
    svr.GET("/file1", [](const HttpReq *req, HttpResp *resp)
    {
        resp->File("todo.txt");
    });

    svr.GET("/file2", [](const HttpReq *req, HttpResp *resp)
    {
        resp->File("html/index.html");
    });

    svr.GET("/file3", [](const HttpReq *req, HttpResp *resp)
    {
        resp->File("/html/index.html");
    });

    svr.GET("/file4", [](const HttpReq *req, HttpResp *resp)
    {
        resp->File("todo.txt", 0);
    });

    svr.GET("/file5", [](const HttpReq *req, HttpResp *resp)
    {
        resp->File("todo.txt", 0, 10);
    });

    svr.GET("/file6", [](const HttpReq *req, HttpResp *resp)
    {
        resp->File("todo.txt", 5, 10);
    });

    // multiple files
    svr.GET("/multi_files", [](const HttpReq *req, HttpResp *resp)
    {
        std::vector<std::string> file_list = {"test.txt", "todo.txt", "test1.txt"};
        resp->File(file_list);
    });

    if (svr.start(8888) == 0)
    {
        getchar();
        svr.stop();
    } else
    {
        fprintf(stderr, "Cannot start server");
        exit(1);
    }
    return 0;
}

Save File

#include "wfrest/HttpServer.h"
using namespace wfrest;

int main()
{
    HttpServer svr;

    // curl -v -X POST "ip:port/file_write1" -F "[email protected]" -H "Content-Type: multipart/form-data"
    svr.POST("/file_write1", [](const HttpReq *req, HttpResp *resp)
    {
        std::string body = req->body();   // multipart/form - body has boundary
        resp->Save("test.txt", std::move(body));
    });

    svr.GET("/file_write2", [](const HttpReq *req, HttpResp *resp)
    {
        std::string body = "1234567890987654321";

        resp->Save("test1.txt", std::move(body));
    });

    if (svr.start(8888) == 0)
    {
        getchar();
        svr.stop();
    } else
    {
        fprintf(stderr, "Cannot start server");
        exit(1);
    }
    return 0;
}

Upload Files

#include "wfrest/HttpServer.h"
#include "wfrest/PathUtil.h"
using namespace wfrest;

int main()
{
    HttpServer svr;
    svr.mount("/static");

    // An expriment (Upload a file to parent dir is really dangerous.):
    // curl -v -X POST "ip:port/upload" -F "[email protected]; filename=../demo.txt" -H "Content-Type: multipart/form-data"
    // Then you find the file is store in the parent dir, which is dangerous
    svr.POST("/upload", [](HttpReq *req, HttpResp *resp)
    {
        std::vector<FormData *> files = req->post_files();
        if(files.empty())
        {
            resp->set_status(HttpStatusBadRequest);
        } else
        {
            auto *file = files[0];
            // file->filename SHOULD NOT be trusted. See Content-Disposition on MDN
            // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#directives
            // The filename is always optional and must not be used blindly by the application:
            // path information should be stripped, and conversion to the server file system rules should be done.
            fprintf(stderr, "filename : %s\n", file->filename.c_str());
            resp->Save(file->filename, std::move(file->body));
        }
    });

    // Here is the right way:
    // curl -v -X POST "ip:port/upload" -F "[email protected]; filename=../demo.txt" -H "Content-Type: multipart/form-data"
    svr.POST("/upload_fix", [](HttpReq *req, HttpResp *resp)
    {
        std::vector<FormData *> files = req->post_files();
        if(files.empty())
        {
            resp->set_status(HttpStatusBadRequest);
        } else
        {
            auto *file = files[0];
            // simple solution to fix the problem above
            // This will restrict the upload file to current directory.
            resp->Save(PathUtil::base(file->filename), std::move(file->body));
        }
    });

    // upload multiple files
    // curl -X POST http://ip:port/upload_multiple \
    // -F "[email protected]" \
    // -F "[email protected]" \
    // -H "Content-Type: multipart/form-data"
    svr.POST("/upload_multiple", [](HttpReq *req, HttpResp *resp)
    {
        std::vector<FormData *> files = req->post_files();
        if(files.empty())
        {
            resp->set_status(HttpStatusBadRequest);
        } else
        {
            for(auto& file : files)
            {
                resp->Save(PathUtil::base(file->filename), std::move(file->body));
            }
        }
    });

    if (svr.start(8888) == 0)
    {
        getchar();
        svr.stop();
    } else
    {
        fprintf(stderr, "Cannot start server");
        exit(1);
    }
    return 0;
}

Json

#include "wfrest/HttpServer.h"
using namespace wfrest;

int main()
{
    HttpServer svr;

    // curl -v http://ip:port/json1
    svr.GET("/json1", [](const HttpReq *req, HttpResp *resp)
    {
        Json json;
        json["test"] = 123;
        json["json"] = "test json";
        resp->Json(json);
    });

    // curl -v http://ip:port/json2
    svr.GET("/json2", [](const HttpReq *req, HttpResp *resp)
    {
        std::string valid_text = R"(
        {
            "numbers": [1, 2, 3]
        }
        )";
        resp->Json(valid_text);
    });

    // curl -v http://ip:port/json3
    svr.GET("/json3", [](const HttpReq *req, HttpResp *resp)
    {
        std::string invalid_text = R"(
        {
            "strings": ["extra", "comma", ]
        }
        )";
        resp->Json(invalid_text);
    });

    // recieve json
    //   curl -X POST http://ip:port/json4
    //   -H 'Content-Type: application/json'
    //   -d '{"login":"my_login","password":"my_password"}'
    svr.POST("/json4", [](const HttpReq *req, HttpResp *resp)
    {
        if(req->content_type != APPLICATION_JSON)
        {
            resp->String("NOT APPLICATION_JSON");
            return;
        }
        fprintf(stderr, "Json : %s", req->json.dump(4).c_str());
    });

    if (svr.start(8888) == 0)
    {
        getchar();
        svr.stop();
    } else
    {
        fprintf(stderr, "Cannot start server");
        exit(1);
    }
    return 0;
}

Computing task

#include "wfrest/HttpServer.h"
using namespace wfrest;

void Fibonacci(int n, HttpResp *resp)
{
    unsigned long long x = 0, y = 1;
    if (n <= 0 || n > 94)
    {
        fprintf(stderr, "invalid parameter");
        return;
    }
    for (int i = 2; i < n; i++)
    {
        y = x + y;
        x = y - x;
    }
    if (n == 1)
        y = 0;
    resp->String("fib(" + std::to_string(n) + ") is : " + std::to_string(y) + "\n");
}

int main()
{
    HttpServer svr;
    // Second parameter means this computing queue id is 1
    // Then this handler become a computing task
    // curl -v http://ip:port/compute_task?num=20
    svr.GET("/compute_task", 1, [](HttpReq *req, HttpResp *resp)
    {
        int num = std::stoi(req->query("num"));
        Fibonacci(num, resp);
    });

    if (svr.start(8888) == 0)
    {
        getchar();
        svr.stop();
    } else
    {
        fprintf(stderr, "Cannot start server");
        exit(1);
    }
    return 0;
}

ServerSeries Interface

#include "wfrest/HttpServer.h"
using namespace wfrest;

int main()
{
    HttpServer svr;

    svr.GET("/series", [](const HttpReq *req, HttpResp *resp, SeriesWork* series)
    {
        auto *timer = WFTaskFactory::create_timer_task(5000000, [](WFTimerTask *) {
            printf("timer task complete(5s).\n");
        });

        series->push_back(timer);
    });

    if (svr.start(8888) == 0)
    {
        getchar();
        svr.stop();
    } else
    {
        fprintf(stderr, "Cannot start server");
        exit(1);
    }
    return 0;
}

How to use logger

#include "wfrest/Logger.h"
using namespace wfrest;

int main()
{
    // set the logger config
    LoggerSettings settings = LOGGER_SETTINGS_DEFAULT;
    settings.level = LogLevel::TRACE;
    settings.log_in_file = true;
    LOGGER(&settings);

    int i = 1;
    LOG_DEBUG << (float)3.14;
    LOG_DEBUG << (const char)'8';
    LOG_DEBUG << &i;
    LOG_DEBUG << wfrest::Fmt("%.3f", 3.1415926);
    LOG_DEBUG << "debug";
    LOG_TRACE << "trace";
    LOG_INFO << "info";
    LOG_WARN << "warning";

    FILE *fp = fopen("/not_exist_file", "rb");
    if (fp == nullptr)
    {
        LOG_SYSERR << "syserr log!";
    }
    LOG_DEBUG  << abc << 123.345 << "chanchan" << '\n'
               << std::string("name");
    return 0;
}

All the configure fields are:

struct LoggerSettings
{
    LogLevel level;    
    bool log_in_console;    
    bool log_in_file;
    const char *file_path;
    const char *file_base_name;
    const char *file_extension;
    uint64_t roll_size;
    std::chrono::seconds flush_interval;
};

Default configure :

static constexpr struct LoggerSettings LOGGER_SETTINGS_DEFAULT =
{
    .level = LogLevel::INFO,
    .log_in_console = true,
    .log_in_file = false,
    .file_path = "./",
    .file_base_name = "wfrest",
    .file_extension = ".log",
    .roll_size = 20 * 1024 * 1024,
    .flush_interval = std::chrono::seconds(3),
};

Sample Output

2021-11-30 22:36:21.422271 822380  [ERROR]  [logger_test.cc:84] No such file or directory (errno=2) syserr log
Comments
  • two test tests failed on Arm64 platform

    two test tests failed on Arm64 platform

    [email protected]:~/workspace/cpprest/wfrest# ./test.sh 
    + BUILD_DIR=./test/build
    + mkdir -p ./test/build
    + cd ./test/build
    + cmake ..
    -- Build wfrest unit test
    -- Configuring done
    -- Generating done
    -- Build files have been written to: /root/workspace/cpprest/wfrest/test/build
    + make
    Consolidate compiler generated dependencies of target router_test
    [  2%] Linking CXX executable router_test
    [  4%] Built target router_test
    [  6%] Building CXX object CMakeFiles/multi_part_test.dir/multi_part_test.cc.o
    [  8%] Linking CXX executable multi_part_test
    [  8%] Built target multi_part_test
    [ 10%] Building CXX object CMakeFiles/StringPiece_feature.dir/StringPiece_feature.cc.o
    [ 12%] Linking CXX executable StringPiece_feature
    [ 12%] Built target StringPiece_feature
    [ 14%] Building CXX object CMakeFiles/RouteTableNode_test.dir/RouteTableNode_test.cc.o
    [ 16%] Linking CXX executable RouteTableNode_test
    [ 16%] Built target RouteTableNode_test
    [ 18%] Building CXX object CMakeFiles/StrUtil_unittest.dir/StrUtil_unittest.cc.o
    [ 20%] Linking CXX executable StrUtil_unittest
    [ 20%] Built target StrUtil_unittest
    [ 22%] Building CXX object CMakeFiles/StringPiece_unittest.dir/StringPiece_unittest.cc.o
    [ 25%] Linking CXX executable StringPiece_unittest
    [ 25%] Built target StringPiece_unittest
    [ 27%] Building CXX object CMakeFiles/Compress_unittest.dir/Compress_unittest.cc.o
    [ 29%] Linking CXX executable Compress_unittest
    [ 29%] Built target Compress_unittest
    [ 31%] Building CXX object CMakeFiles/Router_unittest.dir/Router_unittest.cc.o
    [ 33%] Linking CXX executable Router_unittest
    [ 33%] Built target Router_unittest
    [ 35%] Building CXX object CMakeFiles/base64_unittest.dir/base64_unittest.cc.o
    [ 37%] Linking CXX executable base64_unittest
    [ 37%] Built target base64_unittest
    [ 39%] Building CXX object CMakeFiles/BluePrint_unittest.dir/BluePrint_unittest.cc.o
    [ 41%] Linking CXX executable BluePrint_unittest
    [ 41%] Built target BluePrint_unittest
    [ 43%] Building CXX object CMakeFiles/FileUtil_unittest.dir/FileUtil_unittest.cc.o
    [ 45%] Building CXX object CMakeFiles/FileUtil_unittest.dir/FileTestUtil.cc.o
    [ 47%] Linking CXX executable FileUtil_unittest
    [ 47%] Built target FileUtil_unittest
    [ 50%] Building CXX object CMakeFiles/PathUtil_unittest.dir/PathUtil_unittest.cc.o
    [ 52%] Building CXX object CMakeFiles/PathUtil_unittest.dir/FileTestUtil.cc.o
    [ 54%] Linking CXX executable PathUtil_unittest
    [ 54%] Built target PathUtil_unittest
    [ 56%] Building CXX object CMakeFiles/TimeStamp_unittest.dir/TimeStamp_unittest.cc.o
    [ 58%] Linking CXX executable TimeStamp_unittest
    [ 58%] Built target TimeStamp_unittest
    [ 60%] Building CXX object CMakeFiles/HttpCookie_unittest.dir/HttpCookie_unittest.cc.o
    [ 62%] Linking CXX executable HttpCookie_unittest
    [ 62%] Built target HttpCookie_unittest
    [ 64%] Building CXX object CMakeFiles/RouteTable_unittest.dir/RouteTable_unittest.cc.o
    [ 66%] Linking CXX executable RouteTable_unittest
    [ 66%] Built target RouteTable_unittest
    [ 68%] Building CXX object CMakeFiles/HttpDef_unittest.dir/HttpDef_unittest.cc.o
    [ 70%] Linking CXX executable HttpDef_unittest
    [ 70%] Built target HttpDef_unittest
    [ 72%] Building CXX object CMakeFiles/server_send_unittest.dir/HttpServer/send_unittest.cc.o
    [ 75%] Linking CXX executable server_send_unittest
    [ 75%] Built target server_send_unittest
    [ 77%] Building CXX object CMakeFiles/server_param_unittest.dir/HttpServer/param_unittest.cc.o
    [ 79%] Linking CXX executable server_param_unittest
    [ 79%] Built target server_param_unittest
    [ 81%] Building CXX object CMakeFiles/server_json_unittest.dir/HttpServer/json_unittest.cc.o
    [ 83%] Linking CXX executable server_json_unittest
    [ 83%] Built target server_json_unittest
    [ 85%] Building CXX object CMakeFiles/server_file_unittest.dir/HttpServer/file_unittest.cc.o
    [ 87%] Building CXX object CMakeFiles/server_file_unittest.dir/FileTestUtil.cc.o
    [ 89%] Linking CXX executable server_file_unittest
    [ 89%] Built target server_file_unittest
    [ 91%] Building CXX object CMakeFiles/server_proxy_unittest.dir/HttpServer/proxy_unittest.cc.o
    [ 93%] Linking CXX executable server_proxy_unittest
    [ 93%] Built target server_proxy_unittest
    [ 95%] Building CXX object CMakeFiles/server_static_unittest.dir/HttpServer/static_unittest.cc.o
    [ 97%] Building CXX object CMakeFiles/server_static_unittest.dir/FileTestUtil.cc.o
    [100%] Linking CXX executable server_static_unittest
    [100%] Built target server_static_unittest
    + make test
    Running tests...
    Test project /root/workspace/cpprest/wfrest/test/build
          Start  1: StrUtil_unittest
     1/18 Test  #1: StrUtil_unittest .................   Passed    0.01 sec
          Start  2: StringPiece_unittest
     2/18 Test  #2: StringPiece_unittest .............   Passed    0.01 sec
          Start  3: Compress_unittest
     3/18 Test  #3: Compress_unittest ................   Passed    0.05 sec
          Start  4: Router_unittest
     4/18 Test  #4: Router_unittest ..................   Passed    0.01 sec
          Start  5: base64_unittest
     5/18 Test  #5: base64_unittest ..................   Passed    0.01 sec
          Start  6: BluePrint_unittest
     6/18 Test  #6: BluePrint_unittest ...............   Passed    0.01 sec
          Start  7: FileUtil_unittest
     7/18 Test  #7: FileUtil_unittest ................   Passed    0.01 sec
          Start  8: PathUtil_unittest
     8/18 Test  #8: PathUtil_unittest ................   Passed    0.01 sec
          Start  9: TimeStamp_unittest
     9/18 Test  #9: TimeStamp_unittest ...............***Failed    0.01 sec
          Start 10: HttpCookie_unittest
    10/18 Test #10: HttpCookie_unittest ..............***Failed    0.01 sec
          Start 11: RouteTable_unittest
    11/18 Test #11: RouteTable_unittest ..............   Passed    0.01 sec
          Start 12: HttpDef_unittest
    12/18 Test #12: HttpDef_unittest .................   Passed    0.01 sec
          Start 13: server_send_unittest
    13/18 Test #13: server_send_unittest .............   Passed    0.03 sec
          Start 14: server_param_unittest
    14/18 Test #14: server_param_unittest ............   Passed    0.01 sec
          Start 15: server_json_unittest
    15/18 Test #15: server_json_unittest .............   Passed    0.01 sec
          Start 16: server_file_unittest
    16/18 Test #16: server_file_unittest .............   Passed    0.04 sec
          Start 17: server_proxy_unittest
    17/18 Test #17: server_proxy_unittest ............   Passed    0.01 sec
          Start 18: server_static_unittest
    18/18 Test #18: server_static_unittest ...........   Passed    0.03 sec
    
    89% tests passed, 2 tests failed out of 18
    
    Total Test time (real) =   0.28 sec
    
    The following tests FAILED:
              9 - TimeStamp_unittest (Failed)
             10 - HttpCookie_unittest (Failed)
    Errors while running CTest
    Output from these tests are in: /root/workspace/cpprest/wfrest/test/build/Testing/Temporary/LastTest.log
    Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.
    make: *** [Makefile:71: test] Error 8
    
    opened by cnmade 10
  • HTTP Proxy Problem:Parameters will be lost when forwarding a request

    HTTP Proxy Problem:Parameters will be lost when forwarding a request

    #include "wfrest/HttpServer.h"
    using namespace wfrest;
    
    int main()
    {
        HttpServer svr;
    
        svr.GET("/", [](const HttpReq *req, HttpResp *resp)
        {
            resp->Http("127.0.0.1:777/path?a=1");
        });
        if (svr.start(8888) == 0)
        {
            getchar();
            svr.stop();
        } else
        {
            fprintf(stderr, "Cannot start server");
            exit(1);
        }
        return 0;
    }
    

    When build the proxy server with the code above, the query parameters are lost for the forwarded request.

    Here's how I reproduce the problem

    ./http_proxy_server
    nc -l -p 777
    curl 127.0.0.1:8888/
    

    It can be seen that parameters are not forwarded.

    GET /path HTTP/1.1
    User-Agent: curl/7.29.0
    Host: 127.0.0.1:8888
    Accept: */*
    Connection: Keep-Alive
    

    When I use

    curl 127.0.0.1:777/paht?a=1
    

    everything is normal

    GET /paht?a=1 HTTP/1.1
    User-Agent: curl/7.29.0
    Host: 127.0.0.1:777
    Accept: */*
    
    opened by HaoDongddd 4
  • Segment fault after calling SeriesWork::cancel() in the task.

    Segment fault after calling SeriesWork::cancel() in the task.

    I'm trying to use the SeriesWork feature through the wfrest's interface like what 12_series_interface.cc shown. When I call SeriesWork::cancel() in the HttpServer callback to interrupt the series,the program crash after calling SeriesWork::~Series().

    This error might be caused by Router.cc line 56/59,you call series_of() to get SeriesWork object while it is actually not allocated.

    opened by yuxilao 4
  • 编译报错

    编译报错

    今天下载wfrest代码,按照步骤执行make,报错: in file included from src/core/BluePrint.inl: in member function wfrest::Blueprint::ROUTE… 165:31: error: expected ',' before '…' token 还有185行,305行,326行都有类似错误,请看看应该如何解决?

    opened by henryw2019 3
  • Info: wfrest can build on ARM64 and AMD64 , either docker or podman

    Info: wfrest can build on ARM64 and AMD64 , either docker or podman

    Tested docker build wfrest, on platform ubuntu arm64 and amd64, docker and podman both works.

    make[2]: Leaving directory '/home/project/workflow/build.cmake'
    Install the project...
    -- Install configuration: "RelWithDebInfo"
    -- Installing: /usr/local/lib/cmake/workflow/workflow-config.cmake
    -- Installing: /usr/local/lib/cmake/workflow/workflow-config-version.cmake
    -- Installing: /usr/local/include/workflow/DnsRoutine.h
    -- Installing: /usr/local/include/workflow/MapReduce.h
    -- Installing: /usr/local/include/workflow/MapReduce.inl
    -- Installing: /usr/local/include/workflow/ProtocolMessage.h
    -- Installing: /usr/local/include/workflow/http_parser.h
    -- Installing: /usr/local/include/workflow/HttpMessage.h
    -- Installing: /usr/local/include/workflow/HttpUtil.h
    -- Installing: /usr/local/include/workflow/redis_parser.h
    -- Installing: /usr/local/include/workflow/RedisMessage.h
    -- Installing: /usr/local/include/workflow/mysql_stream.h
    -- Installing: /usr/local/include/workflow/MySQLMessage.h
    -- Installing: /usr/local/include/workflow/MySQLMessage.inl
    -- Installing: /usr/local/include/workflow/MySQLResult.h
    -- Installing: /usr/local/include/workflow/MySQLResult.inl
    -- Installing: /usr/local/include/workflow/mysql_parser.h
    -- Installing: /usr/local/include/workflow/mysql_types.h
    -- Installing: /usr/local/include/workflow/mysql_byteorder.h
    -- Installing: /usr/local/include/workflow/SSLWrapper.h
    -- Installing: /usr/local/include/workflow/dns_parser.h
    -- Installing: /usr/local/include/workflow/DnsMessage.h
    -- Installing: /usr/local/include/workflow/DnsUtil.h
    -- Installing: /usr/local/include/workflow/WFServer.h
    -- Installing: /usr/local/include/workflow/WFDnsServer.h
    -- Installing: /usr/local/include/workflow/WFHttpServer.h
    -- Installing: /usr/local/include/workflow/WFRedisServer.h
    -- Installing: /usr/local/include/workflow/WFMySQLServer.h
    -- Installing: /usr/local/include/workflow/WFMySQLConnection.h
    -- Installing: /usr/local/include/workflow/WFDnsClient.h
    -- Installing: /usr/local/include/workflow/DnsCache.h
    -- Installing: /usr/local/include/workflow/WFGlobal.h
    -- Installing: /usr/local/include/workflow/UpstreamManager.h
    -- Installing: /usr/local/include/workflow/RouteManager.h
    -- Installing: /usr/local/include/workflow/EndpointParams.h
    -- Installing: /usr/local/include/workflow/WFFuture.h
    -- Installing: /usr/local/include/workflow/WFFacilities.h
    -- Installing: /usr/local/include/workflow/WFFacilities.inl
    -- Installing: /usr/local/include/workflow/EncodeStream.h
    -- Installing: /usr/local/include/workflow/LRUCache.h
    -- Installing: /usr/local/include/workflow/StringUtil.h
    -- Installing: /usr/local/include/workflow/URIParser.h
    -- Installing: /usr/local/include/workflow/MD5Util.h
    -- Installing: /usr/local/include/workflow/WFConnection.h
    -- Installing: /usr/local/include/workflow/WFTask.h
    -- Installing: /usr/local/include/workflow/WFTask.inl
    -- Installing: /usr/local/include/workflow/WFGraphTask.h
    -- Installing: /usr/local/include/workflow/WFTaskError.h
    -- Installing: /usr/local/include/workflow/WFTaskFactory.h
    -- Installing: /usr/local/include/workflow/WFTaskFactory.inl
    -- Installing: /usr/local/include/workflow/WFAlgoTaskFactory.h
    -- Installing: /usr/local/include/workflow/WFAlgoTaskFactory.inl
    -- Installing: /usr/local/include/workflow/Workflow.h
    -- Installing: /usr/local/include/workflow/WFOperator.h
    -- Installing: /usr/local/include/workflow/WFResourcePool.h
    -- Installing: /usr/local/include/workflow/WFNameService.h
    -- Installing: /usr/local/include/workflow/WFDnsResolver.h
    -- Installing: /usr/local/include/workflow/WFServiceGovernance.h
    -- Installing: /usr/local/include/workflow/UpstreamPolicies.h
    -- Installing: /usr/local/include/workflow/CommRequest.h
    -- Installing: /usr/local/include/workflow/CommScheduler.h
    -- Installing: /usr/local/include/workflow/Communicator.h
    -- Installing: /usr/local/include/workflow/SleepRequest.h
    -- Installing: /usr/local/include/workflow/ExecRequest.h
    -- Installing: /usr/local/include/workflow/IORequest.h
    -- Installing: /usr/local/include/workflow/Executor.h
    -- Installing: /usr/local/include/workflow/list.h
    -- Installing: /usr/local/include/workflow/mpoller.h
    -- Installing: /usr/local/include/workflow/poller.h
    -- Installing: /usr/local/include/workflow/msgqueue.h
    -- Installing: /usr/local/include/workflow/rbtree.h
    -- Installing: /usr/local/include/workflow/SubTask.h
    -- Installing: /usr/local/include/workflow/thrdpool.h
    -- Installing: /usr/local/include/workflow/IOService_linux.h
    -- Installing: /usr/local/share/doc/workflow-0.9.10/README.md
    -- Installing: /usr/local/lib/libworkflow.a
    -- Installing: /usr/local/lib/libworkflow.so
    -- Up-to-date: /usr/local/lib/libworkflow.a
    -- Installing: /usr/local/lib/cmake/workflow/workflow-targets.cmake
    -- Installing: /usr/local/lib/cmake/workflow/workflow-targets-relwithdebinfo.cmake
    make[1]: Leaving directory '/home/project/workflow/build.cmake'
    Cloning into 'wfrest'...
    -- The C compiler identification is GNU 9.3.0
    -- The CXX compiler identification is GNU 9.3.0
    -- Check for working C compiler: /usr/bin/cc
    -- Check for working C compiler: /usr/bin/cc -- works
    -- Detecting C compiler ABI info
    -- Detecting C compiler ABI info - done
    -- Detecting C compile features
    -- Detecting C compile features - done
    -- Check for working CXX compiler: /usr/bin/c++
    -- Check for working CXX compiler: /usr/bin/c++ -- works
    -- Detecting CXX compiler ABI info
    -- Detecting CXX compiler ABI info - done
    -- Detecting CXX compile features
    -- Detecting CXX compile features - done
    -- Build Type: Release
    -- Found OpenSSL: /usr/lib/aarch64-linux-gnu/libcrypto.so (found version "1.1.1f")  
    -- Found ZLIB: /usr/lib/aarch64-linux-gnu/libz.so (found version "1.2.11") 
    -- workflow exists(version >= 0.9.9), not build
    -- CXX_FLAGS = -g -std=c++11 -rdynamic -pthread -fno-exceptions -O2 -DNDEBUG
    -- lib/cmake/wfrest
    -- Configuring done
    -- Generating done
    -- Build files have been written to: /home/project/wfrest/build
    Scanning dependencies of target wfrest
    [  4%] Building CXX object wfrest/CMakeFiles/wfrest.dir/StrUtil.cc.o
    [  8%] Building CXX object wfrest/CMakeFiles/wfrest.dir/HttpMsg.cc.o
    [ 13%] Building CXX object wfrest/CMakeFiles/wfrest.dir/Router.cc.o
    [ 17%] Building CXX object wfrest/CMakeFiles/wfrest.dir/RouteTable.cc.o
    [ 21%] Building CXX object wfrest/CMakeFiles/wfrest.dir/UriUtil.cc.o
    [ 26%] Building CXX object wfrest/CMakeFiles/wfrest.dir/HttpDef.cc.o
    [ 30%] Building CXX object wfrest/CMakeFiles/wfrest.dir/HttpFile.cc.o
    [ 39%] Building C object wfrest/CMakeFiles/wfrest.dir/MultiPartParser.c.o
    [ 43%] Building CXX object wfrest/CMakeFiles/wfrest.dir/HttpContent.cc.o
    [ 47%] Building CXX object wfrest/CMakeFiles/wfrest.dir/PathUtil.cc.o
    [ 34%] Building CXX object wfrest/CMakeFiles/wfrest.dir/HttpServerTask.cc.o
    [ 52%] Building CXX object wfrest/CMakeFiles/wfrest.dir/HttpServer.cc.o
    [ 56%] Building CXX object wfrest/CMakeFiles/wfrest.dir/Timestamp.cc.o
    [ 60%] Building CXX object wfrest/CMakeFiles/wfrest.dir/SysInfo.cc.o
    [ 65%] Building CXX object wfrest/CMakeFiles/wfrest.dir/Compress.cc.o
    [ 69%] Building CXX object wfrest/CMakeFiles/wfrest.dir/BluePrint.cc.o
    [ 73%] Building CXX object wfrest/CMakeFiles/wfrest.dir/base64.cc.o
    [ 78%] Building CXX object wfrest/CMakeFiles/wfrest.dir/ErrorCode.cc.o
    [ 82%] Building CXX object wfrest/CMakeFiles/wfrest.dir/FileUtil.cc.o
    [ 91%] Building CXX object wfrest/CMakeFiles/wfrest.dir/MysqlUtil.cc.o
    [ 91%] Building CXX object wfrest/CMakeFiles/wfrest.dir/HttpCookie.cc.o
    [ 95%] Building CXX object wfrest/CMakeFiles/wfrest.dir/Aspect.cc.o
    [100%] Linking CXX static library ../lib/libwfrest.a
    [100%] Built target wfrest
    [100%] Built target wfrest
    Install the project...
    -- Install configuration: "Release"
    -- Installing: /usr/local/lib/cmake/wfrest/wfrest-config-version.cmake
    -- Installing: /usr/local/lib/cmake/wfrest/wfrest-config.cmake
    -- Installing: /usr/local/lib/libwfrest.a
    -- Installing: /usr/local/lib/cmake/wfrest/wfrest-targets.cmake
    -- Installing: /usr/local/lib/cmake/wfrest/wfrest-targets-release.cmake
    -- Installing: /usr/local/include/wfrest/AopUtil.h
    -- Installing: /usr/local/include/wfrest/Aspect.h
    -- Installing: /usr/local/include/wfrest/BluePrint.h
    -- Installing: /usr/local/include/wfrest/Compress.h
    -- Installing: /usr/local/include/wfrest/Copyable.h
    -- Installing: /usr/local/include/wfrest/ErrorCode.h
    -- Installing: /usr/local/include/wfrest/FileUtil.h
    -- Installing: /usr/local/include/wfrest/HttpContent.h
    -- Installing: /usr/local/include/wfrest/HttpCookie.h
    -- Installing: /usr/local/include/wfrest/HttpDef.h
    -- Installing: /usr/local/include/wfrest/HttpFile.h
    -- Installing: /usr/local/include/wfrest/HttpMsg.h
    -- Installing: /usr/local/include/wfrest/HttpServer.h
    -- Installing: /usr/local/include/wfrest/HttpServerTask.h
    -- Installing: /usr/local/include/wfrest/Macro.h
    -- Installing: /usr/local/include/wfrest/MultiPartParser.h
    -- Installing: /usr/local/include/wfrest/MysqlUtil.h
    -- Installing: /usr/local/include/wfrest/Noncopyable.h
    -- Installing: /usr/local/include/wfrest/PathUtil.h
    -- Installing: /usr/local/include/wfrest/RouteTable.h
    -- Installing: /usr/local/include/wfrest/Router.h
    -- Installing: /usr/local/include/wfrest/StrUtil.h
    -- Installing: /usr/local/include/wfrest/StringPiece.h
    -- Installing: /usr/local/include/wfrest/SysInfo.h
    -- Installing: /usr/local/include/wfrest/Timestamp.h
    -- Installing: /usr/local/include/wfrest/UriUtil.h
    -- Installing: /usr/local/include/wfrest/VerbHandler.h
    -- Installing: /usr/local/include/wfrest/base64.h
    -- Installing: /usr/local/include/wfrest/json.hpp
    -- Installing: /usr/local/include/wfrest/json_fwd.hpp
    -- Installing: /usr/local/include/wfrest/BluePrint.inl
    -- Installing: /usr/local/lib/cmake/wfrest/FindBrotli.cmake
    STEP 6: COMMIT wfrest
    --> 21f71b2f0a8
    Successfully tagged localhost/wfrest:latest
    21f71b2f0a8bc5d1d8c3ca6dd4b2b15093eff3f409f9ebdc7ca87848ba6719ea
    
    opened by cnmade 3
  • Bug of code in readme

    Bug of code in readme

    Please make sure that you have tested the code before put them into the README doc.

    • Such as no defined varable for abc
    • Missing semicolon

    BTW, in order to build the example you provided, there maybe need some compiler flags to be set such LD_LIBRARY_PATH, or linking specify library, such as -lworkflow.

    opened by chunyang-wen 3
  • How to install with centOS 7.X?

    How to install with centOS 7.X?

    When I make get this :

    make[3]: 进入目录“/home/gaosm/wfrest/build.cmake”
    make[3]: 离开目录“/home/gaosm/wfrest/build.cmake”
    make[3]: 进入目录“/home/gaosm/wfrest/build.cmake”
    [  4%] Building CXX object src/core/CMakeFiles/core.dir/BluePrint.cc.o
    In file included from /home/gaosm/wfrest/src/core/BluePrint.h:226:0,
                     from /home/gaosm/wfrest/src/core/BluePrint.cc:1:
    /home/gaosm/wfrest/src/core/BluePrint.inl: 在成员函数‘void wfrest::BluePrint::ROUTE(const string&, const Handler&, wfrest::Verb, const AP& ...)’中:
    /home/gaosm/wfrest/src/core/BluePrint.inl:165:31: 错误:expected ‘,’ before ‘...’ token
                 [handler, this, ap...](const HttpReq *req,
                                   ^
    /home/gaosm/wfrest/src/core/BluePrint.inl:165:31: 错误:expected identifier before ‘...’ token
    /home/gaosm/wfrest/src/core/BluePrint.inl:165:34: 错误:参数包未能在‘...’中被展开:
                 [handler, this, ap...](const HttpReq *req,
                                      ^
    /home/gaosm/wfrest/src/core/BluePrint.inl:165:34: 附注:       ‘ap’
    /home/gaosm/wfrest/src/core/BluePrint.inl: 在成员函数‘void wfrest::BluePrint::ROUTE(const string&, int, const Handler&, wfrest::Verb, const AP& ...)’中:
    /home/gaosm/wfrest/src/core/BluePrint.inl:185:49: 错误:expected ‘,’ before ‘...’ token
                 [handler, compute_queue_id, this, ap...](HttpReq *req,
                                                     ^
    /home/gaosm/wfrest/src/core/BluePrint.inl:185:49: 错误:expected identifier before ‘...’ token
    /home/gaosm/wfrest/src/core/BluePrint.inl:185:52: 错误:参数包未能在‘...’中被展开:
                 [handler, compute_queue_id, this, ap...](HttpReq *req,
                                                        ^
    /home/gaosm/wfrest/src/core/BluePrint.inl:185:52: 附注:       ‘ap’
    /home/gaosm/wfrest/src/core/BluePrint.inl: 在成员函数‘void wfrest::BluePrint::ROUTE(const string&, const SeriesHandler&, wfrest::Verb, const AP& ...)’中:
    /home/gaosm/wfrest/src/core/BluePrint.inl:305:31: 错误:expected ‘,’ before ‘...’ token
                 [handler, this, ap...](const HttpReq *req,
                                   ^
    /home/gaosm/wfrest/src/core/BluePrint.inl:305:31: 错误:expected identifier before ‘...’ token
    /home/gaosm/wfrest/src/core/BluePrint.inl:305:34: 错误:参数包未能在‘...’中被展开:
                 [handler, this, ap...](const HttpReq *req,
                                      ^
    /home/gaosm/wfrest/src/core/BluePrint.inl:305:34: 附注:       ‘ap’
    /home/gaosm/wfrest/src/core/BluePrint.inl: 在成员函数‘void wfrest::BluePrint::ROUTE(const string&, int, const SeriesHandler&, wfrest::Verb, const AP& ...)’中:
    /home/gaosm/wfrest/src/core/BluePrint.inl:326:49: 错误:expected ‘,’ before ‘...’ token
                 [handler, compute_queue_id, this, ap...](HttpReq *req,
                                                     ^
    /home/gaosm/wfrest/src/core/BluePrint.inl:326:49: 错误:expected identifier before ‘...’ token
    /home/gaosm/wfrest/src/core/BluePrint.inl:326:52: 错误:参数包未能在‘...’中被展开:
                 [handler, compute_queue_id, this, ap...](HttpReq *req,
                                                        ^
    /home/gaosm/wfrest/src/core/BluePrint.inl:326:52: 附注:       ‘ap’
    make[3]: *** [src/core/CMakeFiles/core.dir/BluePrint.cc.o] 错误 1
    make[3]: 离开目录“/home/gaosm/wfrest/build.cmake”
    make[2]: *** [src/core/CMakeFiles/core.dir/all] 错误 2
    make[2]: 离开目录“/home/gaosm/wfrest/build.cmake”
    make[1]: *** [all] 错误 2
    make[1]: 离开目录“/home/gaosm/wfrest/build.cmake”
    make: *** [all] 错误 2
    
    opened by wanesta 2
  • bug : 相同路径,动词会被覆盖

    bug : 相同路径,动词会被覆盖

    相同路径,不同动词,前面的动词会被覆盖掉,但打印路径,接收到的还是发出的动词

    具体可以看下面的例子

    svr.PUT("/account", [](const HttpReq *req, HttpResp *resp)
    {
        fprintf(stderr, "put account\n");
        resp->String("put verb");
    });
    
    svr.DELETE("/account", [](const HttpReq *req, HttpResp *resp)
    {
        fprintf(stderr, "delete account\n");
        resp->String("delete verb");
    });
    
    svr.POST("/account", [](const HttpReq *req, HttpResp *resp)
    {
        fprintf(stderr, "post account\n");
        resp->String("post verb");
    });
    

    按顺序发送PUT、DELETE、POST请求,server输出如下:

    post account
    [WFREST] 2022-04-06 13:54:23 | 200 | ip_addr | PUT | "/account" | -- 
    post account
    [WFREST] 2022-04-06 13:54:32 | 200 | ip_addr | DELETE | "/account" | -- 
    post account
    [WFREST] 2022-04-06 13:54:36 | 200 | ip_addr | POST | "/account" | --
    

    且client收到的消息均为

    post verb
    

    (英文写不好,为了表达清晰,还是用中文)

    opened by cuncinc 2
  • Plz do not install workflow automatically

    Plz do not install workflow automatically

    I think it is not good to install workflow automatically at build time.

    Try to prompt people how to install that library when it's not found.

    Or, install it in CMAKE_BUILD_DIRECTORY ( currently /usr/local ) maybe a good way.

    opened by joelcho 2
  • 长连接流媒体支持情况咨询

    长连接流媒体支持情况咨询

    目前我有一个需求场景是流媒体传输:在传输flv视频中,实现一个 http server(如下图),当有浏览器端(例如 flv.js)请求时我需要维持这个长连接,并且 http server 中有一个存放flv数据的内容队列,当有新的flv数据进入内容队列时,http server 需要即时将这些flv数据不断发送给浏览器端,以维持flv视频的不断播放,不知道 wfrest 对这个场景支不支持 http server

    就是实现一个具有 HTTP-FLV 服务器,有点类似于 nginx-http-flv-module 中的 http-flv 服务,整个场景就是会不断收到 flv 数据流维护内容队列,然后这个 http server 提供的 http-flv 服务就可以,主要就是:

    1. 维持长连接
    2. 当 flv 内容队列有新数据时即时发送给客户端

    在 workflow 也请教了这个 issue https://github.com/sogou/workflow/issues/1131#issuecomment-1368454775

    opened by EricPengShuai 2
  • authentification and authorization

    authentification and authorization

    Is it planned to add oath2.0 and openid connect support to wfrest? I'm using wfrest for a personal project and would very much like to use openid connect to secure my ip. If not: is there a addon for wfrest which implements such functionality?

    opened by iehfned 0
  • g++should >= 5.0

    g++should >= 5.0

    Discussed in https://github.com/wfrest/wfrest/discussions/74

    Originally posted by chanchann December 25, 2021 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41933

    Because in g++ 4.9 and the previous version, lambda can't capture variadic templates, we require you to upgrade your g++ version to 5.0 and above.

    documentation 
    opened by chanchann 0
Releases(v0.9.1)
  • v0.9.1(Aug 29, 2022)

    What's Changed

    • add vcpkg
    • update workflow submodule. Fix compiling problem on MacOS. by @Barenboim in https://github.com/wfrest/wfrest/pull/127

    Full Changelog: https://github.com/wfrest/wfrest/compare/v0.9.0...v0.9.1

    Source code(tar.gz)
    Source code(zip)
  • v0.9.0(Aug 6, 2022)

    What's Changed

    • feat : Basic restful api for http, mysql, redis
    • feat : Support json api
    • feat : Add Aspect of programming
    • feat: Support cn url path
    • feat: Add blueprint
    • feat: static file service
    • feat: easy to use proxy interface

    New Contributors

    • @Wkh3 made their first contribution in https://github.com/wfrest/wfrest/pull/77
    • @cnmade made their first contribution in https://github.com/wfrest/wfrest/pull/95
    • @Barenboim made their first contribution in https://github.com/wfrest/wfrest/pull/115
    • @zhanghuajieHIT made their first contribution in https://github.com/wfrest/wfrest/pull/118

    Full Changelog: https://github.com/wfrest/wfrest/commits/v0.9.0

    Source code(tar.gz)
    Source code(zip)
Owner
null
A REST API in C, yeah, C...

A REST API that fetches custom data from École 42 users, written in C. (Challenge from 42Labs) Constructed with: Mongoose Mjson Org-mode MongoDB Atlas

Henrique Rocha 3 Jun 14, 2022
🌱Light and powerful C++ web framework for highly scalable and resource-efficient web application. It's zero-dependency and easy-portable.

Oat++ News Hey, meet the new oatpp version 1.2.5! See the changelog for details. Check out the new oatpp ORM - read more here. Oat++ is a modern Web F

Oat++ 6k Jan 4, 2023
Various utilities such as WebServer, JSON, WebSocket server, REST framework

DumaisLib This is a library containing several utilities for some projects of Patrick Dumais. Previously, the libraries were all individual but it bec

Patrick Dumais 25 Feb 22, 2022
C++ library for creating an embedded Rest HTTP server (and more)

The libhttpserver reference manual Tl;dr libhttpserver is a C++ library for building high performance RESTful web servers. libhttpserver is built upon

Sebastiano Merlino 711 Dec 27, 2022
C++ client for making HTTP/REST requests

REST client for C++ About This is a simple REST client for C++. It wraps libcurl for HTTP requests. Usage restclient-cpp provides two ways of interact

Daniel Schauenberg 1.4k Dec 30, 2022
A C++ async HTTP client library to use in asynchronous applications while communicating with REST services.

libashttp An asynchronous HTTP library using Boost.ASIO as the backend. This project is licensed under: Usage Here is a example usage which is taken f

Tolga Hoşgör 53 Dec 17, 2022
Modern C++ REST Client library

Introduction to the restc-cpp C++ library The magic that takes the pain out of accessing JSON API's from C++ What it does: It formulates a HTTP reques

Jarle Aase 510 Dec 28, 2022
HTTP/HTTPS REST Client C Library

https_client HTTP/HTTPS REST Client C Library This library is a tiny https client library. it use only small memory(default read buffer size(H_READ_SI

HISONA 103 Dec 20, 2022
Mongoose Embedded Web Server Library - a multi-protocol embedded networking library with TCP/UDP, HTTP, WebSocket, MQTT built-in protocols, async DNS resolver, and non-blocking API.

Mongoose - Embedded Web Server / Embedded Networking Library Mongoose is a networking library for C/C++. It implements event-driven non-blocking APIs

Cesanta Software 9k Jan 1, 2023
An asynchronous web framework for C++ built on top of Qt

!!! I can no longer maintain this project. If you're interessed, please contact me and I can move the projetct to you !!! Tufão - an asynchronous web

Vinícius dos Santos Oliveira 556 Dec 28, 2022
Drogon: A C++14/17 based HTTP web application framework running on Linux/macOS/Unix/Windows

English | 简体中文 | 繁體中文 Overview Drogon is a C++14/17-based HTTP application framework. Drogon can be used to easily build various types of web applicat

An Tao 8.5k Jan 5, 2023
Lightweight Python Web framework

fly Python lightweight web application framework. Event driven architecture. Usable as Web server and Application server. Lightweight and fast. Since

tatsuya.s 16 Dec 11, 2022
The Telegram Bot API provides an HTTP API for creating Telegram Bots.

The Telegram Bot API provides an HTTP API for creating Telegram Bots.

Telegram Library 1.9k Jan 1, 2023
C library to create simple HTTP servers and Web Applications.

Onion http server library Travis status Coverity status Onion is a C library to create simple HTTP servers and Web Applications. master the developmen

David Moreno Montero 1.9k Dec 20, 2022
Simple, secure & standards compliant web server for the most demanding of applications

Simple, secure[1] & standards compliant[2] web server for the most demanding[3] of applications. Read more... ?? Optimized security Being meticulously

uNetworking AB 15k Dec 30, 2022
C Hypertext Library - A library for writing web applications in C

CHL C Hypertext Library - A library for writing web applications in C #include <chl/chl.h> int main() { chl_set_default_headers(); chl_print_header

null 271 Nov 14, 2022
When you need a web server in a hurry.

darkhttpd https://unix4lyfe.org/darkhttpd/ When you need a web server in a hurry. Features: Simple to set up: Single binary, no other files, no instal

Emil Mikulic 866 Jan 6, 2023
web server that will print hello world on the screen only for linux users

a simple http server side lib only for linux users Note: This lib is currently under development you can check the source code and even use it but dn'

notaweeb 11 Mar 14, 2021
Ultra-lightweight web browser based on Qt Ultralight webview, powered by Ultralight HTML renderer

Qt Ultralight Browser This is an ultra-lightweight web browser powered by the Ultralight web engine embedded in Qt 5 app as a custom webview widget -

niu tech 43 Jan 7, 2023