8#include <flatbuffers/flatbuffers.h>
10#include <userver/server/handlers/http_handler_base.hpp>
11#include <userver/server/http/http_error.hpp>
12#include <userver/utils/log.hpp>
13#include <userver/yaml_config/schema.hpp>
15USERVER_NAMESPACE_BEGIN
17namespace server::handlers {
21inline constexpr std::string_view kFlatbufRequestDataName =
"__request_flatbuf";
22inline constexpr std::string_view kFlatbufResponseDataName =
40template <
typename InputType,
typename ReturnType>
43 "Input type should be auto-generated FlatBuffers table type");
45 "Return type should be auto-generated FlatBuffers table type");
48 HttpHandlerFlatbufBase(
const components::ComponentConfig& config,
49 const components::ComponentContext& component_context);
52 request::RequestContext& context)
const final;
54 virtual typename ReturnType::NativeTableType HandleRequestFlatbufThrow(
55 const http::HttpRequest& request,
56 const typename InputType::NativeTableType& input,
57 request::RequestContext& context)
const = 0;
62 const request::RequestContext& context)
const;
67 const request::RequestContext& context)
const;
74 const http::HttpRequest& request,
request::RequestContext& context,
75 const std::string& request_body)
const override;
79 const http::HttpRequest& request,
request::RequestContext& context,
80 const std::string& response_data)
const override;
83 request::RequestContext& context)
const final;
86template <
typename InputType,
typename ReturnType>
89 const components::ComponentContext& component_context)
92template <
typename InputType,
typename ReturnType>
94 const http::HttpRequest& request,
request::RequestContext& context)
const {
96 context.GetData<
const typename InputType::NativeTableType&>(
97 impl::kFlatbufRequestDataName);
100 context.SetData(std::string{impl::kFlatbufResponseDataName},
101 HandleRequestFlatbufThrow(request, input, context));
103 flatbuffers::FlatBufferBuilder fbb;
104 auto ret_fbb = ReturnType::Pack(fbb, &ret);
106 return {
reinterpret_cast<
const char*>(fbb.GetBufferPointer()), fbb.GetSize()};
109template <
typename InputType,
typename ReturnType>
112 const request::RequestContext& context)
const {
113 return context.GetDataOptional<
const typename InputType::NativeTableType>(
114 impl::kFlatbufRequestDataName);
117template <
typename InputType,
typename ReturnType>
120 const request::RequestContext& context)
const {
121 return context.GetDataOptional<
const typename ReturnType::NativeTableType>(
122 impl::kFlatbufResponseDataName);
125template <
typename InputType,
typename ReturnType>
128 const http::HttpRequest&,
request::RequestContext&,
129 const std::string& request_body)
const {
130 size_t limit = GetConfig().request_body_size_log_limit;
131 return utils::log::ToLimitedHex(request_body, limit);
134template <
typename InputType,
typename ReturnType>
137 const http::HttpRequest&,
request::RequestContext&,
138 const std::string& response_data)
const {
139 size_t limit = GetConfig().response_data_size_log_limit;
140 return utils::log::ToLimitedHex(response_data, limit);
143template <
typename InputType,
typename ReturnType>
145 const http::HttpRequest& request,
request::RequestContext& context)
const {
147 const auto* input_fbb = flatbuffers::GetRoot<InputType>(body.data());
148 flatbuffers::Verifier verifier(
reinterpret_cast<
const uint8_t*>(body.data()),
150 if (!input_fbb->Verify(verifier)) {
152 InternalMessage{
"Invalid FlatBuffers format in request body"});
155 typename InputType::NativeTableType input;
156 input_fbb->UnPackTo(&input);
158 context.SetData(std::string{impl::kFlatbufRequestDataName}, std::move(input));
161template <
typename InputType,
typename ReturnType>
165 schema.UpdateDescription(
"HTTP handler flatbuf base config");