CCF
Loading...
Searching...
No Matches
endpoint.h
Go to the documentation of this file.
1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the Apache 2.0 License.
3#pragma once
4
5#include "ccf/ds/json.h"
6#include "ccf/ds/openapi.h"
8#include "ccf/http_consts.h"
9#include "ccf/rest_verb.h"
10#include "ccf/service/map.h"
11
12#include <string>
13#include <utility>
14
16{
17 using URI = std::string;
18
20 {
24 RESTVerb verb = HTTP_POST;
25
26 std::string to_str() const
27 {
28 return fmt::format("{} {}", verb.c_str(), uri_path);
29 }
30 };
31}
32
34{
35 template <>
37 {
39 const ccf::endpoints::EndpointKey& endpoint_key)
40 {
41 auto str =
42 fmt::format("{} {}", endpoint_key.verb.c_str(), endpoint_key.uri_path);
43 return SerialisedEntry(str.begin(), str.end());
44 }
45
47 const SerialisedEntry& data)
48 {
49 std::string str{data.begin(), data.end()};
50 auto i = str.find(' ');
51 if (i == std::string::npos)
52 {
53 throw std::logic_error("invalid encoding of endpoint key");
54 }
55 auto verb = str.substr(0, i);
56 auto uri_path = str.substr(i + 1);
57 return {uri_path, verb};
58 }
59 };
60}
61
62namespace ccf::endpoints
63{
66
68 {
76
81 Always,
82
90 Never
91 };
92
94 {
98 None,
99
104 ToPrimary,
105
109 ToBackup,
110 };
111
112 enum class Mode
113 {
114 ReadWrite,
115 ReadOnly,
117 };
118
124
127 {{ForwardingRequired::Sometimes, "sometimes"},
128 {ForwardingRequired::Always, "always"},
129 {ForwardingRequired::Never, "never"}});
130
133 {{RedirectionStrategy::None, "none"},
134 {RedirectionStrategy::ToPrimary, "to_primary"},
135 {RedirectionStrategy::ToBackup, "to_backup"}});
136
138 Mode,
139 {{Mode::ReadWrite, "readwrite"},
140 {Mode::ReadOnly, "readonly"},
141 {Mode::Historical, "historical"}});
142
144 {
145 enum
146 {
149
150 std::string key;
151
152 bool operator==(const InterpreterReusePolicy&) const = default;
153 };
154
155 void to_json(nlohmann::json& j, const InterpreterReusePolicy& grp);
156 void from_json(const nlohmann::json& j, InterpreterReusePolicy& grp);
157 std::string schema_name(const InterpreterReusePolicy*);
158 void fill_json_schema(nlohmann::json& schema, const InterpreterReusePolicy*);
159
161 {
169 std::vector<nlohmann::json> authn_policies = {};
171 nlohmann::json openapi;
173 bool openapi_hidden = false;
175 std::string js_module;
177 std::string js_function;
181 std::optional<InterpreterReusePolicy> interpreter_reuse = std::nullopt;
182 };
183
186 EndpointProperties, forwarding_required, authn_policies);
189 openapi,
190 openapi_hidden,
191 mode,
192 js_module,
193 js_function,
194 interpreter_reuse,
195 redirection_strategy);
196
233
234 using EndpointDefinitionPtr = std::shared_ptr<const EndpointDefinition>;
235
237 namespace Tables
238 {
239 static constexpr auto ENDPOINTS = "public:ccf.gov.endpoints";
240 }
241
253 {
254 // Functor which is invoked to process requests for this Endpoint
256 // Functor which is invoked to modify the response post commit.
258
260 {
261 virtual void install(Endpoint&) = 0;
262 };
264
266 std::function<void(nlohmann::json&, const Endpoint&)>;
267 std::vector<SchemaBuilderFn> schema_builders = {};
268
269 bool openapi_hidden = false;
270
271 http_status success_status = HTTP_STATUS_OK;
272 nlohmann::json params_schema = nullptr;
273 nlohmann::json result_schema = nullptr;
274
275 std::optional<std::string> openapi_summary = std::nullopt;
276 std::optional<std::string> openapi_description = std::nullopt;
277 std::optional<bool> openapi_deprecated = std::nullopt;
278
283 Endpoint& set_openapi_description(const std::string& description);
284
289 Endpoint& set_openapi_summary(const std::string& summary);
290
295 Endpoint& set_openapi_deprecated(bool is_deprecated);
296
303 const std::string& deprecation_version, const std::string& replacement);
304
309 Endpoint& set_openapi_hidden(bool hidden);
310
316 Endpoint& set_params_schema(const nlohmann::json& j);
317
325 const nlohmann::json& j,
326 std::optional<http_status> status = std::nullopt);
327
344 template <typename In, typename Out>
345 Endpoint& set_auto_schema(std::optional<http_status> status = std::nullopt)
346 {
347 if constexpr (!std::is_same_v<In, void>)
348 {
349 params_schema = ds::json::build_schema<In>();
350
351 schema_builders.push_back(
352 [](nlohmann::json& document, const Endpoint& endpoint) {
353 const auto http_verb = endpoint.dispatch.verb.get_http_method();
354 if (!http_verb.has_value())
355 {
356 // Non-HTTP endpoints are not documented
357 return;
358 }
359
360 ds::openapi::add_request_body_schema<In>(
361 document, endpoint.full_uri_path, http_verb.value());
362 });
363 }
364 else
365 {
366 params_schema = nullptr;
367 }
368
369 if constexpr (!std::is_same_v<Out, void>)
370 {
371 success_status = status.value_or(HTTP_STATUS_OK);
372
373 result_schema = ds::json::build_schema<Out>();
374
375 schema_builders.push_back(
376 [](nlohmann::json& document, const Endpoint& endpoint) {
377 const auto http_verb = endpoint.dispatch.verb.get_http_method();
378 if (!http_verb.has_value())
379 {
380 return;
381 }
382
383 ds::openapi::add_response_schema<Out>(
384 document,
385 endpoint.full_uri_path,
386 http_verb.value(),
387 endpoint.success_status);
388 });
389 }
390 else
391 {
392 success_status = status.value_or(HTTP_STATUS_NO_CONTENT);
393 result_schema = nullptr;
394 }
395
396 return *this;
397 }
398
413 template <typename T>
414 Endpoint& set_auto_schema(std::optional<http_status> status = std::nullopt)
415 {
416 return set_auto_schema<typename T::In, typename T::Out>(status);
417 }
418
430 template <typename T>
432 const std::string& param_name,
434 {
435 schema_builders.push_back(
436 [param_name,
437 presence](nlohmann::json& document, const Endpoint& endpoint) {
438 const auto http_verb = endpoint.dispatch.verb.get_http_method();
439 if (!http_verb.has_value())
440 {
441 // Non-HTTP endpoints are not documented
442 return;
443 }
444
445 const auto schema_name = ds::json::schema_name<T>();
446 const auto query_schema = ds::json::build_schema<T>();
447
448 auto parameter = nlohmann::json::object();
449 parameter["name"] = param_name;
450 parameter["in"] = "query";
451 parameter["required"] = presence == RequiredParameter;
452 parameter["schema"] = ds::openapi::add_schema_to_components(
453 document, schema_name, query_schema);
454 ds::openapi::add_request_parameter_schema(
455 document, endpoint.full_uri_path, http_verb.value(), parameter);
456 });
457
458 return *this;
459 }
460
468
470
471 void install();
472 };
473
474 using EndpointPtr = std::shared_ptr<const Endpoint>;
475}
476
477FMT_BEGIN_NAMESPACE
478template <>
479struct formatter<ccf::endpoints::ForwardingRequired>
480{
481 template <typename ParseContext>
482 constexpr auto parse(ParseContext& ctx)
483 {
484 return ctx.begin();
485 }
486
487 template <typename FormatContext>
488 auto format(
489 const ccf::endpoints::ForwardingRequired& v, FormatContext& ctx) const
490 {
491 char const* s;
492 switch (v)
493 {
495 {
496 s = "sometimes";
497 break;
498 }
500 {
501 s = "always";
502 break;
503 }
505 {
506 s = "never";
507 break;
508 }
509 default:
510 {
511 throw std::logic_error("Unhandled value for ForwardingRequired");
512 }
513 }
514 return format_to(ctx.out(), "{}", s);
515 }
516};
517FMT_END_NAMESPACE
Definition rest_verb.h:45
std::optional< llhttp_method > get_http_method() const
Definition rest_verb.h:57
const char * c_str() const
Definition rest_verb.h:62
Definition map.h:30
#define DECLARE_JSON_REQUIRED_FIELDS(TYPE,...)
Definition json.h:714
#define DECLARE_JSON_TYPE(TYPE)
Definition json.h:663
#define DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(TYPE)
Definition json.h:690
#define DECLARE_JSON_OPTIONAL_FIELDS(TYPE,...)
Definition json.h:786
#define DECLARE_JSON_ENUM(TYPE,...)
Definition json.h:837
Definition endpoint.h:16
std::string URI
Definition endpoint.h:17
std::string schema_name(const InterpreterReusePolicy *)
Definition endpoint.cpp:161
QueryParamPresence
Definition endpoint.h:120
@ RequiredParameter
Definition endpoint.h:121
@ OptionalParameter
Definition endpoint.h:122
Mode
Definition endpoint.h:113
void from_json(const nlohmann::json &j, InterpreterReusePolicy &grp)
Definition endpoint.cpp:148
std::shared_ptr< const Endpoint > EndpointPtr
Definition endpoint.h:474
void fill_json_schema(nlohmann::json &schema, const InterpreterReusePolicy *)
Definition endpoint.cpp:167
RedirectionStrategy
Definition endpoint.h:94
std::function< void(CommandEndpointContext &ctx, const ccf::TxID &txid)> LocallyCommittedEndpointFunction
Definition endpoint_context.h:66
void to_json(nlohmann::json &j, const InterpreterReusePolicy &grp)
Definition endpoint.cpp:136
std::shared_ptr< const EndpointDefinition > EndpointDefinitionPtr
Definition endpoint.h:234
std::function< void(EndpointContext &args)> EndpointFunction
Definition endpoint_context.h:63
ForwardingRequired
Definition endpoint.h:68
Definition sha256_hash.h:80
ccf::ByteVector SerialisedEntry
Definition serialised_entry.h:8
Definition app_interface.h:14
std::vector< std::shared_ptr< AuthnPolicy > > AuthnPolicies
Definition authentication_types.h:47
llhttp_status http_status
Definition http_status.h:9
Definition endpoint.h:198
EndpointKey dispatch
Definition endpoint.h:201
URI full_uri_path
Full URI path to endpoint, including method prefix.
Definition endpoint.h:204
EndpointProperties properties
Definition endpoint.h:206
AuthnPolicies authn_policies
Definition endpoint.h:231
virtual ~EndpointDefinition()=default
Definition endpoint.h:20
URI uri_path
URI path to endpoint.
Definition endpoint.h:22
RESTVerb verb
HTTP Verb.
Definition endpoint.h:24
std::string to_str() const
Definition endpoint.h:26
Definition endpoint.h:161
bool openapi_hidden
Definition endpoint.h:173
nlohmann::json openapi
OpenAPI schema for endpoint.
Definition endpoint.h:171
std::string js_module
JavaScript module.
Definition endpoint.h:175
std::string js_function
JavaScript function name.
Definition endpoint.h:177
std::vector< nlohmann::json > authn_policies
Authentication policies.
Definition endpoint.h:169
std::optional< InterpreterReusePolicy > interpreter_reuse
Definition endpoint.h:181
ForwardingRequired forwarding_required
Endpoint forwarding policy.
Definition endpoint.h:165
RedirectionStrategy redirection_strategy
Endpoint redirection policy.
Definition endpoint.h:167
Mode mode
Endpoint mode.
Definition endpoint.h:163
Definition endpoint.h:260
virtual void install(Endpoint &)=0
Definition endpoint.h:253
nlohmann::json result_schema
Definition endpoint.h:273
std::function< void(nlohmann::json &, const Endpoint &)> SchemaBuilderFn
Definition endpoint.h:266
Endpoint & add_query_parameter(const std::string &param_name, QueryParamPresence presence=RequiredParameter)
Definition endpoint.h:431
EndpointFunction func
Definition endpoint.h:255
Endpoint & set_openapi_hidden(bool hidden)
Definition endpoint.cpp:10
Endpoint & set_openapi_deprecated_replaced(const std::string &deprecation_version, const std::string &replacement)
Definition endpoint.cpp:111
Endpoint & set_openapi_description(const std::string &description)
Definition endpoint.cpp:93
Endpoint & set_result_schema(const nlohmann::json &j, std::optional< http_status > status=std::nullopt)
Definition endpoint.cpp:40
Endpoint & set_params_schema(const nlohmann::json &j)
Definition endpoint.cpp:16
void install()
Definition endpoint.cpp:122
nlohmann::json params_schema
Definition endpoint.h:272
Endpoint & set_forwarding_required(ForwardingRequired fr)
Definition endpoint.cpp:68
http_status success_status
Definition endpoint.h:271
LocallyCommittedEndpointFunction locally_committed_func
Definition endpoint.h:257
Endpoint & set_openapi_deprecated(bool is_deprecated)
Definition endpoint.cpp:105
Endpoint & set_auto_schema(std::optional< http_status > status=std::nullopt)
Definition endpoint.h:414
Endpoint & set_auto_schema(std::optional< http_status > status=std::nullopt)
Definition endpoint.h:345
bool openapi_hidden
Definition endpoint.h:269
Endpoint & set_redirection_strategy(RedirectionStrategy rs)
Definition endpoint.cpp:87
std::optional< std::string > openapi_summary
Definition endpoint.h:275
std::vector< SchemaBuilderFn > schema_builders
Definition endpoint.h:267
Installer * installer
Definition endpoint.h:263
std::optional< bool > openapi_deprecated
Definition endpoint.h:277
Endpoint & set_openapi_summary(const std::string &summary)
Definition endpoint.cpp:99
std::optional< std::string > openapi_description
Definition endpoint.h:276
bool operator==(const InterpreterReusePolicy &) const =default
@ KeyBased
Definition endpoint.h:147
enum ccf::endpoints::InterpreterReusePolicy::@0 kind
std::string key
Definition endpoint.h:150
static ccf::endpoints::EndpointKey from_serialised(const SerialisedEntry &data)
Definition endpoint.h:46
static SerialisedEntry to_serialised(const ccf::endpoints::EndpointKey &endpoint_key)
Definition endpoint.h:38
Definition blit_serialiser.h:14
constexpr auto parse(ParseContext &ctx)
Definition endpoint.h:482
auto format(const ccf::endpoints::ForwardingRequired &v, FormatContext &ctx) const
Definition endpoint.h:488