diff --git a/src/WebSocketProtocol.cpp b/src/WebSocketProtocol.cpp index 1cf40bef..6f90fe4c 100644 --- a/src/WebSocketProtocol.cpp +++ b/src/WebSocketProtocol.cpp @@ -91,12 +91,8 @@ WebSocketProtocol::ProcessResult WebSocketProtocol::ProcessMessage(SessionPtr se return ret; } - if (!incomingMessage.contains("requestType")) { - if (!session->IgnoreInvalidMessages()) { - ret.closeCode = WebSocketServer::WebSocketCloseCode::RequestMissingRequiredField; - ret.closeReason = "Your request is missing a `requestType`."; - } - return ret; + if (!incomingMessage["requestType"].is_string()) { + incomingMessage["requestType"] = ""; } RequestHandler requestHandler; @@ -118,7 +114,60 @@ WebSocketProtocol::ProcessResult WebSocketProtocol::ProcessMessage(SessionPtr se return ret; } else if (messageType == "RequestBatch") { - ; + // RequestID checking has to be done here where we are able to close the connection. + if (!incomingMessage.contains("requestId")) { + if (!session->IgnoreInvalidMessages()) { + ret.closeCode = WebSocketServer::WebSocketCloseCode::RequestMissingRequiredField; + ret.closeReason = "Your request batch is missing a `requestId`."; + } + return ret; + } + + if (!incomingMessage["requests"].is_array()) { + if (!session->IgnoreInvalidMessages()) { + ret.closeCode = WebSocketServer::WebSocketCloseCode::RequestMissingRequiredField; + ret.closeReason = "Your request batch is missing a `requests` or it is not an array."; + } + return ret; + } + + auto requests = incomingMessage["requests"].get>(); + json results = json::array(); + + RequestHandler requestHandler; + for (auto requestJson : requests) { + if (!requestJson["requestType"].is_string()) + requestJson["requestType"] = ""; + + Request request(session->RpcVersion(), session->IgnoreNonFatalRequestChecks(), requestJson["requestType"], requestJson["requestData"]); + + RequestResult requestResult = requestHandler.ProcessRequest(request); + + json result; + result["requestType"] = requestJson["requestType"]; + + if (requestJson.contains("requestId")) + result["requestId"] = requestJson["requestId"]; + + result["requestStatus"] = { + {"result", requestResult.StatusCode == RequestStatus::Success}, + {"code", requestResult.StatusCode} + }; + + if (!requestResult.Comment.empty()) + result["requestStatus"]["comment"] = requestResult.Comment; + + if (requestResult.ResponseData.is_object()) + result["responseData"] = requestResult.ResponseData; + + results.push_back(result); + } + + ret.result["messageType"] = "RequestBatchResponse"; + ret.result["requestId"] = incomingMessage["requestId"]; + ret.result["results"] = results; + + return ret; } else if (messageType == "Identify") { std::unique_lock sessionLock(session->OperationMutex); if (session->IsIdentified()) { diff --git a/src/requesthandler/RequestHandler.cpp b/src/requesthandler/RequestHandler.cpp index 2e2dbcbc..fedbd20f 100644 --- a/src/requesthandler/RequestHandler.cpp +++ b/src/requesthandler/RequestHandler.cpp @@ -14,6 +14,9 @@ RequestResult RequestHandler::ProcessRequest(const Request& request) if (!request.RequestData.is_null() && !request.RequestData.is_object()) return RequestResult::Error(RequestStatus::InvalidRequestParameterDataType, "Your request data is not an object."); + if (request.RequestType.empty()) + return RequestResult::Error(RequestStatus::MissingRequestType, "Your request is missing a `requestType`"); + RequestMethodHandler handler; try { handler = _handlerMap.at(request.RequestType); diff --git a/src/requesthandler/rpc/RequestStatus.h b/src/requesthandler/rpc/RequestStatus.h index f30902c8..0d9a2fc3 100644 --- a/src/requesthandler/rpc/RequestStatus.h +++ b/src/requesthandler/rpc/RequestStatus.h @@ -9,6 +9,8 @@ namespace RequestStatus { Success = 100, + // The `requestType` field is missing from the request data + MissingRequestType = 203, // The request type is invalid (does not exist) UnknownRequestType = 204, // Generic error code (comment is expected to be provided)