Before you start
Make sure that you can compile and run core tests and read a basic example Writing your first HTTP server.
Step by step guide
JSON is a nice format, but it does not suit well for high-load applications.
This tutorial shows you how to send and receive Flatbuffers over HTTP using userver.
In this sample we use the samples/flatbuf_service/flatbuffer_schema.fbs Flatbuffers scheme and compile it via the ‘flatc --cpp --gen-object-api --filename-suffix ’.fbs' flatbuffer_schema.fbs` command.
HTTP Flatbuffer handler component
There are two ways to write a handler that deals with Flatbuffers:
We are going to take the second approach. All the Flatbuffers related action happens in the HandleRequestFlatbufThrow method:
#include "flatbuffer_schema.fbs.h"
 
namespace samples::fbs_handle {
 
class FbsSumEcho final
                                                      fbs::SampleResponse> {
 public:
  
  static constexpr std::string_view kName = "handler-fbs-sample";
 
  
      : HttpHandlerFlatbufBase(config, context) {}
 
  fbs::SampleResponse::NativeTableType HandleRequestFlatbufThrow(
      const fbs::SampleRequest::NativeTableType& fbs_request,
    fbs::SampleResponse::NativeTableType res;
    res.sum = fbs_request.arg1 + fbs_request.arg2;
    res.echo = fbs_request.data;
    return res;
  }
};
 
}  
 
HTTP Flatbuffer request
A clients::http::Client is needed to make HTTP requests. It could be obtained from the components::HttpClient component.
 public:
  static constexpr std::string_view kName = "fbs-request";
 
      : LoggableComponentBase(config, context),
        http_client_{
            context.FindComponent<
components::HttpClient>().GetHttpClient()},
 
        task_{
utils::
Async(
"requests", [this]() { KeepRequesting(); })} {}
 
 
  void KeepRequesting() const;
 
 private:
};
 After that, we just send the data and validate the response:
void FbsRequest::KeepRequesting() const {
  
  fbs::SampleRequest::NativeTableType payload;
  payload.arg1 = 20;
  payload.arg2 = 22;
  payload.data = "Hello word";
 
  
  flatbuffers::FlatBufferBuilder fbb;
  auto ret_fbb = fbs::SampleRequest::Pack(fbb, &payload);
  fbb.Finish(ret_fbb);
  std::string data(reinterpret_cast<const char*>(fbb.GetBufferPointer()),
                   fbb.GetSize());
 
  
  const auto response = http_client_.CreateRequest()
                            .post("http://localhost:8084/fbs", std::move(data))
                            .timeout(std::chrono::seconds(1))
                            .retry(10)
                            .perform();
 
  
  UASSERT_MSG(response->IsOk(), 
"Sample should work well in tests");
 
 
  
  const auto body = response->body_view();
  const auto* response_fb =
      flatbuffers::GetRoot<fbs::SampleResponse>(body.data());
  flatbuffers::Verifier verifier(reinterpret_cast<const uint8_t*>(body.data()),
                                 body.size());
  UASSERT_MSG(response_fb->Verify(verifier), 
"Broken flatbuf in sample");
 
  fbs::SampleResponse::NativeTableType result;
  response_fb->UnPackTo(&result);
 
  
  UASSERT_MSG(result.sum == 42, 
"Sample should work well in tests");
 
  UASSERT_MSG(result.echo == payload.data, 
"Sample should work well in tests");
 
}
Build and Run
To build the sample, execute the following build steps at the userver root directory: 
bash
mkdir build_release
cd build_release
cmake -DCMAKE_BUILD_TYPE=Release ..
make userver-samples-flatbuf_service
The sample could be started by running make start-userver-samples-flatbuf_service. The command would invoke testsuite start target that sets proper paths in the configuration files and starts the service.
To start the service manually run ./samples/flatbuf_service/userver-samples-flatbuf_service -c </path/to/static_config.yaml>.
Now you can send a request to your server from another terminal: 
bash
$ echo "100000000c00180000000800100004000c00000014000000140000000000000016000000000000000a00000048656c6c6f20776f72640000" \
      | xxd -r -p | curl --data-binary "@-" http://localhost:8084/fbs -v --output /dev/null
* TCP_NODELAY set
* Connected to localhost (::1) port 8084 (#0)
> POST /fbs HTTP/1.1
> Host: localhost:8084
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Length: 56
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 56 out of 56 bytes
< HTTP/1.1 200 OK
< Date: Wed, 16 Jun 2021 12:52:22 UTC
< Content-Type: text/html
< X-YaRequestId: c8b2aee7ca5f4165ad25119b1850e778
< Server: userver/2.0 (20210616074040; rv:2c78282ea)
< X-YaTraceId: 8f4765a7176e41d28c3c6a677f00193e
< Connection: keep-alive
< Content-Length: 48
<
* Connection #0 to host localhost left intact
Functional testing
Naive functional tests for the service could be implemented using the testsuite in the following way:
async def test_flatbuf(service_client):
    body = bytearray.fromhex(
        '100000000c00180000000800100004000c000000140000001400000000000000'
        '16000000000000000a00000048656c6c6f20776f72640000',
    )
    response = await service_client.post('/fbs', data=body)
    assert response.status == 200
Do not forget to add the plugin in conftest.py:
pytest_plugins = ['pytest_userver.plugins.core']
 
Full sources
See the full example: