Need help with BeastHttp?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

0xdead4ead
226 Stars 27 Forks BSD 2-Clause "Simplified" License 380 Commits 16 Opened issues

Description

Provides helper tools for creating RESTful services using Boost.Beast

Services available

!
?

Need anything else?

Contributors list

# 187,010
asio
cpp11
cpp17
constex...
354 commits
# 563,888
C++
asio
cpp11
cpp14
7 commits
# 88,498
iOS
Node.js
frida
cpp11
2 commits
# 724,606
C++
asio
cpp11
cpp14
1 commit

SYNOPSIS license build badge.cpp

Easy HTTP (Header-only) library implemented using minimum C++11 and Boost.Beast. Allows you to get or provide REST resources available from an application in C ++. Use all the features of the Boost.Beast when constructing queries and answers.

FEATURES

  • HTTP 1.0 / 1.1
  • TLS/SSL
  • Pipeline request
  • Used I/O multiplexing model (Asio library implementation)
  • Timer manage (default action: Closing connection)
  • Server-Sent Events
  • Simple way to dynamic add REST resources using regex for path, and anonymous functions
  • Support accepted plain and SSL session on the same port

DEPENDENCIES

USAGE

More examples is

here...
The following notes show the standard syntax for setting up routes and starting a server!

Alias's represent instances of default classes for reactive (select/epool) design.

    using namespace _0xdead4ead;
    namespace beast = boost::beast;

using http_session = http::reactor::_default::session_type;
using http_listener = http::reactor::_default::listener_type;

Creating a new callback functions storage and route path for GET request with "/" resource:

    static const std::regex::flag_type regex_flags = std::regex::ECMAScript;

http::basic_router<http_session> router{regex_flags};

router.get("^/$", [](auto beast_http_request, auto context) {
    context.send(make_200<:http::string_body>(beast_http_request, "Main page\n", "text/html"));
});

router.all("^.*$", [](auto beast_http_request, auto context) {
    context.send(make_404<:http::string_body>(beast_http_request, "Resource is not found\n", "text/html"));
});

// or so ...

using http::literals::operator""_get;

"^/$"_get.advance(router, [](auto beast_http_request, auto context) {
    // as above...
});

"^.*$"_all.advance(router, [](auto beast_http_request, auto context) {
    // as above...
});

</:http::string_body></:http::string_body>

It is possible to add multiple handlers for one route. For movement on them

std::next
or
std::advance
is used:
    router.get("^/a/b$",
       [](auto /*beast_http_request*/, auto /*context*/, auto iterator){
        // process /a
        std::next(iterator)();
    }, [](auto /*beast_http_request*/, auto /*context*/){
        // process /b
    });

Getting a parameter from a URI. Request send example

curl localhost --request 'GET' --request-target '/user/param?y=1992'
:
    using pack = http::param::pack;

router.param<pack>().get("^/user/param[?]y=(\\d+)$",
   [](auto /*beast_http_request*/, auto /*context*/, auto args){
    assert(std::get&lt;0&gt;(args) == 1992);
});

// or

router.param<pack>().get("^/user/param[?]y=(\\d+)$",
   [](auto /*beast_http_request*/, auto /*context*/, auto iterator, auto /*args*/){
    // process /user
    std::next(iterator)();
}, [](auto /*beast_http_request*/, auto /*context*/, auto args){
    // process /param
    assert(std::get&lt;0&gt;(args) == 1992);
});

Getting a parameter using a string literal (as above) :

    // For value f'n is required c++14
    using http::literals::value;
    using http::literals::operator""_c;

auto param = router.param<pack>();

"^/user/param[?]y=(\\d+)$"_get.advance(std::move(param),
   [](auto /*beast_http_request*/, auto /*context*/, auto args){
    assert(value(args, 0_c) == 1992);
});

Create modular, mounted route handlers:

    http::basic_router animals{regex_flags};

animals.get("^/cat$", [](auto beast_http_request, auto context){ // '/animals/cat'
    context.send(make_200<:http::string_body>(beast_http_request, "me-ow\n", "text/html"));
});

animals.get("^/dog$", [](auto beast_http_request, auto context){ // '/animals/dog'
    context.send(make_200<:http::string_body>(beast_http_request, "aw! aw! Rrrrr\n", "text/html"));
});

animals.get("^/mouse$", [](auto beast_http_request, auto context){ // '/animals/mouse'
    context.send(make_200<:http::string_body>(beast_http_request, "...\n", "text/html"));
});

animals.get("^[/]??$", [](auto beast_http_request, auto context){ // '/animals' or '/animals/'
    context.send(make_200<:http::string_body>(beast_http_request, "animals home page\n", "text/html"));
});

router.use("^/animals$", animals);

</:http::string_body></:http::string_body></:http::string_body></:http::string_body>

Create handlers routes, forming a chain, for the route path:

    http::chain_router books{regex_flags};

books.route("^/book$")
        .get([](auto beast_http_request, auto context) {
    context.send(make_200<:http::string_body>(beast_http_request, "get a random book\n", "text/html"));
})
        .post([](auto beast_http_request, auto context) {
    context.send(make_200<:http::string_body>(beast_http_request, "add a book\n", "text/html"));
})
        .put([](auto beast_http_request, auto context) {
    context.send(make_200<:http::string_body>(beast_http_request, "update the book\n", "text/html"));
});

router.use("^/books$", books);

</:http::string_body></:http::string_body></:http::string_body>

Start listening on 0.0.0.0:8080

    // global namespace
    static boost::asio::io_context ioc;
    static boost::asio::posix::stream_descriptor out{ioc, ::dup(STDERR_FILENO)};
    //

const auto&amp; onError = [](auto system_error_code, auto from){
    http::out::pushn<:ostream>(
                out, "From:", from, "Info:", system_error_code.message());
};

const auto&amp; onAccept = [&amp;](auto asio_socket){
    auto endpoint = asio_socket.remote_endpoint();

    http::out::prefix::version::time::pushn<:ostream>(
                out, endpoint.address().to_string() + ':' + std::to_string(endpoint.port()), "connected!");

    http_session::recv(std::move(asio_socket), router, onError);
};

auto const address = boost::asio::ip::address_v4::any();
auto const port = static_cast<unsigned short>(8080);

http_listener::launch(ioc, {address, port}, onAccept, onError);

</:ostream></:ostream>

Run the I/O service on the requested number of threads:

    std::thread t{[](){
        ioc.run();
    }};

// do other work...

t.join();

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.