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 const std::string kFlatbufRequestDataName =
"__request_flatbuf";
22inline const std::string kFlatbufResponseDataName =
"__response_flatbuf";
39template <
typename InputType,
typename ReturnType>
42 "Input type should be auto-generated FlatBuffers table type");
44 "Return type should be auto-generated FlatBuffers table type");
47 HttpHandlerFlatbufBase(
const components::ComponentConfig& config,
48 const components::ComponentContext& component_context);
51 request::RequestContext& context)
const final;
53 virtual typename ReturnType::NativeTableType HandleRequestFlatbufThrow(
54 const http::HttpRequest& request,
55 const typename InputType::NativeTableType& input,
56 request::RequestContext& context)
const = 0;
61 const request::RequestContext& context)
const;
66 const request::RequestContext& context)
const;
73 const http::HttpRequest& request,
request::RequestContext& context,
74 const std::string& request_body)
const override;
78 const http::HttpRequest& request,
request::RequestContext& context,
79 const std::string& response_data)
const override;
82 request::RequestContext& context)
const final;
85template <
typename InputType,
typename ReturnType>
88 const components::ComponentContext& component_context)
91template <
typename InputType,
typename ReturnType>
93 const http::HttpRequest& request,
request::RequestContext& context)
const {
95 context.GetData<
const typename InputType::NativeTableType&>(
96 impl::kFlatbufRequestDataName);
98 const auto& ret = context.SetData<
const typename ReturnType::NativeTableType>(
99 impl::kFlatbufResponseDataName,
100 HandleRequestFlatbufThrow(request, input, context));
102 flatbuffers::FlatBufferBuilder fbb;
103 auto ret_fbb = ReturnType::Pack(fbb, &ret);
105 return {
reinterpret_cast<
const char*>(fbb.GetBufferPointer()), fbb.GetSize()};
108template <
typename InputType,
typename ReturnType>
111 const request::RequestContext& context)
const {
112 return context.GetDataOptional<
const typename InputType::NativeTableType>(
113 impl::kFlatbufRequestDataName);
116template <
typename InputType,
typename ReturnType>
119 const request::RequestContext& context)
const {
120 return context.GetDataOptional<
const typename ReturnType::NativeTableType>(
121 impl::kFlatbufResponseDataName);
124template <
typename InputType,
typename ReturnType>
127 const http::HttpRequest&,
request::RequestContext&,
128 const std::string& request_body)
const {
129 size_t limit = GetConfig().request_body_size_log_limit;
130 return utils::log::ToLimitedHex(request_body, limit);
133template <
typename InputType,
typename ReturnType>
136 const http::HttpRequest&,
request::RequestContext&,
137 const std::string& response_data)
const {
138 size_t limit = GetConfig().response_data_size_log_limit;
139 return utils::log::ToLimitedHex(response_data, limit);
142template <
typename InputType,
typename ReturnType>
144 const http::HttpRequest& request,
request::RequestContext& context)
const {
146 const auto* input_fbb = flatbuffers::GetRoot<InputType>(body.data());
147 flatbuffers::Verifier verifier(
reinterpret_cast<
const uint8_t*>(body.data()),
149 if (!input_fbb->Verify(verifier)) {
151 InternalMessage{
"Invalid FlatBuffers format in request body"});
154 typename InputType::NativeTableType input;
155 input_fbb->UnPackTo(&input);
157 context.SetData(impl::kFlatbufRequestDataName, std::move(input));
160template <
typename InputType,
typename ReturnType>
164 schema.UpdateDescription(
"HTTP handler flatbuf base config");