Am 02.07.2017 um 02:22 schrieb Vinnie Falco via Boost:
* Similarly, as a user I'd prefer not to have string_body as a distinct
type (unless it's a convenience typedef for dynamic_bodystd::string). If
std::string is not a model of DynamicBuffer, I think DynamicBuffer could
stand a slight reformulation.
std::string does not model DynamicBuffer, which itself is a Net-TS
concept and thus immutable from Beast's perspective. Therefore
beast::http::basic_dynamic_body cannot work with std::string and
beast::http::string_body becomes necessary . I will likely add
beast::http::basic_string_body to allow the allocator to be
customized.
As a user I'd prefer not to have string_body as a distinct type too.
Same for string_view_body. Both are tightly bounded to distinct types.
Instead of having more and more body types tightly bounded to distinct
types i would prefer less body types loosely bounded to concepts.
So with a concept of "character sequence" we could introduce a
"sequence_body" working with models like std::string, std::string_view,
boost::string_ref, std::vector<char>, etc.
And with a concept of "character stream" we could introduce a
"stream_body" working with models like std::[o|i]stringstream,
std::[o|i]fstream, boost::iostreams::stream, etc.
These two new body types could replace string_body, string_view_body,
const_body (from example/common) and mutable_body (from example/common).
So we end up with less body types and less redundance, but much more
flexibility and testability.
Sample code for using these new body types below.
What do other participants think about this concept based body design?
Thanks,
Mike...
#include
#include
#include
#include <iostream>
#include <fstream>
#include <sstream>
#include "sequence_body.hpp"
#include "stream_body.hpp"
inline constexpr auto host = "httpbin.org";
void sequence_body_demo(boost::asio::ip::tcp::socket& socket,
beast::flat_buffer& buffer)
{
using string_view_body = beast::http::sequence_bodystd::string_view;
using string_body = beast::http::sequence_bodystd::string;
beast::http::request request;
request.method(beast::http::verb::post);
request.target("/post");
request.set(beast::http::field::host, host);
request.set(beast::http::field::content_length, 3);
request.body = "foo";
beast::http::write(socket, request);
beast::http::response response;
beast::http::read(socket, buffer, response);
std::cout << response.body << std::endl;
}
void stream_body_demo(boost::asio::ip::tcp::socket& socket,
beast::flat_buffer& buffer)
{
using ifstream_body = beast::http::stream_bodystd::ifstream;
using osstream_body = beast::http::stream_bodystd::ostringstream;
beast::http::request request;
request.method(beast::http::verb::post);
request.target("/post");
request.set(beast::http::field::host, host);
request.set(beast::http::field::content_length, 3); // chunked does
not work, httpbin needs content_length
request.body.open("foo.txt");
beast::http::write(socket, request);
beast::http::response response;
beast::http::read(socket, buffer, response);
std::cout << response.body.str() << std::endl;
}
int main()
{
try
{
boost::asio::io_service service;
boost::asio::ip::tcp::socket socket {service};
boost::asio::ip::tcp::resolver resolver {service};
boost::asio::connect(socket, resolver.resolve({host, "http"}));
beast::flat_buffer buffer;
sequence_body_demo(socket, buffer);
stream_body_demo(socket, buffer);
}
catch (std::exception const& exception)
{
std::cerr << "error: " << exception.what() << std::endl;
}
return 0;
}
==>
{
"args": {},
"data": "foo",
"files": {},
"form": {},
"headers": {
"Connection": "close",
"Content-Length": "3",
"Host": "httpbin.org"
},
"json": null,
"origin": "46.59.255.80",
"url": "http://httpbin.org/post"
}
{
"args": {},
"data": "foo",
"files": {},
"form": {},
"headers": {
"Connection": "close",
"Content-Length": "3",
"Host": "httpbin.org"
},
"json": null,
"origin": "46.59.255.80",
"url": "http://httpbin.org/post"
}