Bugfix in HttpResponse

string_views are potentially wrong if raw is very small
and stdlib has small string optimisation. Use unique_ptr
instead to force allocations in all cases.
This commit is contained in:
King_DuckZ 2020-09-03 00:55:16 +01:00
parent 5342185370
commit 99d577f43a
2 changed files with 35 additions and 9 deletions

View file

@ -17,7 +17,7 @@
#pragma once
#include <string>
#include <memory>
#include <string_view>
#include <vector>
#include <utility>
@ -25,7 +25,7 @@
namespace nap {
struct HttpResponse {
std::string raw;
std::unique_ptr<char[]> raw;
std::vector<std::pair<std::string_view, std::string_view>> header;
std::string_view body;
std::string_view http_ver;

View file

@ -24,6 +24,7 @@
#include <sstream>
#include <algorithm>
#include <cassert>
#include <tuple>
namespace nap {
namespace {
@ -35,6 +36,29 @@ namespace {
return std::equal(protocol, protocol + protocolLen, parUrl.begin());
}
std::tuple<std::unique_ptr<char[]>, std::string_view, std::string_view> make_raw_string (
const std::ostringstream& head,
const std::ostringstream& body
) {
//TODO: use .view() with c++20
auto head_str = head.str();
auto body_str = body.str();
const std::size_t size = head_str.size() + 1 + body_str.size();
auto ret = std::make_unique<char[]>(size);
std::copy(head_str.begin(), head_str.end(), ret.get());
ret[head_str.size()] = '\n';
std::copy(body_str.begin(), body_str.end(), ret.get() + head_str.size() + 1);
const char* const buff = ret.get();
return std::make_tuple(
std::move(ret),
std::string_view(buff, head_str.size()),
std::string_view(buff + head_str.size() + 1, body_str.size())
);
}
} //unnamed namespace
HttpResponse page_fetch (
@ -73,14 +97,16 @@ HttpResponse page_fetch (
HttpResponse resp;
resp.code = easy.get_info<CURLINFO_RESPONSE_CODE>().get();
resp.raw = header_oss.str();
resp.raw += "\n";
const std::size_t body_start = resp.raw.size();
resp.raw += body_oss.str();
std::string_view raw_view(resp.raw);
resp.body = raw_view.substr(body_start);
auto parsed_header = header_parse(raw_view.substr(0, body_start));
std::string_view head;
{
auto [raw, head_tmp, body] = make_raw_string(header_oss, body_oss);
head = head_tmp;
resp.raw = std::move(raw);
resp.body = body;
}
auto parsed_header = header_parse(head);
resp.header = std::move(parsed_header.fields);
assert(resp.code == parsed_header.code);
resp.http_ver = parsed_header.version;