Hi, Am 29.09.2016 03:06, schrieb Vinnie Falco:
I don't think a synchronous interface is necessary.
Probably true. A synchronous interface would require a redundant code path.
I second that.
I'd be happy to work with you on creating a proposed higher level interface that I think would stand a chance at WG21. It may improve consensus for the Boost review, but if it has the opposite effect we could just rip it out. What do you think?
There's a lot of merit to a team effort for building a good design. However, I'm not sure that I want to broaden the scope of Beast's current interfaces.
I agree, that there is much value in having one library for the low level stuff, which beast is very well suited. I also agree, that higher level APIs should be built on top of that instead of putting everything in the same project.
With respect to a high level client interface, [...] The cool thing about this, is that someone has already created such an interface. It is Huu Nguyen, the author of "C++ Requests: Curl for People". And the repository is here: https://github.com/whoshuu/cpr [...] I reached out to the author and he related to me that his ambition is to iterate on this library to produce a version that does not have curl as a dependency. I think the most productive use of development energies with respect to building a high level HTTP client would go towards supporting the refinement of this library, or if the author does not have the resources then to examine his interface and use it as a model for creating such a library (using Beast for the protocol level support).
Really great.
On the subject of a turn-key generic HTTP server I think there are more possibilities that I could put something together. [...]
I think frameworks for HTTP Servers should be separated in various parts: 1. Low Level HTTP stuff - that is what beast is perfect for 2. A Request Router 3. A Database Access Layer - most Web applications are good off to use a database 4. A way to create the HTML output without mixing it with the code For 3 and 4 I'd propose Roland Bocks sqlpp11 (https://github.com/rbock/sqlpp11) and kiss-templates (https://github.com/rbock/kiss-templates) So some weeks ago I started a request router as hobby project based on beast v1. It does not even remotely work yet and of course the interface is not at all fixed now. As usuall hobby projects might get a lot of love, but never enough time, so the advance is very slow at the moment. The routing looks like this: auto appRoute = route_url(route("^/foo/([0-9]+)"s, app::foo{url_match_cast<int>{"$1"s}}), route("^/bar/([a-fA-F0-9]*)"s, app::bar{url_match_caststd::string{"$1"s}}), route("^/baz/([0-9]*([.][0-9]+)?)", app::baz{url_match_cast<double>{"$1"}})); auto r = route_url(route("^/oldAppBase(.*)$"s, redirect("/newAppBase$1"s)), route("^/newAppBase(.*)$"s, appRoute("$1"s)), route("^/webSockets(.*)$"s, sockHandler{"$1"s}), route("^/otherWebSockets(.*)$"s, otherSockHandler{"$1"s}), route("^/static(.*)$"s, static_file_handler{boost::filesystem::current_path(), "$1"s})); The idea here is, that you can create independent components, like "appRoute", and mount them together to build a complete application. The Components themself can be build with multiple handlers, that can be components themselves as well. This is inspired by Django. The handlers might look like this: namespace app { class foo: public base_http_handler<foo> { using base_http_handler<foo>::operator(); url_match_cast<int> get_foo_; public: foo(const url_match_cast<int>& get_foo): get_foo_{get_foo} {}; template<typename Request> beast::http::response_v1beast::http::string_body operator () (const std::smatch& match, const Request& req) { auto resp = beast::http::response_v1beast::http::string_body{}; resp.status = 200; resp.reason = beast::http::reason_string(200); resp.headers.replace("Content-Type", "text/html"); auto foo_text = boost::lexical_caststd::string(get_foo_(match)); resp.body = "<html><head><title>foo: "s + foo_text + "</title></head><body>foo: "s + foo_text + "</body></html>"s; resp.headers.replace("Content-Length", resp.body.size()); return resp; }; }; } But they can also just be lambdas with the signature like this call operator. With generalized captures, this could also be writen as: route("^/foo/([0-9]+)"s, [get_foo_=url_match_cast<int>{"$1"s}] (const std::smatch& match, const Request& req) -> beast::http::response_v1beast::http::string_body operator () { // ... auto foo = get_foo_(match); // ... }) The parameter match is the match of the regular expression on the path. With get_foo_(match) we get the first parameter ("$1") from that match as an integer (url_match_cast<int>). I think, the main loop should not be part of the framework. My current idea would look like to use std::futureboost::system::error_code as return type for the call operator of a rout_url: std::futureboost::system::error_code success_async = r(url, req, my_socket); What do you think about such an interface? Christof