Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 1.7.0 #121

Merged
merged 25 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2d9f8cc
Don't auto-log HTTP exceptions.
josephbirkner Jun 24, 2024
38b40ca
Bump version.
josephbirkner Jul 2, 2024
a6f3f87
Explicitely support zlib.
josephbirkner Jul 4, 2024
cd20e5c
Simplify SSL support by linking statically.
josephbirkner Jul 4, 2024
28f5087
Support multiple servers in the OpenAPI spec.
josephbirkner Jul 4, 2024
f624b4d
Allow parameters which do not define z-zserio-request-part.
josephbirkner Jul 4, 2024
c73dca0
Support new flexible YAML settings file format.
josephbirkner Jul 5, 2024
bfce116
Fix access-after-move.
josephbirkner Jul 5, 2024
4e67871
Fix CI problems.
josephbirkner Jul 8, 2024
f1ad5b4
Use node built into manylinux image instead of the Github version rel…
josephbirkner Jul 8, 2024
ab0c060
Add Python 3.12 to CI.
josephbirkner Jul 8, 2024
c96ca7f
Correctly symlink node20
josephbirkner Jul 8, 2024
0bca753
Use Github-provisioned Node after all, no chance to override it.
josephbirkner Jul 8, 2024
1cfee19
Fix dependency version conflict.
josephbirkner Jul 8, 2024
36ba66b
Update conanfile.py
josephbirkner Jul 9, 2024
1afc220
Fix ctest no-tests parameter.
josephbirkner Jul 9, 2024
997b0b5
Enforce that testing is enabled.
josephbirkner Jul 9, 2024
4efa132
Update docs for http-settings.
josephbirkner Jul 9, 2024
64dbd20
Fix server index access in HTTP client.
josephbirkner Jul 9, 2024
6b588aa
Disable Python 3.12 support for now, waiting for new zserio release w…
josephbirkner Jul 9, 2024
2dd3b75
Improve ZLIB integration.
josephbirkner Jul 15, 2024
bd5f1f2
Add httpcl::Settings::updateTimestamp
josephbirkner Jul 15, 2024
f3edafc
Add test for serverIndex.
josephbirkner Jul 15, 2024
b9cea63
Catch exceptions from load().
josephbirkner Jul 17, 2024
5e89717
Fix include guards.
josephbirkner Jul 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,18 @@ if (NOT TARGET Catch2)
endif()

if (NOT TARGET httplib)
find_package(ZLIB CONFIG REQUIRED)
set(HTTPLIB_REQUIRE_ZLIB ON CACHE BOOL "Do not use zlib when compiling httplib." FORCE)
if (NOT TARGET ZLIB::ZLIB)
find_package(ZLIB CONFIG REQUIRED)
endif ()
set (HTTPLIB_IS_USING_ZLIB TRUE)
FetchContent_Declare(httplib
GIT_REPOSITORY "https://github.com/yhirose/cpp-httplib.git"
GIT_TAG "v0.15.3"
GIT_SHALLOW ON)
FetchContent_MakeAvailable(httplib)
target_compile_definitions(httplib
INTERFACE
CPPHTTPLIB_OPENSSL_SUPPORT)
CPPHTTPLIB_OPENSSL_SUPPORT)
target_link_libraries(
httplib INTERFACE OpenSSL::SSL ZLIB::ZLIB)
endif()
Expand Down
11 changes: 11 additions & 0 deletions libs/httpcl/include/httpcl/http-settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <map>
#include <vector>
#include <string>
#include <shared_mutex>
#include <atomic>
#include "yaml-cpp/yaml.h"


Expand Down Expand Up @@ -92,6 +94,15 @@ struct Settings
*/
std::vector<Config> settings;
YAML::Node document;
mutable std::shared_mutex mutex;
std::chrono::steady_clock::time_point lastRead;

/**
* Prompt settings instance to re-parse the HTTP settings file,
* by calling updateTimestamp with std::chrono::steady_clock::now().
*/
static void updateTimestamp(std::chrono::steady_clock::time_point time);
static std::atomic<std::chrono::steady_clock::time_point> lastUpdated;
};

struct secret
Expand Down
17 changes: 15 additions & 2 deletions libs/httpcl/src/http-settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,8 +332,16 @@ Settings::Settings()
load();
}

std::atomic<std::chrono::steady_clock::time_point> Settings::lastUpdated{std::chrono::steady_clock::now()};

void Settings::updateTimestamp(std::chrono::steady_clock::time_point time) {
lastUpdated.store(time, std::memory_order_relaxed);
}

void Settings::load()
{
std::unique_lock lock(mutex);
lastRead = std::chrono::steady_clock::now();
settings.clear();

auto cookieJar = std::getenv("HTTP_SETTINGS_FILE");
Expand Down Expand Up @@ -412,15 +420,20 @@ Config::Config(const std::string& yamlConf)

Config Settings::operator[] (const std::string &url) const
{
Config result;
std::shared_lock lock(mutex);
if (lastRead < lastUpdated.load(std::memory_order_relaxed)) {
lock.unlock();
const_cast<Settings*>(this)->load();
josephbirkner marked this conversation as resolved.
Show resolved Hide resolved
lock.lock();
}

Config result;
for (auto const& config : settings)
{
if (!std::regex_match(url, config.urlPattern))
continue;
result |= config;
}

return result;
}

Expand Down
3 changes: 1 addition & 2 deletions libs/pyzswagcl/py-openapi-client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ PyOpenApiClient::PyOpenApiClient(std::string const& openApiUrl,
std::ifstream fs(openApiUrl);
return parseOpenAPIConfig(fs);
}
else
return fetchOpenAPIConfig(openApiUrl, *httpClient, httpConfig);
return fetchOpenAPIConfig(openApiUrl, *httpClient, httpConfig);
}();

client_ = std::make_unique<OpenAPIClient>(
Expand Down
3 changes: 2 additions & 1 deletion libs/zswag/test/calc/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -273,4 +273,5 @@ paths:
summary: ''
security:
- HeaderAuth: []
servers: []
servers:
- url: /
2 changes: 1 addition & 1 deletion libs/zswag/test/calc/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def run_test(aspect, request, fn, expect, auth_args):
try:
print(f"[py-test-client] Test#{counter}: {aspect}", flush=True)
print(f"[py-test-client] -> Instantiating client.", flush=True)
oa_client = OAClient(f"http://{host}:{port}/openapi.json", **auth_args)
oa_client = OAClient(f"http://{host}:{port}/openapi.json", **auth_args, server_index=0)
# Just make sure that OpenAPI JSON content is parsable
assert oa_client.config().content and json.loads(oa_client.config().content)
client = api.Calculator.Client(oa_client)
Expand Down
30 changes: 16 additions & 14 deletions libs/zswag/test/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ int main (int argc, char* argv[]) {

spdlog::info("[cpp-test-client] Starting integration tests with {}", specUrl);

auto runTest = [&] (auto const& fn, auto expect, std::string const& aspect, std::function<void(httpcl::Config&)> const& authFun)
auto runTest = [&] (auto const& fn, auto expect, std::string const& aspect, std::function<void(Config&)> const& authFun)
{
++testCounter;
spdlog::info("[cpp-test-client] Executing test #{}: {} ...", testCounter, aspect);
Expand All @@ -28,9 +28,11 @@ int main (int argc, char* argv[]) {
spdlog::info("[cpp-test-client] => Instantiating client.");
auto httpClient = std::make_unique<HttpLibHttpClient>();
auto openApiConfig = fetchOpenAPIConfig(specUrl, *httpClient);
httpcl::Config authHttpConf;
// See https://github.com/spec-first/connexion/issues/1139
openApiConfig.servers.insert(openApiConfig.servers.begin(), URIComponents::fromStrPath("/bad/path/we/dont/access"));
Config authHttpConf;
authFun(authHttpConf);
auto oaClient = OAClient(openApiConfig, std::move(httpClient), authHttpConf);
auto oaClient = OAClient(openApiConfig, std::move(httpClient), authHttpConf, 1);
spdlog::info("[cpp-test-client] => Running request.");
calculator::Calculator::Client calcClient(oaClient);
auto response = fn(calcClient);
Expand All @@ -49,22 +51,22 @@ int main (int argc, char* argv[]) {
calculator::BaseAndExponent req(calculator::I32(2), calculator::I32(3), 0, "", .0, std::vector<bool>{});
return calcClient.powerMethod(req);
}, 8., "Pass fields in path and header",
[](httpcl::Config& conf){});
[](Config& conf){});

runTest([](calculator::Calculator::Client& calcClient){
calculator::Integers req(std::vector<int32_t>{100, -200, 400});
return calcClient.intSumMethod(req);
}, 300., "Pass hex-encoded array in query",
[](httpcl::Config& conf){
[](Config& conf){
conf.headers.insert({"Authorization", "Bearer 123"});
});

runTest([](calculator::Calculator::Client& calcClient){
calculator::Bytes req(std::vector<uint8_t>{8, 16, 32, 64});
return calcClient.byteSumMethod(req);
}, 120., "Pass base64url-encoded byte array in path",
[](httpcl::Config& conf){
conf.auth = httpcl::Config::BasicAuthentication{
[](Config& conf){
conf.auth = Config::BasicAuthentication{
"u", "pw", ""
};
});
Expand All @@ -73,55 +75,55 @@ int main (int argc, char* argv[]) {
calculator::Integers req(std::vector<int32_t>{1, 2, 3, 4});
return calcClient.intMulMethod(req);
}, 24., "Pass base64-encoded long array in path",
[](httpcl::Config& conf){
[](Config& conf){
conf.query.insert({"api-key", "42"});
});

runTest([](calculator::Calculator::Client& calcClient){
calculator::Doubles req(std::vector<double>{34.5, 2.});
return calcClient.floatMulMethod(req);
}, 69., "Pass float array in query.",
[](httpcl::Config& conf){
[](Config& conf){
conf.cookies.insert({"api-cookie", "42"});
});

runTest([](calculator::Calculator::Client& calcClient){
calculator::Bools req(std::vector<bool>{true, false});
return calcClient.bitMulMethod(req);
}, false, "Pass bool array in query (expect false).",
[](httpcl::Config& conf){
[](Config& conf){
conf.apiKey = "42";
});

runTest([](calculator::Calculator::Client& calcClient){
calculator::Bools req(std::vector<bool>{true, true});
return calcClient.bitMulMethod(req);
}, true, "Pass bool array in query (expect true).",
[](httpcl::Config& conf){
[](Config& conf){
conf.headers.insert({"X-Generic-Token", "42"});
});

runTest([](calculator::Calculator::Client& calcClient){
calculator::Double req(1.);
return calcClient.identityMethod(req);
}, 1., "Pass request as blob in body",
[](httpcl::Config& conf){
[](Config& conf){
conf.cookies.insert({"api-cookie", "42"});
});

runTest([](calculator::Calculator::Client& calcClient){
calculator::Strings req(std::vector<std::string>{"foo", "bar"});
return calcClient.concatMethod(req);
}, std::string("foobar"), "Pass base64-encoded strings.",
[](httpcl::Config& conf){
[](Config& conf){
conf.headers.insert({"Authorization", "Bearer 123"});
});

runTest([](calculator::Calculator::Client& calcClient){
calculator::EnumWrapper req(calculator::Enum::TEST_ENUM_0);
return calcClient.nameMethod(req);
}, std::string("TEST_ENUM_0"), "Pass enum.",
[](httpcl::Config& conf){
[](Config& conf){
conf.apiKey = "42";
});

Expand Down
5 changes: 3 additions & 2 deletions libs/zswagcl/include/zswagcl/oaclient.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ class OAClient : public ::zserio::IServiceClient
{
public:
OAClient(
zswagcl::OpenAPIConfig config,
OpenAPIConfig config,
std::unique_ptr<httpcl::IHttpClient> client,
httpcl::Config httpConfig = {});
httpcl::Config httpConfig = {},
uint32_t serverIndex = 0);

std::vector<uint8_t> callMethod(
zserio::StringView methodName,
Expand Down
5 changes: 3 additions & 2 deletions libs/zswagcl/src/oaclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ namespace zswagcl

OAClient::OAClient(zswagcl::OpenAPIConfig config,
std::unique_ptr<httpcl::IHttpClient> client,
httpcl::Config httpConfig)
: client_(std::move(config), std::move(httpConfig), std::move(client))
httpcl::Config httpConfig,
uint32_t serverIndex)
: client_(std::move(config), std::move(httpConfig), std::move(client), serverIndex)
{}

template<typename arr_elem_t>
Expand Down
Loading