Implement ApiNap::ping()

This commit is contained in:
King_DuckZ 2020-09-03 01:59:33 +01:00
parent 99d577f43a
commit 3ff82985c9
8 changed files with 73 additions and 12 deletions

View file

@ -39,18 +39,20 @@ namespace {
std::tuple<std::unique_ptr<char[]>, std::string_view, std::string_view> make_raw_string (
const std::ostringstream& head,
const std::ostringstream& body
const std::ostringstream& body,
std::size_t body_padding
) {
//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();
const std::size_t size = head_str.size() + 1 + body_str.size() + body_padding;
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);
std::fill(ret.get() + size - body_padding, ret.get() + size, ' ');
const char* const buff = ret.get();
return std::make_tuple(
@ -64,7 +66,8 @@ namespace {
HttpResponse page_fetch (
const std::string& url,
const std::string& user_agent,
const PageFetchHeaders& headers
const PageFetchHeaders& headers,
std::size_t body_padding
) {
using curl::curl_pair;
@ -100,7 +103,7 @@ HttpResponse page_fetch (
std::string_view head;
{
auto [raw, head_tmp, body] = make_raw_string(header_oss, body_oss);
auto [raw, head_tmp, body] = make_raw_string(header_oss, body_oss, body_padding);
head = head_tmp;
resp.raw = std::move(raw);
resp.body = body;

View file

@ -21,6 +21,7 @@
#include <string_view>
#include <string>
#include <vector>
#include <cstddef>
namespace nap {
@ -29,7 +30,8 @@ typedef std::vector<std::string> PageFetchHeaders;
HttpResponse page_fetch (
const std::string& url,
const std::string& user_agent,
const PageFetchHeaders& headers
const PageFetchHeaders& headers,
std::size_t body_padding
);
} //namespace nap

View file

@ -21,6 +21,11 @@
namespace nap {
QuickRest::QuickRest (std::size_t body_padding) :
m_body_padding(body_padding)
{
}
void QuickRest::add_headers (std::initializer_list<HeaderPairView> headers) {
m_header_lines.reserve(m_header_lines.size() + headers.size());
@ -39,6 +44,6 @@ void QuickRest::set_user_agent (std::string&& name) {
}
HttpResponse QuickRest::fetch (std::string_view url) {
return page_fetch(std::string(url), m_user_agent, m_header_lines);
return page_fetch(std::string(url), m_user_agent, m_header_lines, m_body_padding);
}
} //namespace nap

View file

@ -24,6 +24,7 @@
#include <initializer_list>
#include <vector>
#include <utility>
#include <cstddef>
namespace nap {
@ -31,7 +32,7 @@ class QuickRest {
public:
typedef std::pair<std::string_view, std::string_view> HeaderPairView;
QuickRest() = default;
explicit QuickRest(std::size_t body_padding=0);
void add_headers (std::initializer_list<HeaderPairView> headers);
void set_user_agent (std::string&& name);
@ -40,6 +41,7 @@ public:
private:
std::string m_user_agent;
std::vector<std::string> m_header_lines;
std::size_t m_body_padding;
};
} //namespace nap

View file

@ -17,9 +17,35 @@
#include "private/api_nap.hpp"
#include "private/v1_endpoints.hpp"
#include "private/dateconv.hpp"
#include "duckhandy/int_conv.hpp"
namespace oro {
namespace {
Header to_header (const nap::HttpResponse& resp) {
using dhandy::int_conv;
Header ret;
for (const auto& entry : resp.header) {
if (entry.first == "Date")
ret.date = from_header_timestamp(entry.second);
else if (entry.first == "X-RateLimit-Limit")
ret.rate_limit = int_conv<decltype(ret.rate_limit)>(entry.second);
else if (entry.first == "X-RateLimit-Remaining")
ret.rate_limit_remaining = int_conv<decltype(ret.rate_limit_remaining)>(entry.second);
else if (entry.first == "X-RateLimit-Reset")
ret.rate_limit_reset = int_conv<decltype(ret.rate_limit_reset)>(entry.second);
else if (entry.first == "Retry-After")
ret.retry_after = int_conv<decltype(ret.retry_after)>(entry.second);
else if (entry.first == "Server")
ret.server = std::string(entry.second);
}
return ret;
}
} //unnamed namespace
ApiNap::ApiNap (
std::string&& root_address,
std::string&& api_key,
@ -27,7 +53,7 @@ ApiNap::ApiNap (
std::string&& client_purpose
) :
Api(std::move(root_address), std::move(api_key), std::move(client_name), std::move(client_purpose)),
m_qrest()
m_qrest(simdjson::SIMDJSON_PADDING)
{
m_qrest.add_headers({
{"X-Client", m_client_name},
@ -40,8 +66,22 @@ ApiNap::ApiNap (
ApiNap::~ApiNap() noexcept = default;
std::pair<Header, Ping> ApiNap::ping() {
m_qrest.fetch(m_prefix + g_endpoint_ping);
//std::cout << nap::page_fetch(url, client_name).body << '\n';
auto resp = m_qrest.fetch(m_prefix + g_endpoint_ping);
Ping dataret;
{
std::unique_lock lock(m_json_mutex);
simdjson::dom::element doc = m_json.parse(
reinterpret_cast<const uint8_t*>(resp.body.data()),
resp.body.size()
);
dataret.message = doc["message"];
dataret.generation_timestamp = std::string(doc["generation_timestamp"]);
dataret.version = static_cast<int>(int64_t(doc["version"]));
}
return {to_header(resp), std::move(dataret)};
}
std::pair<Header, WhoAmI> ApiNap::who_am_i() {

View file

@ -19,6 +19,7 @@
#include "oro/api.hpp"
#include "nap/quick_rest.hpp"
#include <mutex>
namespace oro {
@ -41,6 +42,8 @@ public:
virtual std::pair<Header, Creators> fame_list() override;
private:
std::mutex m_json_mutex;
simdjson::dom::parser m_json;
nap::QuickRest m_qrest;
};

View file

@ -32,8 +32,8 @@ namespace {
}
};
Timestamp to_timestamp (const char* fmt, const std::string& str) {
std::istringstream iss(str);
Timestamp to_timestamp (const char* fmt, std::string_view str) {
std::istringstream iss{std::string(str)};
Timestamp ts;
date::from_stream(iss, fmt, ts.ts);
return ts;
@ -57,6 +57,10 @@ Timestamp from_json_timestamp (const std::string& str) {
}
Timestamp from_header_timestamp (const std::string& str) {
return from_header_timestamp(std::string_view(str));
}
Timestamp from_header_timestamp (std::string_view str) {
UniqueLocale loc(std::setlocale(LC_TIME, "POSIX"));
//date has this format: Fri, 19 Jun 2020 22:33:43 GMT
return to_timestamp("%a, %d %b %Y %T %Z", str);

View file

@ -19,9 +19,11 @@
#include "oro/datatypes.hpp"
#include <string>
#include <string_view>
namespace oro {
Timestamp from_json_timestamp (const std::string& str);
Timestamp from_header_timestamp (std::string_view str);
Timestamp from_header_timestamp (const std::string& str);
Timestamp from_sqlite_timestamp (const std::string& str);
std::string to_sqlite_string (const Timestamp& ts);