My results look like...
POST /post HTTP/1.1
Host: localhost:3003
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0)
Gecko/20100101 Firefox/62.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:3003/profile
Content-type: multipart/form-data
Content-Length: 14708
Cookie: mycookie=7bdbed41954cd4133a172acb92988e58
Connection: keep-alive
-----------------------------4636945214860352321751082034
...
binary characters...
...
-----------------------------4636945214860352321751082034
Acquired from
boost::asio::async_read(
socket_,
strmbuffer_,
boost::asio::transfer_exactly(bytes_to_transfer),
strand_.wrap(
[this, self](boost::system::error_code ec, std::size_t bytes_transferred)
{
std::stringstream ss;
ss << buffer_data; // from socket_.async_read_some()
ss << &strmbuffer_; // now stringstream contains everything
// the character routine which writes the above
// and which i use for output...
std::string output_file = "../../upload/test.png";
std::ofstream outfile(output_file);
char c;
unsigned bl = boundary.length();
bool endfile = false;
unsigned bufsize = 512;
if(outfile){
char buffer[bufsize];
while(!endfile){
// here looks like below
// to find and pass the first boundary
} // then stream continues...
while(!endfile){
unsigned j = 0;
unsigned k;
memset(buffer, 0, bufsize); // redundant
while(j < bufsize && ss.get(c) && !endfile){
buffer[j] = c;
k = 0;
while(boundary[bl - 1 - k] == buffer[j - k]){
if(k >= bl - 1){
endfile = true;
break;
}
k++;
}
j++;
}
outfile.write(buffer, j);
j = 0;
}
}
}
);
...essentially. Thus, the receiving
socket_.async_read_some()
gives me a
boost::array<char, 8192> buffer_;
which gives me the http request info. But in the case of multipart/form-data, it reads passed the first boundary, which means the next read() doesn't see it. Argh! (So does async_read_until().) So, in
boost::asio::async_read()
i convert the
boost::asio::streambuf strmbuffer_;
to a stringstream and add them together for the std::cout results above.
I'm not convinced that I should be using stringstream, at all. But the above routine (using stringstream) works fine in Boost::Beast. It does NOT in Asio. Unfortunately, the string_body type, which receives the http request in Beast, has a restrictive size limit, 1 meg, i believe. No idea how to change that.
I can't find much on this topic, anywhere. Perhaps, the information is too dangerous. If they told me, they'd have to kill me. What should I be using in Asio to write binary data to disk??
By default, the HTTP request parser starts with a 1 megabyte limit. This is to prevent resource exhaustion attacks where the client sends very large or endless amounts of body data. You can easily change this limit by calling
parser::body_limit
with the desired maximum. This is described in the documentation:https://www.boost.org/doc/libs/1_68_0/libs/beast/doc/html/beast/ref/boost__beast__http__parser/body_limit.html https://www.boost.org/doc/libs/1_68_0/libs/beast/doc/html/beast/using_http/buffer_oriented_parsing.html
In order to adjust parser parameters such as the body limit (or header limit) you will need to use the "parser stream operation" interface. This is explained here:
https://www.boost.org/doc/libs/1_68_0/libs/beast/doc/html/beast/using_http/parser_stream_operations.html