Boost logo

Boost :

Subject: Re: [boost] [beast] Request for Discussion
From: Vinnie Falco (vinnie.falco_at_[hidden])
Date: 2016-09-28 21:06:06


On Wed, Sep 28, 2016 at 8:39 PM, David Sankel <camior_at_[hidden]> wrote:
> Your investigation into creating a higher level interface, despite your own
> reluctance to do so, is very much appreciated.

Thanks!

> I think that the io_service object should not be hidden with a
> higher-level interface.

Yep, and that's a mistake that websocketpp made. For both a client and
a server, it should be possible for:

1. The caller to provide an io_service with its own threads if they want

2. A choice of using an implicit strand: just one thread in the
io_service pool), or an explicit strand (e.g. io_service::strand
wrapper equivalent).

3.Some struct tag or construction option that provides an io_service
with some reasonable default threading policy, so the caller doesn't
have to bother with it at all.

> I don't think a synchronous interface is necessary.

Probably true. A synchronous interface would require a redundant code path.

> 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. Other individuals have tried to create these high
level interfaces, and they have all failed review. There was a recent
claim in the mailing list that some individual could have written a
high quality HTTP client if they wanted to - then why didn't they?
We've certainly gone long enough without basic HTTP functionality
available with a sensible interface. I think Beast has a better chance
if it keeps its scope limited to just the low level protocol. Despite
this limited scope, it still provides a useful building block - and
one that we need.

With respect to a high level client interface, I have to be honest,
reading the Python Requests documentation really spoiled me. In a way,
its a good thing because I now realize that my own individual effort
and resources at producing a client would fall far short of Python
Requests - so I'm not wasting any of my energy on that anymore. When I
imagine what the most awesome C++ HTTP client library could look like,
it looks like Python Requests.

I don't think we should reinvent the wheel here, when some folks have
already done most of the heavy lifting for us. A C++, full featured
HTTP client implementation should be closely modeled after Python
Requests. 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).

On the subject of a turn-key generic HTTP server I think there are
more possibilities that I could put something together. We have a use
case for it at Ripple, and the amount of work to write a server is far
less than writing a full featured client. One caveat, when I talk
about writing a server I am talking about a low level server. I don't
have the knowledge or resources to include features like server side
multi-part encoding, cookie jars, redirection, caching of local
content, authentication, etc... I am talking about a server class
template which lets you write something like this:

struct handler
{
    template<class Body, class Headers>
    response_v1<string_body>
    operator()(request_v1<Body, Headers> const& req)
    {
       // your code here
    }
};

int main()
{
    using beast::http;

    beast::http::async_server<handler> s{"0.0.0.0", 80};

    // Block until SIGINT or SIGTERM is received.
    sig_wait();
}

Like the current Beast interfaces, this would be a low level server.
it manages the connections, correctly handles exiting the app cleanly,
reads the HTTP requests and buffers the responses. But that's it, the
rest is up to the caller. I imagine we would have the same debate
about low level versus high level server interface, and my answer
would be that someone can use this generic server as a building block
to add components to it and make it more full featured. For example by
writing a cgi module, or adding a file serving handler, etc..

I've already started some of this work but there are some design
issues that I haven't solved yet (I'm open to suggestions):

https://github.com/vinniefalco/Beast/blob/6f794e80fd4fad3a4777e68f7fc732ecbbdb94e7/extras/beast/http/async_server.hpp#L84.

I think conversations about these subjects are a good idea, thanks for
bringing it to the list.

Regards


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk