On Fri, Sep 30, 2016 at 10:34 AM, Christof Donat
I'm proposing that there is a server layer that is even lower than the items listed above.
So that would be between the low level HTTP stuff and the request router.
Right. My approach is to work from the bottom up, since the number of degrees of freedom with respect to designing an interface increases as you go to higher levels (some would disagree with that statement). No one can dispute that an HTTP application needs to send and receive HTTP messages (the lowest level). But there would be debate on how to handle cookies or how they should be persisted (high level functions). Once you have read/write HTTP message primitives available, then on the server side the next logical step up is to have a low-level server framework.
We could try define a kind of concept for the session store and the session objects, so that the session could also be persistent on disk
Oops, I think perhaps I miscommunicated. When I say session, I mean it in the lowest level sense. Pretty much the boost::asio::ip::tcp::socket and a few state variables (such as a reference to the server, and a reference to the acceptor). I wasn't talking about a high level HTTP session such as persistent data that survives an individual TCP/IP connection. If it seems that I'm trying to steer the discussion towards more low-level concepts, well... I am :) For me to get from point A (Beast's interfaces) to point B (what real users want, such as a robust client or server template) I think of small steps that build on what's already there.
One important thing, I think is, that we should also be able to have no session tracking at all without having to pay for that
I agree with the general principle of "pay for what you use."
So am I correct to assume, that the idea is to have a more or less arbitrary body object.
I'm not exactly sure what you mean by an arbitrary body object.
In the end that will have to serialized to a string of bytes.
Yes, in order for an HTTP message instantiated with a specified Body type to be Serializable, the Body must provide the nested type which meets the requirements of Writer: http://vinniefalco.github.io/beast/beast/ref/Writer.html
Did you intend to have that implemented in the body object?
If I understand your question correctly, yes the Body type provides both the container used to represent the body (this becomes a data member in the message object) and the algorithms used to serialize and parse the body. The choice of container is entirely up to you and doesn't need to actually hold the data. In the Beast HTTP server example, the file_body uses a std::string representing the path to the file: https://github.com/vinniefalco/Beast/blob/70b8555cdca69b9c5777db02115d30d1c1... https://github.com/vinniefalco/Beast/blob/70b8555cdca69b9c5777db02115d30d1c1...
My current idea was to call the template inside the handler and write the result to the body.
If you're serving a static file and anticipate that there will be large files, I think you will get better results if you implement your own custom Body type. Remember that the calculation of HTTP responses happens on an io_service thread. Things work better if you block on O(1) instead of O(n). So rather than reading in the entire file into memory when building the response, its better to just send fixed size pieces of the file from a custom writer. This also consumes less memory, allowing the server to scale to more connections with the same amount of resources. The Beast file_body sends in chunks of 4K: https://github.com/vinniefalco/Beast/blob/70b8555cdca69b9c5777db02115d30d1c1...
I think, the router can be made to handle different return types
I don't know about that...I wouldn't use the return value.
I also have some thoughts to make it more flexible on the parameters. For some handlers you'll be happy to just get the URL match, others will maybe need a stream for websocket interaction. I think, that can be achieved using boost call traits, std::result_of, std::is_callable, or similar things, and a little bit of not too difficult meta programming magic.
A code sample would greatly help in visualizing these ideas!
Another approach, instead of using the return type, is to give the handler an object which when invoked with a message, queues or sends the message. ... I also thought about that. For the time being, I chose to return the response object for semantic reasons. For me that is the result of the operation. With the approach of passing in a kind of response object, the operation would, as a side effect, respond to the request, and return something else, like an error code, or even void.
Adhering to language "purity" certainly has its merits but when building general purpose code I think we need to consider all the possibilities. For returning the http::response_v1, using the indirect interface I described above will result in smaller, easier to understand code. Creating a system where functions return response objects of different types (varying by their Body parameter) only creates complexity for calling code. And the only advantage is that it is emotionally satisfying - this will be hard to justify to users of the library. For error_code, passing it as a non-const reference is a clear winner. If you use error_code as the return value you are paying for a default construction in every function on the call chain.