From 6fefd2fa7add783fee8f574a6dc5596ac201afa5 Mon Sep 17 00:00:00 2001 From: "v.alyamkin" Date: Tue, 2 Aug 2016 20:36:16 +0300 Subject: [PATCH] - Change classes location - CallURL helper - Helper functions library - Minor refactoring --- .../Classes/{Json => }/VaRestJsonObject.h | 0 .../Classes/{Json => }/VaRestJsonValue.h | 0 Source/VaRestPlugin/Classes/VaRestLibrary.h | 72 ++++++++++++++ .../Classes/{Json => }/VaRestRequestJSON.h | 55 ++--------- Source/VaRestPlugin/Classes/VaRestTypes.h | 41 ++++++++ .../Private/{Json => }/VaRestJsonObject.cpp | 0 .../Private/{Json => }/VaRestJsonValue.cpp | 0 Source/VaRestPlugin/Private/VaRestLibrary.cpp | 97 +++++++++++++++++++ .../Private/{Json => }/VaRestRequestJSON.cpp | 47 +-------- 9 files changed, 222 insertions(+), 90 deletions(-) rename Source/VaRestPlugin/Classes/{Json => }/VaRestJsonObject.h (100%) rename Source/VaRestPlugin/Classes/{Json => }/VaRestJsonValue.h (100%) create mode 100644 Source/VaRestPlugin/Classes/VaRestLibrary.h rename Source/VaRestPlugin/Classes/{Json => }/VaRestRequestJSON.h (87%) create mode 100644 Source/VaRestPlugin/Classes/VaRestTypes.h rename Source/VaRestPlugin/Private/{Json => }/VaRestJsonObject.cpp (100%) rename Source/VaRestPlugin/Private/{Json => }/VaRestJsonValue.cpp (100%) create mode 100644 Source/VaRestPlugin/Private/VaRestLibrary.cpp rename Source/VaRestPlugin/Private/{Json => }/VaRestRequestJSON.cpp (85%) diff --git a/Source/VaRestPlugin/Classes/Json/VaRestJsonObject.h b/Source/VaRestPlugin/Classes/VaRestJsonObject.h similarity index 100% rename from Source/VaRestPlugin/Classes/Json/VaRestJsonObject.h rename to Source/VaRestPlugin/Classes/VaRestJsonObject.h diff --git a/Source/VaRestPlugin/Classes/Json/VaRestJsonValue.h b/Source/VaRestPlugin/Classes/VaRestJsonValue.h similarity index 100% rename from Source/VaRestPlugin/Classes/Json/VaRestJsonValue.h rename to Source/VaRestPlugin/Classes/VaRestJsonValue.h diff --git a/Source/VaRestPlugin/Classes/VaRestLibrary.h b/Source/VaRestPlugin/Classes/VaRestLibrary.h new file mode 100644 index 00000000..b909b71c --- /dev/null +++ b/Source/VaRestPlugin/Classes/VaRestLibrary.h @@ -0,0 +1,72 @@ +// Copyright 2016 Vladimir Alyamkin. All Rights Reserved. + +#pragma once + +#include "Kismet/BlueprintFunctionLibrary.h" + +#include "VaRestTypes.h" +#include "VaRestLibrary.generated.h" + +class UVaRestRequestJSON; +class UVaRestJsonObject; + +DECLARE_DYNAMIC_DELEGATE_OneParam(FVaRestCallDelegate, UVaRestRequestJSON*, Request); + +USTRUCT() +struct FVaRestCallResponse +{ + GENERATED_USTRUCT_BODY() + + UPROPERTY() + UVaRestRequestJSON* Request; + + UPROPERTY() + UObject* WorldContextObject; + + UPROPERTY() + FVaRestCallDelegate Callback; + + FDelegateHandle CompleteDelegateHandle; + FDelegateHandle FailDelegateHandle; + + FVaRestCallResponse() + : Request(nullptr) + , WorldContextObject(nullptr) + { + } + +}; + +/** + * Usefull tools for REST communications + */ +UCLASS() +class UVaRestLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + + + ////////////////////////////////////////////////////////////////////////// + // Helpers + +public: + /** Applies percent-encoding to text */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Utility") + static FString PercentEncode(const FString& Text); + + + ////////////////////////////////////////////////////////////////////////// + // Easy URL processing + +public: + /** Easy way to process http requests */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Library", meta = (WorldContext = "WorldContextObject")) + static void CallURL(UObject* WorldContextObject, const FString& URL, ERequestVerb Verb, ERequestContentType ContentType, UVaRestJsonObject* VaRestJson, const FVaRestCallDelegate& Callback); + + /** Called when URL is processed (one for both success/unsuccess events)*/ + static void OnCallComplete(UVaRestRequestJSON* Request); + +private: + static TMap RequestMap; + +}; diff --git a/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h b/Source/VaRestPlugin/Classes/VaRestRequestJSON.h similarity index 87% rename from Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h rename to Source/VaRestPlugin/Classes/VaRestRequestJSON.h index 4828ad90..369d4ddf 100644 --- a/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h +++ b/Source/VaRestPlugin/Classes/VaRestRequestJSON.h @@ -2,6 +2,7 @@ #pragma once +#include "VaRestTypes.h" #include "VaRestRequestJSON.generated.h" /** @@ -57,46 +58,17 @@ template class FVaRestLatentAction : public FPendingLatentAction const int32 OutputLink; const FWeakObjectPtr CallbackTarget; T &Result; - }; -/** Verb (GET, PUT, POST) used by the request */ -UENUM(BlueprintType) -enum class ERequestVerb : uint8 +template void FVaRestLatentAction::Cancel() { - GET, - POST, - PUT, - DEL UMETA(DisplayName="DELETE"), - /** Set CUSTOM verb by SetCustomVerb() function */ - CUSTOM -}; + UObject *Obj = Request.Get(); + if (Obj != nullptr) + { + ((UVaRestRequestJSON*)Obj)->Cancel(); + } +} -/** Content type (json, urlencoded, etc.) used by the request */ -UENUM(BlueprintType) -enum class ERequestContentType : uint8 -{ - x_www_form_urlencoded_url UMETA(DisplayName = "x-www-form-urlencoded (URL)"), - x_www_form_urlencoded_body UMETA(DisplayName = "x-www-form-urlencoded (Request Body)"), - json, - binary -}; - -/** Enumerates the current state of an Http request */ -UENUM(BlueprintType) -enum class ERequestStatus : uint8 -{ - /** Has not been started via ProcessRequest() */ - NotStarted, - /** Currently being ticked and processed */ - Processing, - /** Finished but failed */ - Failed, - /** Failed because it was unable to connect (safe to retry) */ - Failed_ConnectionError, - /** Finished and was successful */ - Succeeded -}; /** Generate a delegates for callback events */ DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRequestComplete, class UVaRestRequestJSON*, Request); @@ -105,6 +77,7 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRequestFail, class UVaRestRequest DECLARE_MULTICAST_DELEGATE_OneParam(FOnStaticRequestComplete, class UVaRestRequestJSON*); DECLARE_MULTICAST_DELEGATE_OneParam(FOnStaticRequestFail, class UVaRestRequestJSON*); + /** * General helper class http requests via blueprints */ @@ -151,14 +124,6 @@ class VARESTPLUGIN_API UVaRestRequestJSON : public UObject void SetHeader(const FString& HeaderName, const FString& HeaderValue); - ////////////////////////////////////////////////////////////////////////// - // Helpers - - /** Applies percent-encoding to text */ - UFUNCTION(BlueprintCallable, Category = "VaRest|Utility") - static FString PercentEncode(const FString& Text); - - ////////////////////////////////////////////////////////////////////////// // Destruction and reset @@ -275,7 +240,7 @@ class VARESTPLUGIN_API UVaRestRequestJSON : public UObject protected: /** Latent action helper */ - FVaRestLatentAction *ContinueAction; + FVaRestLatentAction* ContinueAction; /** Internal request data stored as JSON */ UPROPERTY() diff --git a/Source/VaRestPlugin/Classes/VaRestTypes.h b/Source/VaRestPlugin/Classes/VaRestTypes.h new file mode 100644 index 00000000..0ba037e2 --- /dev/null +++ b/Source/VaRestPlugin/Classes/VaRestTypes.h @@ -0,0 +1,41 @@ +// Copyright 2016 Vladimir Alyamkin. All Rights Reserved. + +#pragma once + +/** Verb (GET, PUT, POST) used by the request */ +UENUM(BlueprintType) +enum class ERequestVerb : uint8 +{ + GET, + POST, + PUT, + DEL UMETA(DisplayName = "DELETE"), + /** Set CUSTOM verb by SetCustomVerb() function */ + CUSTOM +}; + +/** Content type (json, urlencoded, etc.) used by the request */ +UENUM(BlueprintType) +enum class ERequestContentType : uint8 +{ + x_www_form_urlencoded_url UMETA(DisplayName = "x-www-form-urlencoded (URL)"), + x_www_form_urlencoded_body UMETA(DisplayName = "x-www-form-urlencoded (Request Body)"), + json, + binary +}; + +/** Enumerates the current state of an Http request */ +UENUM(BlueprintType) +enum class ERequestStatus : uint8 +{ + /** Has not been started via ProcessRequest() */ + NotStarted, + /** Currently being ticked and processed */ + Processing, + /** Finished but failed */ + Failed, + /** Failed because it was unable to connect (safe to retry) */ + Failed_ConnectionError, + /** Finished and was successful */ + Succeeded +}; diff --git a/Source/VaRestPlugin/Private/Json/VaRestJsonObject.cpp b/Source/VaRestPlugin/Private/VaRestJsonObject.cpp similarity index 100% rename from Source/VaRestPlugin/Private/Json/VaRestJsonObject.cpp rename to Source/VaRestPlugin/Private/VaRestJsonObject.cpp diff --git a/Source/VaRestPlugin/Private/Json/VaRestJsonValue.cpp b/Source/VaRestPlugin/Private/VaRestJsonValue.cpp similarity index 100% rename from Source/VaRestPlugin/Private/Json/VaRestJsonValue.cpp rename to Source/VaRestPlugin/Private/VaRestJsonValue.cpp diff --git a/Source/VaRestPlugin/Private/VaRestLibrary.cpp b/Source/VaRestPlugin/Private/VaRestLibrary.cpp new file mode 100644 index 00000000..87c4441d --- /dev/null +++ b/Source/VaRestPlugin/Private/VaRestLibrary.cpp @@ -0,0 +1,97 @@ +// Copyright 2016 Vladimir Alyamkin. All Rights Reserved. + +#include "VaRestPluginPrivatePCH.h" + + +////////////////////////////////////////////////////////////////////////// +// Helpers + +FString UVaRestLibrary::PercentEncode(const FString& Text) +{ + FString OutText = Text; + + OutText = OutText.Replace(TEXT(" "), TEXT("%20")); + OutText = OutText.Replace(TEXT("!"), TEXT("%21")); + OutText = OutText.Replace(TEXT("\""), TEXT("%22")); + OutText = OutText.Replace(TEXT("#"), TEXT("%23")); + OutText = OutText.Replace(TEXT("$"), TEXT("%24")); + OutText = OutText.Replace(TEXT("&"), TEXT("%26")); + OutText = OutText.Replace(TEXT("'"), TEXT("%27")); + OutText = OutText.Replace(TEXT("("), TEXT("%28")); + OutText = OutText.Replace(TEXT(")"), TEXT("%29")); + OutText = OutText.Replace(TEXT("*"), TEXT("%2A")); + OutText = OutText.Replace(TEXT("+"), TEXT("%2B")); + OutText = OutText.Replace(TEXT(","), TEXT("%2C")); + OutText = OutText.Replace(TEXT("/"), TEXT("%2F")); + OutText = OutText.Replace(TEXT(":"), TEXT("%3A")); + OutText = OutText.Replace(TEXT(";"), TEXT("%3B")); + OutText = OutText.Replace(TEXT("="), TEXT("%3D")); + OutText = OutText.Replace(TEXT("?"), TEXT("%3F")); + OutText = OutText.Replace(TEXT("@"), TEXT("%40")); + OutText = OutText.Replace(TEXT("["), TEXT("%5B")); + OutText = OutText.Replace(TEXT("]"), TEXT("%5D")); + OutText = OutText.Replace(TEXT("{"), TEXT("%7B")); + OutText = OutText.Replace(TEXT("}"), TEXT("%7D")); + + return OutText; +} + + +////////////////////////////////////////////////////////////////////////// +// Easy URL processing + +TMap UVaRestLibrary::RequestMap; + +void UVaRestLibrary::CallURL(UObject* WorldContextObject, const FString& URL, ERequestVerb Verb, ERequestContentType ContentType, UVaRestJsonObject* VaRestJson, const FVaRestCallDelegate& Callback) +{ + UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject); + if (World == nullptr) + { + UE_LOG(LogVaRest, Error, TEXT("UVaRestLibrary: Wrong world context")) + return; + } + + // Check we have valid data json + if (VaRestJson == nullptr) + { + VaRestJson = UVaRestJsonObject::ConstructJsonObject(WorldContextObject); + } + + UVaRestRequestJSON* Request = NewObject(); + + Request->SetVerb(Verb); + Request->SetContentType(ContentType); + Request->SetRequestObject(VaRestJson); + + FVaRestCallResponse Response; + Response.Request = Request; + Response.WorldContextObject = WorldContextObject; + Response.Callback = Callback; + + Response.CompleteDelegateHandle = Request->OnStaticRequestComplete.AddStatic(&UVaRestLibrary::OnCallComplete); + Response.FailDelegateHandle = Request->OnStaticRequestFail.AddStatic(&UVaRestLibrary::OnCallComplete); + + RequestMap.Add(Request, Response); + + Request->ResetResponseData(); + Request->ProcessURL(URL); +} + +void UVaRestLibrary::OnCallComplete(UVaRestRequestJSON* Request) +{ + if (!RequestMap.Contains(Request)) + { + return; + } + + FVaRestCallResponse* Response = RequestMap.Find(Request); + + Request->OnStaticRequestComplete.Remove(Response->CompleteDelegateHandle); + Request->OnStaticRequestFail.Remove(Response->FailDelegateHandle); + + Response->Callback.ExecuteIfBound(Request); + + Response->WorldContextObject = nullptr; + Response->Request = nullptr; + RequestMap.Remove(Request); +} diff --git a/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp b/Source/VaRestPlugin/Private/VaRestRequestJSON.cpp similarity index 85% rename from Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp rename to Source/VaRestPlugin/Private/VaRestRequestJSON.cpp index 5aad3e70..65940fee 100644 --- a/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp +++ b/Source/VaRestPlugin/Private/VaRestRequestJSON.cpp @@ -3,15 +3,6 @@ #include "VaRestPluginPrivatePCH.h" #include "CoreMisc.h" -template void FVaRestLatentAction::Cancel() -{ - UObject *Obj = Request.Get(); - if (Obj != nullptr) - { - ((UVaRestRequestJSON*)Obj)->Cancel(); - } -} - UVaRestRequestJSON::UVaRestRequestJSON(const class FObjectInitializer& PCIP) : Super(PCIP), BinaryContentType(TEXT("application/octet-stream")) @@ -71,40 +62,6 @@ void UVaRestRequestJSON::SetHeader(const FString& HeaderName, const FString& Hea } -////////////////////////////////////////////////////////////////////////// -// Helpers - -FString UVaRestRequestJSON::PercentEncode(const FString& Text) -{ - FString OutText = Text; - - OutText = OutText.Replace(TEXT(" "), TEXT("%20")); - OutText = OutText.Replace(TEXT("!"), TEXT("%21")); - OutText = OutText.Replace(TEXT("\""), TEXT("%22")); - OutText = OutText.Replace(TEXT("#"), TEXT("%23")); - OutText = OutText.Replace(TEXT("$"), TEXT("%24")); - OutText = OutText.Replace(TEXT("&"), TEXT("%26")); - OutText = OutText.Replace(TEXT("'"), TEXT("%27")); - OutText = OutText.Replace(TEXT("("), TEXT("%28")); - OutText = OutText.Replace(TEXT(")"), TEXT("%29")); - OutText = OutText.Replace(TEXT("*"), TEXT("%2A")); - OutText = OutText.Replace(TEXT("+"), TEXT("%2B")); - OutText = OutText.Replace(TEXT(","), TEXT("%2C")); - OutText = OutText.Replace(TEXT("/"), TEXT("%2F")); - OutText = OutText.Replace(TEXT(":"), TEXT("%3A")); - OutText = OutText.Replace(TEXT(";"), TEXT("%3B")); - OutText = OutText.Replace(TEXT("="), TEXT("%3D")); - OutText = OutText.Replace(TEXT("?"), TEXT("%3F")); - OutText = OutText.Replace(TEXT("@"), TEXT("%40")); - OutText = OutText.Replace(TEXT("["), TEXT("%5B")); - OutText = OutText.Replace(TEXT("]"), TEXT("%5D")); - OutText = OutText.Replace(TEXT("{"), TEXT("%7B")); - OutText = OutText.Replace(TEXT("}"), TEXT("%7D")); - - return OutText; -} - - ////////////////////////////////////////////////////////////////////////// // Destruction and reset @@ -299,7 +256,7 @@ void UVaRestRequestJSON::ProcessRequest() if (!Key.IsEmpty() && !Value.IsEmpty()) { UrlParams += ParamIdx == 0 ? "?" : "&"; - UrlParams += UVaRestRequestJSON::PercentEncode(Key) + "=" + UVaRestRequestJSON::PercentEncode(Value); + UrlParams += UVaRestLibrary::PercentEncode(Key) + "=" + UVaRestLibrary::PercentEncode(Value); } ParamIdx++; @@ -328,7 +285,7 @@ void UVaRestRequestJSON::ProcessRequest() if (!Key.IsEmpty() && !Value.IsEmpty()) { UrlParams += ParamIdx == 0 ? "" : "&"; - UrlParams += UVaRestRequestJSON::PercentEncode(Key) + "=" + UVaRestRequestJSON::PercentEncode(Value); + UrlParams += UVaRestLibrary::PercentEncode(Key) + "=" + UVaRestLibrary::PercentEncode(Value); } ParamIdx++;