Giving code some initial structure
This commit is contained in:
parent
e0611ec6ff
commit
96e35a5814
7 changed files with 194 additions and 57 deletions
67
src/main.cpp
67
src/main.cpp
|
@ -1,63 +1,16 @@
|
||||||
#define HAS_UNCAUGHT_EXCEPTIONS 1
|
#include "oro/api.hpp"
|
||||||
|
|
||||||
#include <restc-cpp/restc-cpp.h>
|
|
||||||
#include <restc-cpp/RequestBuilder.h>
|
|
||||||
#include <string>
|
|
||||||
#include <boost/fusion/adapted.hpp>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "date/date.h"
|
|
||||||
|
|
||||||
namespace rc = restc_cpp;
|
|
||||||
|
|
||||||
namespace oro {
|
|
||||||
typedef date::sys_time<std::chrono::microseconds> timestamp_t;
|
|
||||||
|
|
||||||
struct Timestamp {
|
|
||||||
Timestamp& operator= (const std::string& str) {
|
|
||||||
std::istringstream iss(str);
|
|
||||||
date::from_stream(iss, "%FT%T%Ez", ts);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
timestamp_t ts;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Ping {
|
|
||||||
Timestamp generation_timestamp;
|
|
||||||
std::string message;
|
|
||||||
int version;
|
|
||||||
};
|
|
||||||
} //namespace oro
|
|
||||||
|
|
||||||
BOOST_FUSION_ADAPT_STRUCT(
|
|
||||||
oro::Ping,
|
|
||||||
(oro::Timestamp, generation_timestamp)
|
|
||||||
(std::string, message)
|
|
||||||
(int, version)
|
|
||||||
)
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
using date::operator<<;
|
oro::Api oro_api("https://api.originsro.org", "RESTC_CPP", "Testing");
|
||||||
|
auto ping = oro_api.ping();
|
||||||
|
|
||||||
auto rest_client = rc::RestClient::Create();
|
std::cout << "rate limit: " << ping.first.rate_limit << '\n';
|
||||||
oro::Ping ping = rest_client->ProcessWithPromiseT<oro::Ping>([&](rc::Context& ctx) {
|
std::cout << "remaining: " << ping.first.rate_limit_remaining << '\n';
|
||||||
oro::Ping ping;
|
std::cout << "reset: " << ping.first.rate_limit_reset << '\n';
|
||||||
std::unique_ptr<rc::Reply> reply = rc::RequestBuilder(ctx)
|
std::cout << "retry after: " << ping.first.retry_after << '\n';
|
||||||
.Get("https://api.originsro.org/api/v1/ping")
|
std::cout << "server: " << ping.first.server << '\n';
|
||||||
.Header("X-Client", "RESTC_CPP")
|
std::cout << "answer: " << ping.second.message << '\n';
|
||||||
.Header("X-Client-Purpose", "Testing")
|
std::cout << "version: " << ping.second.version << '\n';
|
||||||
.Execute();
|
|
||||||
|
|
||||||
std::cout << "I got X-RateLimit-Limit: " << *reply->GetHeader("X-RateLimit-Limit") << '\n';
|
|
||||||
|
|
||||||
rc::SerializeFromJson(ping, std::move(reply));
|
|
||||||
return ping;
|
|
||||||
}).get();
|
|
||||||
|
|
||||||
std::cout << "Response received:\n\ttimestamp: " << ping.generation_timestamp.ts;
|
|
||||||
std::cout << "\n\tmessage: " << ping.message;
|
|
||||||
std::cout << "\n\tversion: " << ping.version;
|
|
||||||
|
|
||||||
std::cout << std::endl;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@ restc_cpp_dep = dependency('restc-cpp', version: '>=0.1.1',
|
||||||
|
|
||||||
executable(meson.project_name(),
|
executable(meson.project_name(),
|
||||||
'main.cpp',
|
'main.cpp',
|
||||||
|
'oro/datatypes.cpp',
|
||||||
|
'oro/api.cpp',
|
||||||
install: true,
|
install: true,
|
||||||
dependencies: [restc_cpp_dep],
|
dependencies: [restc_cpp_dep],
|
||||||
include_directories: date_incdir,
|
include_directories: date_incdir,
|
||||||
|
|
75
src/oro/api.cpp
Normal file
75
src/oro/api.cpp
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#include "api.hpp"
|
||||||
|
#include "datatypes.hpp"
|
||||||
|
#include <restc-cpp/restc-cpp.h>
|
||||||
|
#include <restc-cpp/RequestBuilder.h>
|
||||||
|
#include <boost/fusion/adapted.hpp>
|
||||||
|
|
||||||
|
namespace rc = restc_cpp;
|
||||||
|
|
||||||
|
BOOST_FUSION_ADAPT_STRUCT(
|
||||||
|
oro::Ping,
|
||||||
|
(oro::Timestamp, generation_timestamp)
|
||||||
|
(std::string, message)
|
||||||
|
(int, version)
|
||||||
|
)
|
||||||
|
|
||||||
|
namespace oro {
|
||||||
|
namespace {
|
||||||
|
constexpr const char g_endpoint_ping[] = "api/v1/ping";
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::pair<Header, T> call_rest_api (
|
||||||
|
rc::RestClient& rest_client,
|
||||||
|
const std::string& url,
|
||||||
|
const std::string& client_name,
|
||||||
|
const std::string& client_purpose
|
||||||
|
) {
|
||||||
|
return rest_client.template ProcessWithPromiseT< std::pair<Header, T> >([&](rc::Context& ctx) {
|
||||||
|
std::unique_ptr<rc::Reply> reply = rc::RequestBuilder(ctx)
|
||||||
|
.Get(url)
|
||||||
|
.Header("X-Client", client_name)
|
||||||
|
.Header("X-Client-Purpose", client_purpose)
|
||||||
|
.Execute();
|
||||||
|
|
||||||
|
Header h;
|
||||||
|
if (auto val = reply->GetHeader("X-RateLimit-Limit")) {
|
||||||
|
h.rate_limit = std::stoi(*val);
|
||||||
|
}
|
||||||
|
if (auto val = reply->GetHeader("X-RateLimit-Remaining")) {
|
||||||
|
h.rate_limit_remaining = std::stoi(*val);
|
||||||
|
}
|
||||||
|
if (auto val = reply->GetHeader("X-RateLimit-Reset")) {
|
||||||
|
h.rate_limit_reset = std::stoul(*val);
|
||||||
|
}
|
||||||
|
if (auto val = reply->GetHeader("Retry-After")) {
|
||||||
|
h.retry_after = std::stoul(*val);
|
||||||
|
}
|
||||||
|
if (auto val = reply->GetHeader("Server")) {
|
||||||
|
h.server = std::move(*val);
|
||||||
|
}
|
||||||
|
|
||||||
|
T retval;
|
||||||
|
rc::SerializeFromJson(retval, std::move(reply));
|
||||||
|
|
||||||
|
return std::make_pair(std::move(h), std::move(retval));
|
||||||
|
}).get();
|
||||||
|
}
|
||||||
|
} //unnamed namespace
|
||||||
|
|
||||||
|
Api::Api (std::string&& root_address, std::string&& client_name, std::string&& client_purpose) :
|
||||||
|
m_prefix(std::move(root_address)),
|
||||||
|
m_client_name(std::move(client_name)),
|
||||||
|
m_client_purpose(std::move(client_purpose)),
|
||||||
|
m_client(rc::RestClient::Create())
|
||||||
|
{
|
||||||
|
if (not m_prefix.empty() and m_prefix[m_prefix.size() - 1] != '/')
|
||||||
|
m_prefix.push_back('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
Api::~Api() noexcept = default;
|
||||||
|
|
||||||
|
std::pair<Header, Ping> Api::ping() {
|
||||||
|
return call_rest_api<oro::Ping>(*m_client, m_prefix + g_endpoint_ping, m_client_name, m_client_purpose);
|
||||||
|
}
|
||||||
|
|
||||||
|
} //namespace oro
|
65
src/oro/api.hpp
Normal file
65
src/oro/api.hpp
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ping.hpp"
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace restc_cpp {
|
||||||
|
class RestClient;
|
||||||
|
} //namespace restc_cpp
|
||||||
|
|
||||||
|
namespace oro {
|
||||||
|
|
||||||
|
struct Header {
|
||||||
|
//Date: Fri, 19 Jun 2020 22:33:43 GMT
|
||||||
|
Timestamp date;
|
||||||
|
|
||||||
|
//Content-Type: application/json
|
||||||
|
//Content-Length: 89
|
||||||
|
//Connection: keep-alive
|
||||||
|
//Set-Cookie: __cfduid=dccdd965b47650be8b0107bb1292154981592606023; expires=Sun, 19-Jul-20 22:33:43 GMT; path=/; domain=.originsro.org; HttpOnly; SameSite=Lax
|
||||||
|
|
||||||
|
//X-RateLimit-Limit: 2
|
||||||
|
int rate_limit;
|
||||||
|
|
||||||
|
//X-RateLimit-Remaining: 0
|
||||||
|
int rate_limit_remaining;
|
||||||
|
|
||||||
|
//X-RateLimit-Reset: 1592606027
|
||||||
|
unsigned long rate_limit_reset;
|
||||||
|
|
||||||
|
//Retry-After: 3
|
||||||
|
unsigned long retry_after;
|
||||||
|
|
||||||
|
//CF-Cache-Status: DYNAMIC
|
||||||
|
//cf-request-id: 03705077e200000091668c6200000001
|
||||||
|
//Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
|
||||||
|
//Server: cloudflare
|
||||||
|
std::string server;
|
||||||
|
|
||||||
|
//CF-RAY: 5a60b69fdc270091-LHR
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class Api {
|
||||||
|
public:
|
||||||
|
Api (
|
||||||
|
std::string&& root_address,
|
||||||
|
std::string&& client_name,
|
||||||
|
std::string&& client_purpose
|
||||||
|
);
|
||||||
|
~Api() noexcept;
|
||||||
|
|
||||||
|
std::pair<Header, Ping> ping();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_prefix;
|
||||||
|
std::string m_client_name;
|
||||||
|
std::string m_client_purpose;
|
||||||
|
|
||||||
|
std::unique_ptr<restc_cpp::RestClient> m_client;
|
||||||
|
};
|
||||||
|
|
||||||
|
} //namespace oro
|
15
src/oro/datatypes.cpp
Normal file
15
src/oro/datatypes.cpp
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#include "datatypes.hpp"
|
||||||
|
|
||||||
|
#define HAS_UNCAUGHT_EXCEPTIONS 1
|
||||||
|
#include "date/date.h"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace oro {
|
||||||
|
Timestamp& Timestamp::operator= (const std::string& str) {
|
||||||
|
std::istringstream iss(str);
|
||||||
|
|
||||||
|
//date has this format: 2020-06-19T22:33:36.855672+00:00
|
||||||
|
date::from_stream(iss, "%FT%T%Ez", ts);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
} //namespace oro
|
15
src/oro/datatypes.hpp
Normal file
15
src/oro/datatypes.hpp
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace oro {
|
||||||
|
typedef std::chrono::time_point<std::chrono::system_clock, std::chrono::microseconds> timestamp_t;
|
||||||
|
|
||||||
|
struct Timestamp {
|
||||||
|
Timestamp& operator= (const std::string& str);
|
||||||
|
operator timestamp_t() const { return ts; }
|
||||||
|
|
||||||
|
timestamp_t ts;
|
||||||
|
};
|
||||||
|
} //namespace oro
|
12
src/oro/ping.hpp
Normal file
12
src/oro/ping.hpp
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "datatypes.hpp"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace oro {
|
||||||
|
struct Ping {
|
||||||
|
Timestamp generation_timestamp;
|
||||||
|
std::string message;
|
||||||
|
int version;
|
||||||
|
};
|
||||||
|
} //namespace oro
|
Loading…
Add table
Reference in a new issue