CCF
Loading...
Searching...
No Matches
api_version.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/http_query.h"
6#include "ccf/json_handler.h"
7
8#include <string>
9
11{
12 enum class ApiVersion
13 {
16
17 v1,
18 };
19
20 static constexpr std::pair<ApiVersion, char const*> api_version_strings[] = {
21 {ApiVersion::preview_v1, "2023-06-01-preview"},
22 {ApiVersion::v1, "2024-07-01"}};
23
24 std::optional<ApiVersion> get_api_version(
26 ApiVersion min_accepted,
27 // Optional out-parameter indicating why API version wasn't found
28 const char** error_code = nullptr)
29 {
30 std::string accepted_versions_suffix = "The supported api-versions are: ";
31 auto first = true;
32 for (const auto& p : api_version_strings)
33 {
34 if (p.first < min_accepted)
35 {
36 continue;
37 }
38
39 if (first)
40 {
41 accepted_versions_suffix += p.second;
42 first = false;
43 }
44 else
45 {
46 accepted_versions_suffix += fmt::format(", {}", p.second);
47 }
48 }
49
50 const auto param_name = "api-version";
51 const auto parsed_query =
52 http::parse_query(ctx.rpc_ctx->get_request_query());
53 const auto qit = parsed_query.find(param_name);
54 if (qit == parsed_query.end())
55 {
56 ctx.rpc_ctx->set_error(
57 HTTP_STATUS_BAD_REQUEST,
58 ccf::errors::MissingApiVersionParameter,
59 fmt::format(
60 "The api-version query parameter (?{}=) is required for all "
61 "requests. {}",
62 param_name,
63 accepted_versions_suffix));
64 if (error_code != nullptr)
65 {
66 *error_code = ccf::errors::MissingApiVersionParameter;
67 }
68 return std::nullopt;
69 }
70
71 const auto it = std::find_if(
72 std::begin(api_version_strings),
73 std::end(api_version_strings),
74 [&qit](const auto& p) { return p.second == qit->second; });
75 if (it == std::end(api_version_strings) || it->first < min_accepted)
76 {
77 auto message = fmt::format(
78 "Unsupported api-version '{}'. {}",
79 qit->second,
80 accepted_versions_suffix);
81 ctx.rpc_ctx->set_error(
82 HTTP_STATUS_BAD_REQUEST,
83 ccf::errors::UnsupportedApiVersionValue,
84 std::move(message));
85 if (error_code != nullptr)
86 {
87 *error_code = ccf::errors::UnsupportedApiVersionValue;
88 }
89 return std::nullopt;
90 }
91
92 return it->first;
93 }
94
95 // Extracts api-version from query parameter, and passes this to the given
96 // functor. Will return error responses for missing and unknown api-versions.
97 // This means handler functors can safely provide a default implementation
98 // without validating the given API version, so long as the behaviour is the
99 // same for *all* accepted versions.
100 template <typename Fn>
101 auto api_version_adapter(Fn&& f, ApiVersion min_accepted = ApiVersion::MIN)
102 {
103 return [f, min_accepted](auto& ctx) {
104 const auto api_version = get_api_version(ctx, min_accepted);
105 if (api_version.has_value())
106 {
107 f(ctx, api_version.value());
108 }
109
110 return;
111 };
112 }
113}
Definition api_version.h:11
std::optional< ApiVersion > get_api_version(ccf::endpoints::CommandEndpointContext &ctx, ApiVersion min_accepted, const char **error_code=nullptr)
Definition api_version.h:24
auto api_version_adapter(Fn &&f, ApiVersion min_accepted=ApiVersion::MIN)
Definition api_version.h:101
ApiVersion
Definition api_version.h:13
Definition endpoint_context.h:24
std::shared_ptr< ccf::RpcContext > rpc_ctx
Definition endpoint_context.h:31