21#ifndef KICAD_API_HANDLER_H
22#define KICAD_API_HANDLER_H
27#include <fmt/format.h>
28#include <tl/expected.hpp>
33#include <google/protobuf/message.h>
36#include <api/common/envelope.pb.h>
39using kiapi::common::ApiRequest, kiapi::common::ApiResponse;
40using kiapi::common::ApiResponseStatus, kiapi::common::ApiStatusCode;
42typedef tl::expected<ApiResponse, ApiResponseStatus>
API_RESULT;
74 typedef std::function<HANDLER_RESULT<ApiResponse>( ApiRequest& )>
REQUEST_HANDLER;
90 template <
class RequestType,
class ResponseType,
class HandlerType>
95 std::string typeName = RequestType().GetTypeName();
97 wxASSERT_MSG( !m_handlers.count( typeName ),
98 wxString::Format(
"Duplicate API handler for type %s", typeName ) );
100 m_handlers[typeName] =
101 [
this, aHandler]( ApiRequest& aRequest ) ->
API_RESULT
104 ApiResponse envelope;
106 if( !tryUnpack( aRequest, envelope, cmd ) )
110 ctx.
ClientName = aRequest.header().client_name();
113 std::invoke( aHandler,
static_cast<HandlerType*
>(
this ), cmd, ctx );
115 if( response.has_value() )
117 envelope.mutable_status()->set_status( ApiStatusCode::AS_OK );
118 envelope.mutable_message()->PackFrom( *response );
123 return tl::unexpected( response.error() );
135 template<
typename MessageType>
136 bool tryUnpack( ApiRequest& aRequest, ApiResponse& aReply, MessageType& aDest )
138 if( !aRequest.message().UnpackTo( &aDest ) )
140 std::string msg = fmt::format(
"could not unpack message of type {} from request",
141 aDest.GetTypeName() );
142 aReply.mutable_status()->set_status( ApiStatusCode::AS_BAD_REQUEST );
143 aReply.mutable_status()->set_error_message( msg );
tl::expected< ApiResponse, ApiResponseStatus > API_RESULT
tl::expected< T, ApiResponseStatus > HANDLER_RESULT
static const wxString m_defaultCommitMessage
void registerHandler(HANDLER_RESULT< ResponseType >(HandlerType::*aHandler)(RequestType &, const HANDLER_CONTEXT &))
Registers an API command handler for the given message types.
std::map< std::string, REQUEST_HANDLER > m_handlers
Maps type name (without the URL prefix) to a handler method.
bool tryUnpack(ApiRequest &aRequest, ApiResponse &aReply, MessageType &aDest)
std::function< HANDLER_RESULT< ApiResponse >(ApiRequest &)> REQUEST_HANDLER
A handler for outer messages (envelopes) that will unpack to inner messages and call a specific handl...