// Copyright (c) 2023 King Wai Mark #include "HTTPRequestClient.h" int UHTTPRequestClient::RequestTimeoutDuration = 60; FString UHTTPRequestClient::MethodToString(EMethod Method) { switch (Method) { case EMethod::GET: return "GET"; case EMethod::PUT: return "PUT"; case EMethod::POST: return "POST"; case EMethod::PATCH: return "PATCH"; case EMethod::DEL: return "DELETE"; case EMethod::COPY: return "COPY"; case EMethod::HEAD: return "HEAD"; case EMethod::OPTIONS: return "OPTIONS"; case EMethod::LINK: return "LINK"; case EMethod::UNLINK: return "UNLINK"; case EMethod::LOCK: return "LOCK"; case EMethod::UNLOCK: return "UNLOCK"; case EMethod::PROPFIND: return "PROPFIND"; case EMethod::VIEW: return "VIEW"; } return ""; } void UHTTPRequestClient::MakeAHttpRequest(const EMethod Method, const FString URL, const TMap Params, const TMap Headers, const FString Body, const FResponse &OnComplete) { FHttpModule& HttpModule = FHttpModule::Get(); // 1. Create Request Object TSharedRef HttpRequest = HttpModule.CreateRequest(); // 2. Set the request method. E.g. GET, POST, PUSH, etc. const FString RequestMethod = UHTTPRequestClient::MethodToString(Method); if(RequestMethod.Len() <= 0) { UE_LOG(LogTemp, Error, TEXT("Request method not set.")); return; } HttpRequest->SetVerb(RequestMethod); // 3. Set the url. if(URL.Len() <= 0) { UE_LOG(LogTemp, Error, TEXT("The URL for the request cannot be empty.")); return; }; FString FullUrl = URL.TrimStartAndEnd(); // 3.a Add the query parameters using the Param map. int ParamIndex = 0; for (auto Param : Params) { if(ParamIndex == 0) FullUrl = FullUrl + "?"; else FullUrl = FullUrl + "&"; FullUrl = FullUrl + Param.Key + "=" + Param.Value; ParamIndex = ParamIndex + 1; } HttpRequest->SetURL(FullUrl); // 4. Set the request headers for (auto Header : Headers) { HttpRequest->AppendToHeader(Header.Key, Header.Value); } // 5. Add body to the request. HttpRequest->SetContentAsString(Body); // 6. Attach the callback to notify us that the process is completed. HttpRequest->OnProcessRequestComplete().BindLambda( // Here, we "capture" the 'this' pointer (the "&"), so our lambda can call this // class's methods in the callback. [&, OnComplete]( FHttpRequestPtr Req, FHttpResponsePtr Res, bool ConnectedSuccessfully) mutable { OnComplete.ExecuteIfBound(Res->GetResponseCode(), Res->GetContentAsString()); }); // 7. Set Settings HttpRequest->SetTimeout(UHTTPRequestClient::RequestTimeoutDuration); // 8. Submit the request for processing HttpRequest->ProcessRequest(); } FJSONObject UHTTPRequestClient::ResponseStringToJSON(const FString ResponseString) { FJSONObject JSONObject = FJSONObject(); const TSharedRef> JsonReader = TJsonReaderFactory::Create(ResponseString); TSharedPtr JsonParsed; if (FJsonSerializer::Deserialize(JsonReader, JsonParsed)) { JSONObject.JsonParsed = JsonParsed; } return JSONObject; } FJSONObject UHTTPRequestClient::GetObjectFromJSONObject(const FJSONObject JSON, const FString Key) { FJSONObject JsonObject = FJSONObject(); if(JSON.JsonParsed != nullptr) { JsonObject.JsonParsed = JSON.JsonParsed->GetObjectField(Key); } return JsonObject; } TArray UHTTPRequestClient::GetObjectArrayFromJSONObject(const FJSONObject JSON, const FString Key) { TArray ObjectArray = TArray(); if(JSON.JsonParsed != nullptr) { for (auto ArrayField : JSON.JsonParsed->GetArrayField(Key)) { FJSONObject TempJsonObject = FJSONObject(); TempJsonObject.JsonParsed = ArrayField->AsObject(); ObjectArray.Add(TempJsonObject); } } return ObjectArray; } TArray UHTTPRequestClient::GetStringArrayFromJSONObject(const FJSONObject JSON, const FString Key) { TArray StringArray = TArray(); if(JSON.JsonParsed != nullptr) { JSON.JsonParsed->TryGetStringArrayField(Key, StringArray); } return StringArray; } TArray UHTTPRequestClient::GetNumberArrayFromJSONObject(const FJSONObject JSON, const FString Key) { TArray NumberArray = TArray(); if(JSON.JsonParsed != nullptr) { for (auto ArrayField : JSON.JsonParsed->GetArrayField(Key)) { float TempNumber = ArrayField->AsNumber(); NumberArray.Add(TempNumber); } } return NumberArray; } TArray UHTTPRequestClient::GetBooleanArrayFromJSONObject(const FJSONObject JSON, const FString Key) { TArray BooleanArray = TArray(); if(JSON.JsonParsed != nullptr) { for (auto ArrayField : JSON.JsonParsed->GetArrayField(Key)) { bool TempBool = ArrayField->AsBool(); BooleanArray.Add(TempBool); } } return BooleanArray; } FString UHTTPRequestClient::GetStringFromJSONObject(const FJSONObject JSON, const FString Key) { FString StringData = ""; if(JSON.JsonParsed != nullptr) { JSON.JsonParsed->TryGetStringField(Key, StringData); } return StringData; } float UHTTPRequestClient::GetNumberFromJSONObject(const FJSONObject JSON, const FString Key) { double NumberData = 0; if(JSON.JsonParsed != nullptr) { JSON.JsonParsed->TryGetNumberField(Key, NumberData); } return NumberData; } bool UHTTPRequestClient::GetBooleanFromJSONObject(const FJSONObject JSON, const FString Key) { bool BooleanData = false; if(JSON.JsonParsed != nullptr) { JSON.JsonParsed->TryGetBoolField(Key, BooleanData); } return BooleanData; } void UHTTPRequestClient::SetTimeoutDuration(const int TimeoutDuration) { if(RequestTimeoutDuration < 3) { UHTTPRequestClient::RequestTimeoutDuration = 3; } else { UHTTPRequestClient::RequestTimeoutDuration = TimeoutDuration; } } int UHTTPRequestClient::GetTimeoutDuration() { return UHTTPRequestClient::RequestTimeoutDuration; } FString UHTTPRequestClient::ReplaceWithASCII(const FString& Str) { FString EncodedURL = Str; EncodedURL.ReplaceInline(TEXT(" "), TEXT("%20"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("!"), TEXT("%21"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("\""), TEXT("%22"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("#"), TEXT("%23"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("$"), TEXT("%24"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("&"), TEXT("%26"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("'"), TEXT("%27"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("("), TEXT("%28"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT(")"), TEXT("%29"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("*"), TEXT("%2A"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("+"), TEXT("%2B"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT(","), TEXT("%2C"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("-"), TEXT("%2D"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("."), TEXT("%2E"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("/"), TEXT("%2F"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT(":"), TEXT("%3A"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT(";"), TEXT("%3B"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("<"), TEXT("%3C"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("="), TEXT("%3D"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT(">"), TEXT("%3E"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("?"), TEXT("%3F"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("@"), TEXT("%40"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("["), TEXT("%5B"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("\\"), TEXT("%5C"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("]"), TEXT("%5D"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("^"), TEXT("%5E"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("_"), TEXT("%5F"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("`"), TEXT("%60"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("{"), TEXT("%7B"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("|"), TEXT("%7C"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("}"), TEXT("%7D"), ESearchCase::CaseSensitive); EncodedURL.ReplaceInline(TEXT("~"), TEXT("%7E"), ESearchCase::CaseSensitive); return EncodedURL; }