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"
12
13#include <string>
14#include <utility>
15
17{
18 using URI = std::string;
19
21 {
25 RESTVerb verb = HTTP_POST;
26
27 [[nodiscard]] std::string to_str() const
28 {
29 return fmt::format("{} {}", verb.c_str(), uri_path);
30 }
31 };
32}
33
35{
36 template <>
38 {
40 const ccf::endpoints::EndpointKey& endpoint_key)
41 {
42 auto str =
43 fmt::format("{} {}", endpoint_key.verb.c_str(), endpoint_key.uri_path);
44 return {str.begin(), str.end()};
45 }
46
48 const SerialisedEntry& data)
49 {
50 std::string str{data.begin(), data.end()};
51 auto i = str.find(' ');
52 if (i == std::string::npos)
53 {
54 throw std::logic_error("invalid encoding of endpoint key");
55 }
56 auto verb = str.substr(0, i);
57 auto uri_path = str.substr(i + 1);
58 return {uri_path, verb};
59 }
60 };
61}
62
63namespace ccf::endpoints
64{
67
68 enum class ForwardingRequired : uint8_t
69 {
77
82 Always,
83
91 Never
92 };
93
94 enum class RedirectionStrategy : uint8_t
95 {
99 None,
100
105 ToPrimary,
106
110 ToBackup,
111 };
112
113 enum class Mode : uint8_t
114 {
115 ReadWrite,
116 ReadOnly,
118 };
119
125
128 {{ForwardingRequired::Sometimes, "sometimes"},
129 {ForwardingRequired::Always, "always"},
130 {ForwardingRequired::Never, "never"}});
131
134 {{RedirectionStrategy::None, "none"},
135 {RedirectionStrategy::ToPrimary, "to_primary"},
136 {RedirectionStrategy::ToBackup, "to_backup"}});
137
139 Mode,
140 {{Mode::ReadWrite, "readwrite"},
141 {Mode::ReadOnly, "readonly"},
142 {Mode::Historical, "historical"}});
143
145 {
146 enum class Kind : uint8_t
147 {
150
151 std::string key;
152
153 bool operator==(const InterpreterReusePolicy&) const = default;
154 };
155
156 void to_json(nlohmann::json& j, const InterpreterReusePolicy& grp);
157 void from_json(const nlohmann::json& j, InterpreterReusePolicy& grp);
158 std::string schema_name(
159 [[maybe_unused]] const InterpreterReusePolicy* policy);
160 void fill_json_schema(
161 nlohmann::json& schema,
162 [[maybe_unused]] const InterpreterReusePolicy* policy);
163
187
190 EndpointProperties, forwarding_required, authn_policies);
193 openapi,
194 openapi_hidden,
195 mode,
196 js_module,
197 js_function,
198 interpreter_reuse,
199 redirection_strategy);
200
239
240 using EndpointDefinitionPtr = std::shared_ptr<const EndpointDefinition>;
241
243 namespace Tables
244 {
245 static constexpr auto ENDPOINTS = "public:ccf.gov.endpoints";
246 }
247
259 {
260 // Functor which is invoked to process requests for this Endpoint
262
263 // Functor which is invoked to modify the response after it is locally
264 // committed (ie - assigned a transaction ID)
266
268 {
269 virtual void install(Endpoint&) = 0;
270 virtual ~Installer() = default;
271 };
273
275 std::function<void(nlohmann::json&, const Endpoint&)>;
276 std::vector<SchemaBuilderFn> schema_builders;
277
278 bool openapi_hidden = false;
279
280 http_status success_status = HTTP_STATUS_OK;
281 nlohmann::json params_schema = nullptr;
282 nlohmann::json result_schema = nullptr;
283
284 std::optional<std::string> openapi_summary = std::nullopt;
285 std::optional<std::string> openapi_description = std::nullopt;
286 std::optional<bool> openapi_deprecated = std::nullopt;
287
292 Endpoint& set_openapi_description(const std::string& description);
293
298 Endpoint& set_openapi_summary(const std::string& summary);
299
304 Endpoint& set_openapi_deprecated(bool is_deprecated);
305
312 const std::string& deprecation_version, const std::string& replacement);
313
318 Endpoint& set_openapi_hidden(bool hidden);
319
327
333 Endpoint& set_params_schema(const nlohmann::json& j);
334
342 const nlohmann::json& j,
343 std::optional<http_status> status = std::nullopt);
344
361 // NOLINTNEXTLINE(misc-confusable-identifiers)
362 template <typename In, typename Out>
363 Endpoint& set_auto_schema(std::optional<http_status> status = std::nullopt)
364 {
365 if constexpr (!std::is_same_v<In, void>)
366 {
367 params_schema = ds::json::build_schema<In>();
368
369 schema_builders.push_back(
370 [](nlohmann::json& document, const Endpoint& endpoint) {
371 const auto http_verb = endpoint.dispatch.verb.get_http_method();
372 if (!http_verb.has_value())
373 {
374 // Non-HTTP endpoints are not documented
375 return;
376 }
377
378 ds::openapi::add_request_body_schema<In>(
379 document, endpoint.full_uri_path, http_verb.value());
380 });
381 }
382 else
383 {
384 params_schema = nullptr;
385 }
386
387 if constexpr (!std::is_same_v<Out, void>)
388 {
389 success_status = status.value_or(HTTP_STATUS_OK);
390
391 result_schema = ds::json::build_schema<Out>();
392
393 schema_builders.push_back(
394 [](nlohmann::json& document, const Endpoint& endpoint) {
395 const auto http_verb = endpoint.dispatch.verb.get_http_method();
396 if (!http_verb.has_value())
397 {
398 return;
399 }
400
401 ds::openapi::add_response_schema<Out>(
402 document,
403 endpoint.full_uri_path,
404 http_verb.value(),
405 endpoint.success_status);
406 });
407 }
408 else
409 {
410 success_status = status.value_or(HTTP_STATUS_NO_CONTENT);
411 result_schema = nullptr;
412 }
413
414 return *this;
415 }
416
431 template <typename T>
432 Endpoint& set_auto_schema(std::optional<http_status> status = std::nullopt)
433 {
434 return set_auto_schema<typename T::In, typename T::Out>(status);
435 }
436
448 template <typename T>
450 const std::string& param_name,
452 {
453 schema_builders.push_back(
454 [param_name,
455 presence](nlohmann::json& document, const Endpoint& endpoint) {
456 const auto http_verb = endpoint.dispatch.verb.get_http_method();
457 if (!http_verb.has_value())
458 {
459 // Non-HTTP endpoints are not documented
460 return;
461 }
462
463 const auto schema_name = ds::json::schema_name<T>();
464 const auto query_schema = ds::json::build_schema<T>();
465
466 auto parameter = nlohmann::json::object();
467 parameter["name"] = param_name;
468 parameter["in"] = "query";
469 parameter["required"] =
471 parameter["schema"] = ds::openapi::add_schema_to_components(
472 document, schema_name, query_schema);
473 ds::openapi::add_request_parameter_schema(
474 document, endpoint.full_uri_path, http_verb.value(), parameter);
475 });
476
477 return *this;
478 }
479
487
489
492
493 void install();
494 };
495
496 using EndpointPtr = std::shared_ptr<const Endpoint>;
497}
498
499FMT_BEGIN_NAMESPACE
500template <>
501struct formatter<ccf::endpoints::ForwardingRequired>
502{
503 template <typename ParseContext>
504 constexpr auto parse(ParseContext& ctx)
505 {
506 return ctx.begin();
507 }
508
509 template <typename FormatContext>
510 auto format(
511 const ccf::endpoints::ForwardingRequired& v, FormatContext& ctx) const
512 {
513 switch (v)
514 {
516 {
517 return format_to(ctx.out(), "sometimes");
518 }
520 {
521 return format_to(ctx.out(), "always");
522 }
524 {
525 return format_to(ctx.out(), "never");
526 }
527 default:
528 {
529 throw std::logic_error(fmt::format(
530 "Unhandled value for ForwardingRequired: {}",
531 static_cast<uint8_t>(v)));
532 }
533 }
534 }
535};
536FMT_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:736
#define DECLARE_JSON_TYPE(TYPE)
Definition json.h:685
#define DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(TYPE)
Definition json.h:712
#define DECLARE_JSON_OPTIONAL_FIELDS(TYPE,...)
Definition json.h:811
#define DECLARE_JSON_ENUM(TYPE,...)
Definition json.h:864
Definition endpoint.h:17
void fill_json_schema(nlohmann::json &schema, const InterpreterReusePolicy *policy)
Definition endpoint.cpp:180
RedirectionStrategy
Definition endpoint.h:95
std::string URI
Definition endpoint.h:18
QueryParamPresence
Definition endpoint.h:121
@ RequiredParameter
Definition endpoint.h:122
@ OptionalParameter
Definition endpoint.h:123
Mode
Definition endpoint.h:114
void from_json(const nlohmann::json &j, InterpreterReusePolicy &grp)
Definition endpoint.cpp:161
OperatorFeature
Definition operator_feature.h:10
ForwardingRequired
Definition endpoint.h:69
std::shared_ptr< const Endpoint > EndpointPtr
Definition endpoint.h:496
std::function< void(CommandEndpointContext &ctx, const ccf::TxID &txid)> LocallyCommittedEndpointFunction
Definition endpoint_context.h:69
std::string schema_name(const InterpreterReusePolicy *policy)
Definition endpoint.cpp:174
void to_json(nlohmann::json &j, const InterpreterReusePolicy &grp)
Definition endpoint.cpp:149
std::shared_ptr< const EndpointDefinition > EndpointDefinitionPtr
Definition endpoint.h:240
std::function< void(EndpointContext &args)> EndpointFunction
Definition endpoint_context.h:66
Definition sha256_hash.h:88
ccf::ByteVector SerialisedEntry
Definition serialised_entry.h:8
Definition app_interface.h:13
std::vector< std::shared_ptr< AuthnPolicy > > AuthnPolicies
Definition authentication_types.h:47
llhttp_status http_status
Definition http_status.h:9
Definition endpoint.h:202
EndpointKey dispatch
Definition endpoint.h:205
URI full_uri_path
Full URI path to endpoint, including method prefix.
Definition endpoint.h:208
EndpointProperties properties
Definition endpoint.h:210
std::set< OperatorFeature > required_operator_features
Definition endpoint.h:237
AuthnPolicies authn_policies
Definition endpoint.h:235
virtual ~EndpointDefinition()=default
Definition endpoint.h:21
URI uri_path
URI path to endpoint.
Definition endpoint.h:23
RESTVerb verb
HTTP Verb.
Definition endpoint.h:25
std::string to_str() const
Definition endpoint.h:27
Definition endpoint.h:165
bool openapi_hidden
Definition endpoint.h:177
nlohmann::json openapi
OpenAPI schema for endpoint.
Definition endpoint.h:175
std::string js_module
JavaScript module.
Definition endpoint.h:179
std::string js_function
JavaScript function name.
Definition endpoint.h:181
std::vector< nlohmann::json > authn_policies
Authentication policies.
Definition endpoint.h:173
std::optional< InterpreterReusePolicy > interpreter_reuse
Definition endpoint.h:185
ForwardingRequired forwarding_required
Endpoint forwarding policy.
Definition endpoint.h:169
RedirectionStrategy redirection_strategy
Endpoint redirection policy.
Definition endpoint.h:171
Mode mode
Endpoint mode.
Definition endpoint.h:167
Definition endpoint.h:268
virtual void install(Endpoint &)=0
Definition endpoint.h:259
nlohmann::json result_schema
Definition endpoint.h:282
std::function< void(nlohmann::json &, const Endpoint &)> SchemaBuilderFn
Definition endpoint.h:275
Endpoint & add_query_parameter(const std::string &param_name, QueryParamPresence presence=QueryParamPresence::RequiredParameter)
Definition endpoint.h:449
Endpoint & require_operator_feature(OperatorFeature feature)
Definition endpoint.cpp:16
EndpointFunction func
Definition endpoint.h:261
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:124
Endpoint & set_openapi_description(const std::string &description)
Definition endpoint.cpp:106
Endpoint & set_result_schema(const nlohmann::json &j, std::optional< http_status > status=std::nullopt)
Definition endpoint.cpp:46
Endpoint & set_params_schema(const nlohmann::json &j)
Definition endpoint.cpp:22
void install()
Definition endpoint.cpp:135
nlohmann::json params_schema
Definition endpoint.h:281
Endpoint & set_forwarding_required(ForwardingRequired fr)
Definition endpoint.cpp:74
http_status success_status
Definition endpoint.h:280
LocallyCommittedEndpointFunction locally_committed_func
Definition endpoint.h:265
Endpoint & set_openapi_deprecated(bool is_deprecated)
Definition endpoint.cpp:118
Endpoint & set_auto_schema(std::optional< http_status > status=std::nullopt)
Definition endpoint.h:432
Endpoint & set_auto_schema(std::optional< http_status > status=std::nullopt)
Definition endpoint.h:363
bool openapi_hidden
Definition endpoint.h:278
Endpoint & set_redirection_strategy(RedirectionStrategy rs)
Definition endpoint.cpp:93
std::optional< std::string > openapi_summary
Definition endpoint.h:284
std::vector< SchemaBuilderFn > schema_builders
Definition endpoint.h:276
Installer * installer
Definition endpoint.h:272
std::optional< bool > openapi_deprecated
Definition endpoint.h:286
Endpoint & set_locally_committed_function(const LocallyCommittedEndpointFunction &lcf)
Definition endpoint.cpp:99
Endpoint & set_openapi_summary(const std::string &summary)
Definition endpoint.cpp:112
std::optional< std::string > openapi_description
Definition endpoint.h:285
enum ccf::endpoints::InterpreterReusePolicy::Kind kind
bool operator==(const InterpreterReusePolicy &) const =default
std::string key
Definition endpoint.h:151
static ccf::endpoints::EndpointKey from_serialised(const SerialisedEntry &data)
Definition endpoint.h:47
static SerialisedEntry to_serialised(const ccf::endpoints::EndpointKey &endpoint_key)
Definition endpoint.h:39
Definition blit_serialiser.h:14
constexpr auto parse(ParseContext &ctx)
Definition endpoint.h:504
auto format(const ccf::endpoints::ForwardingRequired &v, FormatContext &ctx) const
Definition endpoint.h:510