From 160ef4d7711f3c1e0fadf3b7dc28fe5701359cd2 Mon Sep 17 00:00:00 2001
From: tt2468 <tt2468@gmail.com>
Date: Mon, 3 May 2021 18:44:13 -0700
Subject: [PATCH] RequestHandler: Add RequestBatch logic

---
 src/WebSocketProtocol.cpp              | 63 +++++++++++++++++++++++---
 src/requesthandler/RequestHandler.cpp  |  3 ++
 src/requesthandler/rpc/RequestStatus.h |  2 +
 3 files changed, 61 insertions(+), 7 deletions(-)

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<std::vector<json>>();
+		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<std::mutex> 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)