RequestHandler: Finish checks system and first request

This commit is contained in:
tt2468 2021-05-03 16:55:30 -07:00
parent c2b717cabf
commit 2aba810ce1
7 changed files with 180 additions and 12 deletions

View File

@ -239,6 +239,8 @@ void WebSocketServer::BroadcastEvent(uint64_t requiredIntent, std::string eventT
it.second->IncrementOutgoingMessages();
break;
}
if (errorCode)
blog(LOG_ERROR, "[WebSocketServer::BroadcastEvent] Error sending event message: %s", errorCode.message().c_str());
}
}
lock.unlock();

View File

@ -4,7 +4,9 @@
const std::map<std::string, RequestMethodHandler> RequestHandler::_handlerMap
{
// General
{"GetVersion", &RequestHandler::GetVersion},
{"BroadcastCustomEvent", &RequestHandler::BroadcastCustomEvent},
};
RequestResult RequestHandler::ProcessRequest(const Request& request)

View File

@ -15,6 +15,7 @@ class RequestHandler {
private:
RequestResult GetVersion(const Request&);
RequestResult BroadcastCustomEvent(const Request&);
static const std::map<std::string, RequestMethodHandler> _handlerMap;
};

View File

@ -1,9 +1,28 @@
#include "../obs-websocket.h"
#include "../WebSocketServer.h"
#include "RequestHandler.h"
#include "../plugin-macros.generated.h"
RequestResult RequestHandler::GetVersion(const Request& request)
{
json ret{{"test", "pp"}};
return RequestResult::Success(ret);
return RequestResult::Success();
}
RequestResult RequestHandler::BroadcastCustomEvent(const Request& request)
{
RequestStatus::RequestStatus statusCode;
std::string comment;
if (!request.ValidateObject("eventData", statusCode, comment)) {
return RequestResult::Error(statusCode, comment);
}
auto webSocketServer = GetWebSocketServer();
if (!webSocketServer)
return RequestResult::Error(RequestStatus::RequestProcessingFailed, "Unable to send event.");
webSocketServer->BroadcastEvent((1 << 0), "CustomEvent", request.RequestData["eventData"]);
return RequestResult::Success();
}

View File

@ -2,13 +2,140 @@
#include "../../plugin-macros.generated.h"
json GetDefaultJsonObject(json requestData)
{
if (!requestData.is_object())
return json::object();
else
return requestData;
}
Request::Request(uint8_t rpcVersion, bool ignoreNonFatalRequestChecks, std::string requestType, json requestData) :
RpcVersion(rpcVersion),
IgnoreNonFatalRequestChecks(ignoreNonFatalRequestChecks),
RequestData(GetDefaultJsonObject(requestData)),
RequestType(requestType)
{
if (!requestData.is_object())
RequestData = json::object();
else
RequestData = requestData;
}
const bool Request::ValidateBasic(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const
{
if (!HasRequestData()) {
statusCode = RequestStatus::MissingRequestData;
comment = "Your request data is missing or invalid (non-object)";
return false;
}
if (!RequestData.contains(keyName)) {
statusCode = RequestStatus::MissingRequestParameter;
comment = std::string("Your request is missing the `") + keyName + "` parameter.";
return false;
}
return true;
}
const bool Request::ValidateNumber(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const double minValue, const double maxValue) const
{
if (!ValidateBasic(keyName, statusCode, comment)) {
return false;
}
if (!RequestData[keyName].is_number()) {
statusCode = RequestStatus::InvalidRequestParameterDataType;
comment = std::string("The parameter `") + keyName + "` must be a number.";
return false;
}
double value = RequestData[keyName];
if (value < minValue) {
statusCode = RequestStatus::RequestParameterOutOfRange;
comment = std::string("The parameter `") + keyName + "` is below the minimum of `" + std::to_string(minValue) + "`";
return false;
}
if (value > maxValue) {
statusCode = RequestStatus::RequestParameterOutOfRange;
comment = std::string("The parameter `") + keyName + "` is above the maximum of `" + std::to_string(maxValue) + "`";
return false;
}
return true;
}
const bool Request::ValidateString(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const
{
if (!ValidateBasic(keyName, statusCode, comment)) {
return false;
}
if (!RequestData[keyName].is_string()) {
statusCode = RequestStatus::InvalidRequestParameterDataType;
comment = std::string("The parameter `") + keyName + "` must be a string.";
return false;
}
if (RequestData[keyName].get<std::string>().empty() && !allowEmpty) {
statusCode = RequestStatus::RequestParameterEmpty;
comment = std::string("The parameter `") + keyName + "` must not be empty.";
return false;
}
return true;
}
const bool Request::ValidateBoolean(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const
{
if (!ValidateBasic(keyName, statusCode, comment)) {
return false;
}
if (!RequestData[keyName].is_boolean()) {
statusCode = RequestStatus::InvalidRequestParameterDataType;
comment = std::string("The parameter `") + keyName + "` must be boolean.";
return false;
}
return true;
}
const bool Request::ValidateObject(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const
{
if (!ValidateBasic(keyName, statusCode, comment)) {
return false;
}
if (!RequestData[keyName].is_object()) {
statusCode = RequestStatus::InvalidRequestParameterDataType;
comment = std::string("The parameter `") + keyName + "` must be an object.";
return false;
}
if (RequestData[keyName].empty() && !allowEmpty) {
statusCode = RequestStatus::RequestParameterEmpty;
comment = std::string("The parameter `") + keyName + "` must not be empty.";
return false;
}
return true;
}
const bool Request::ValidateArray(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty) const
{
if (!ValidateBasic(keyName, statusCode, comment)) {
return false;
}
if (!RequestData[keyName].is_array()) {
statusCode = RequestStatus::InvalidRequestParameterDataType;
comment = std::string("The parameter `") + keyName + "` must be an array.";
return false;
}
if (RequestData[keyName].empty() && !allowEmpty) {
statusCode = RequestStatus::RequestParameterEmpty;
comment = std::string("The parameter `") + keyName + "` must not be empty.";
return false;
}
return true;
}

View File

@ -1,13 +1,28 @@
#pragma once
#include <string>
#include "RequestStatus.h"
#include "../../utils/Utils.h"
struct Request
{
Request(uint8_t rpcVersion, bool ignoreNonFatalRequestChecks, std::string requestType, json requestData = nullptr);
Request(const uint8_t rpcVersion, const bool ignoreNonFatalRequestChecks, const std::string requestType, const json requestData = nullptr);
uint8_t RpcVersion;
bool IgnoreNonFatalRequestChecks;
std::string RequestType;
json RequestData;
const bool HasRequestData() const
{
return RequestData.is_object();
}
const bool ValidateBasic(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const;
const bool ValidateNumber(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const double minValue = -INFINITY, const double maxValue = INFINITY) const;
const bool ValidateString(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const;
const bool ValidateBoolean(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment) const;
const bool ValidateObject(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const;
const bool ValidateArray(const std::string keyName, RequestStatus::RequestStatus &statusCode, std::string &comment, const bool allowEmpty = false) const;
const uint8_t RpcVersion;
const bool IgnoreNonFatalRequestChecks;
const std::string RequestType;
const json RequestData;
};

View File

@ -16,6 +16,8 @@ namespace RequestStatus {
// A required request parameter is missing
MissingRequestParameter = 300,
// The request does not have a valid requestData object.
MissingRequestData = 301,
// Generic invalid request parameter message
InvalidRequestParameter = 400,