From d599b647ec43b9184392216ba363fa9535134554 Mon Sep 17 00:00:00 2001 From: "v.alyamkin" Date: Wed, 11 May 2016 09:58:11 +0300 Subject: [PATCH 01/16] Request logging --- Source/VaRestPlugin/Classes/Json/VaRestJsonObject.h | 2 +- Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h | 4 ++++ .../VaRestPlugin/Private/Json/VaRestRequestJSON.cpp | 12 ++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Source/VaRestPlugin/Classes/Json/VaRestJsonObject.h b/Source/VaRestPlugin/Classes/Json/VaRestJsonObject.h index 2ad0a0f4..e074c7e6 100644 --- a/Source/VaRestPlugin/Classes/Json/VaRestJsonObject.h +++ b/Source/VaRestPlugin/Classes/Json/VaRestJsonObject.h @@ -37,7 +37,7 @@ class VARESTPLUGIN_API UVaRestJsonObject : public UObject UFUNCTION(BlueprintCallable, Category = "VaRest|Json") FString EncodeJson() const; - /** Serialize Json to string (signel string without line breaks) */ + /** Serialize Json to string (single string without line breaks) */ UFUNCTION(BlueprintCallable, Category = "VaRest|Json") FString EncodeJsonToSingleString() const; diff --git a/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h b/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h index faf5047a..03e829b8 100644 --- a/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h +++ b/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h @@ -137,6 +137,10 @@ class VARESTPLUGIN_API UVaRestRequestJSON : public UObject UFUNCTION(BlueprintCallable, Category = "VaRest|Request") 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); diff --git a/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp b/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp index bbb57866..af57d7e9 100644 --- a/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp +++ b/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp @@ -71,6 +71,10 @@ void UVaRestRequestJSON::SetHeader(const FString& HeaderName, const FString& Hea RequestHeaders.Add(HeaderName, HeaderValue); } + +////////////////////////////////////////////////////////////////////////// +// Helpers + FString UVaRestRequestJSON::PercentEncode(const FString& Text) { FString OutText = Text; @@ -295,6 +299,8 @@ void UVaRestRequestJSON::ProcessRequest(TSharedRef HttpRequest) // Apply params HttpRequest->SetURL(HttpRequest->GetURL() + UrlParams); + UE_LOG(LogVaRest, Log, TEXT("Request (urlencoded): %s %s %s"), *HttpRequest->GetVerb(), *HttpRequest->GetURL(), *UrlParams); + break; } case ERequestContentType::x_www_form_urlencoded_body: @@ -322,6 +328,8 @@ void UVaRestRequestJSON::ProcessRequest(TSharedRef HttpRequest) // Apply params HttpRequest->SetContentAsString(UrlParams); + UE_LOG(LogVaRest, Log, TEXT("Request (url body): %s %s %s"), *HttpRequest->GetVerb(), *HttpRequest->GetURL(), *UrlParams); + break; } case ERequestContentType::binary: @@ -329,6 +337,8 @@ void UVaRestRequestJSON::ProcessRequest(TSharedRef HttpRequest) HttpRequest->SetHeader(TEXT("Content-Type"), BinaryContentType); HttpRequest->SetContent(RequestBytes); + UE_LOG(LogVaRest, Log, TEXT("Request (binary): %s %s"), *HttpRequest->GetVerb(), *HttpRequest->GetURL()); + break; } case ERequestContentType::json: @@ -343,6 +353,8 @@ void UVaRestRequestJSON::ProcessRequest(TSharedRef HttpRequest) // Set Json content HttpRequest->SetContentAsString(OutputString); + UE_LOG(LogVaRest, Log, TEXT("Request (json): %s %s %s"), *HttpRequest->GetVerb(), *HttpRequest->GetURL(), *OutputString); + break; } From 74699735399e83e1b3b59ca806f4b84117b67048 Mon Sep 17 00:00:00 2001 From: "v.alyamkin" Date: Thu, 2 Jun 2016 09:17:17 +0300 Subject: [PATCH 02/16] Minor category fix --- Source/VaRestEditorPlugin/Classes/VaRest_BreakJson.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/VaRestEditorPlugin/Classes/VaRest_BreakJson.h b/Source/VaRestEditorPlugin/Classes/VaRest_BreakJson.h index 13847c05..d2fdb657 100644 --- a/Source/VaRestEditorPlugin/Classes/VaRest_BreakJson.h +++ b/Source/VaRestEditorPlugin/Classes/VaRest_BreakJson.h @@ -23,13 +23,13 @@ struct FVaRest_NamedType { GENERATED_USTRUCT_BODY(); - UPROPERTY(EditAnywhere) + UPROPERTY(EditAnywhere, Category = NamedType) FString Name; - UPROPERTY(EditAnywhere) + UPROPERTY(EditAnywhere, Category = NamedType) EVaRest_JsonType Type; - UPROPERTY(EditAnywhere) + UPROPERTY(EditAnywhere, Category = NamedType) bool bIsArray; }; From 03503d23ae3c7ae41113c46cc41cb78bbf620aa4 Mon Sep 17 00:00:00 2001 From: "v.alyamkin" Date: Mon, 27 Jun 2016 22:12:15 +0300 Subject: [PATCH 03/16] Static requests for C++ raw bindings --- Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h | 12 ++++++++++-- .../VaRestPlugin/Private/Json/VaRestRequestJSON.cpp | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h b/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h index 03e829b8..5ee06bbe 100644 --- a/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h +++ b/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h @@ -92,6 +92,9 @@ namespace ERequestContentType DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRequestComplete, class UVaRestRequestJSON*, Request); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRequestFail, class UVaRestRequestJSON*, Request); +DECLARE_MULTICAST_DELEGATE_OneParam(FOnStaticRequestComplete, class UVaRestRequestJSON*); +DECLARE_MULTICAST_DELEGATE_OneParam(FOnStaticRequestFail, class UVaRestRequestJSON*); + /** * General helper class http requests via blueprints */ @@ -232,8 +235,13 @@ class VARESTPLUGIN_API UVaRestRequestJSON : public UObject /** Event occured when the request wasn't successfull */ UPROPERTY(BlueprintAssignable, Category = "VaRest|Event") FOnRequestFail OnRequestFail; - - + + /** Event occured when the request has been completed */ + FOnStaticRequestComplete OnStaticRequestComplete; + + /** Event occured when the request wasn't successfull */ + FOnStaticRequestFail OnStaticRequestFail; + ////////////////////////////////////////////////////////////////////////// // Data diff --git a/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp b/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp index af57d7e9..3a803c89 100644 --- a/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp +++ b/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp @@ -391,6 +391,7 @@ void UVaRestRequestJSON::OnProcessRequestComplete(FHttpRequestPtr Request, FHttp // Broadcast the result event OnRequestFail.Broadcast(this); + OnStaticRequestFail.Broadcast(this); return; } @@ -436,6 +437,7 @@ void UVaRestRequestJSON::OnProcessRequestComplete(FHttpRequestPtr Request, FHttp // Broadcast the result event OnRequestComplete.Broadcast(this); + OnStaticRequestComplete.Broadcast(this); // Finish the latent action if (ContinueAction) From 72bcb5a4407f8affbc04e3d8ccb28af14f4ebb0b Mon Sep 17 00:00:00 2001 From: "v.alyamkin" Date: Tue, 2 Aug 2016 18:17:25 +0300 Subject: [PATCH 04/16] Additional warnings --- .../Private/Json/VaRestJsonObject.cpp | 72 ++++++++++++++++++- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/Source/VaRestPlugin/Private/Json/VaRestJsonObject.cpp b/Source/VaRestPlugin/Private/Json/VaRestJsonObject.cpp index 5972c3aa..d117f834 100644 --- a/Source/VaRestPlugin/Private/Json/VaRestJsonObject.cpp +++ b/Source/VaRestPlugin/Private/Json/VaRestJsonObject.cpp @@ -152,10 +152,15 @@ void UVaRestJsonObject::SetField(const FString& FieldName, UVaRestJsonValue* Jso float UVaRestJsonObject::GetNumberField(const FString& FieldName) const { + if (!JsonObj->HasTypedField(FieldName)) + { + UE_LOG(LogVaRest, Warning, TEXT("No field with name %s of type Number"), *FieldName); + } + if (!JsonObj.IsValid()) { return 0.0f; - } + } return JsonObj->GetNumberField(FieldName); } @@ -172,11 +177,16 @@ void UVaRestJsonObject::SetNumberField(const FString& FieldName, float Number) FString UVaRestJsonObject::GetStringField(const FString& FieldName) const { + if (!JsonObj->HasTypedField(FieldName)) + { + UE_LOG(LogVaRest, Warning, TEXT("No field with name %s of type String"), *FieldName); + } + if (!JsonObj.IsValid()) { return TEXT(""); } - + return JsonObj->GetStringField(FieldName); } @@ -192,6 +202,11 @@ void UVaRestJsonObject::SetStringField(const FString& FieldName, const FString& bool UVaRestJsonObject::GetBoolField(const FString& FieldName) const { + if (!JsonObj->HasTypedField(FieldName)) + { + UE_LOG(LogVaRest, Warning, TEXT("No field with name %s of type Boolean"), *FieldName); + } + if (!JsonObj.IsValid()) { return false; @@ -212,6 +227,11 @@ void UVaRestJsonObject::SetBoolField(const FString& FieldName, bool InValue) TArray UVaRestJsonObject::GetArrayField(const FString& FieldName) { + if (!JsonObj->HasTypedField(FieldName)) + { + UE_LOG(LogVaRest, Warning, TEXT("No field with name %s of type Array"), *FieldName); + } + TArray OutArray; if (!JsonObj.IsValid()) { @@ -298,6 +318,11 @@ void UVaRestJsonObject::MergeJsonObject(UVaRestJsonObject* InJsonObject, bool Ov UVaRestJsonObject* UVaRestJsonObject::GetObjectField(const FString& FieldName) const { + if (!JsonObj->HasTypedField(FieldName)) + { + UE_LOG(LogVaRest, Warning, TEXT("No field with name %s of type Object"), *FieldName); + } + if (!JsonObj.IsValid()) { return NULL; @@ -327,6 +352,11 @@ void UVaRestJsonObject::SetObjectField(const FString& FieldName, UVaRestJsonObje TArray UVaRestJsonObject::GetNumberArrayField(const FString& FieldName) { + if (!JsonObj->HasTypedField(FieldName)) + { + UE_LOG(LogVaRest, Warning, TEXT("No field with name %s of type Array"), *FieldName); + } + TArray NumberArray; if (!JsonObj.IsValid()) @@ -337,6 +367,12 @@ TArray UVaRestJsonObject::GetNumberArrayField(const FString& FieldName) TArray > JsonArrayValues = JsonObj->GetArrayField(FieldName); for (TArray >::TConstIterator It(JsonArrayValues); It; ++It) { + auto Value = (*It).Get(); + if (Value->Type != EJson::Number) + { + UE_LOG(LogVaRest, Error, TEXT("Not Number element in array with field name %s"), *FieldName); + } + NumberArray.Add((*It)->AsNumber()); } @@ -362,6 +398,11 @@ void UVaRestJsonObject::SetNumberArrayField(const FString& FieldName, const TArr TArray UVaRestJsonObject::GetStringArrayField(const FString& FieldName) { + if (!JsonObj->HasTypedField(FieldName)) + { + UE_LOG(LogVaRest, Warning, TEXT("No field with name %s of type Array"), *FieldName); + } + TArray StringArray; if (!JsonObj.IsValid()) @@ -372,6 +413,12 @@ TArray UVaRestJsonObject::GetStringArrayField(const FString& FieldName) TArray > JsonArrayValues = JsonObj->GetArrayField(FieldName); for (TArray >::TConstIterator It(JsonArrayValues); It; ++It) { + auto Value = (*It).Get(); + if (Value->Type != EJson::String) + { + UE_LOG(LogVaRest, Error, TEXT("Not String element in array with field name %s"), *FieldName); + } + StringArray.Add((*It)->AsString()); } @@ -397,6 +444,11 @@ void UVaRestJsonObject::SetStringArrayField(const FString& FieldName, const TArr TArray UVaRestJsonObject::GetBoolArrayField(const FString& FieldName) { + if (!JsonObj->HasTypedField(FieldName)) + { + UE_LOG(LogVaRest, Warning, TEXT("No field with name %s of type Array"), *FieldName); + } + TArray BoolArray; if (!JsonObj.IsValid()) @@ -407,6 +459,12 @@ TArray UVaRestJsonObject::GetBoolArrayField(const FString& FieldName) TArray > JsonArrayValues = JsonObj->GetArrayField(FieldName); for (TArray >::TConstIterator It(JsonArrayValues); It; ++It) { + auto Value = (*It).Get(); + if (Value->Type != EJson::Boolean) + { + UE_LOG(LogVaRest, Error, TEXT("Not Boolean element in array with field name %s"), *FieldName); + } + BoolArray.Add((*It)->AsBool()); } @@ -432,6 +490,11 @@ void UVaRestJsonObject::SetBoolArrayField(const FString& FieldName, const TArray TArray UVaRestJsonObject::GetObjectArrayField(const FString& FieldName) { + if (!JsonObj->HasTypedField(FieldName)) + { + UE_LOG(LogVaRest, Warning, TEXT("No field with name %s of type Array"), *FieldName); + } + TArray OutArray; if (!JsonObj.IsValid()) @@ -442,6 +505,11 @@ TArray UVaRestJsonObject::GetObjectArrayField(const FString& TArray< TSharedPtr > ValArray = JsonObj->GetArrayField(FieldName); for (auto Value : ValArray) { + if (Value->Type != EJson::Object) + { + UE_LOG(LogVaRest, Error, TEXT("Not Object element in array with field name %s"), *FieldName); + } + TSharedPtr NewObj = Value->AsObject(); UVaRestJsonObject* NewJson = NewObject(); From 51778b4e505138045e07f6194442501b57d836d8 Mon Sep 17 00:00:00 2001 From: "v.alyamkin" Date: Tue, 2 Aug 2016 18:18:04 +0300 Subject: [PATCH 05/16] Switch module type to Developer --- VaRestPlugin.uplugin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VaRestPlugin.uplugin b/VaRestPlugin.uplugin index bce225b7..c840d989 100644 --- a/VaRestPlugin.uplugin +++ b/VaRestPlugin.uplugin @@ -20,7 +20,7 @@ }, { "Name": "VaRestEditorPlugin", - "Type": "Editor" + "Type": "Developer" } ] } \ No newline at end of file From b2bd4bd73a5af0e63731d12b2d99d7a89195f414 Mon Sep 17 00:00:00 2001 From: "v.alyamkin" Date: Tue, 2 Aug 2016 18:29:07 +0300 Subject: [PATCH 06/16] Set response code regadless error or not --- Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp b/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp index 3a803c89..de20e64a 100644 --- a/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp +++ b/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp @@ -384,10 +384,13 @@ void UVaRestRequestJSON::OnProcessRequestComplete(FHttpRequestPtr Request, FHttp // Be sure that we have no data from previous response ResetResponseData(); + // Save response code first as int32 + ResponseCode = Response->GetResponseCode(); + // Check we have result to process futher if (!bWasSuccessful) { - UE_LOG(LogVaRest, Error, TEXT("Request failed: %s"), *Request->GetURL()); + UE_LOG(LogVaRest, Error, TEXT("Request failed (%d): %s"), ResponseCode, *Request->GetURL()); // Broadcast the result event OnRequestFail.Broadcast(this); @@ -399,11 +402,8 @@ void UVaRestRequestJSON::OnProcessRequestComplete(FHttpRequestPtr Request, FHttp // Save response data as a string ResponseContent = Response->GetContentAsString(); - // Save response code as int32 - ResponseCode = Response->GetResponseCode(); - // Log response state - UE_LOG(LogVaRest, Log, TEXT("Response (%d): %s"), Response->GetResponseCode(), *Response->GetContentAsString()); + UE_LOG(LogVaRest, Log, TEXT("Response (%d): %s"), ResponseCode, *ResponseContent); // Process response headers TArray Headers = Response->GetAllHeaders(); From 5e8d206bdc821afc992533afbc47fc1d35cf63f5 Mon Sep 17 00:00:00 2001 From: "v.alyamkin" Date: Tue, 2 Aug 2016 18:53:27 +0300 Subject: [PATCH 07/16] Enums refactoring --- .../Classes/Json/VaRestRequestJSON.h | 64 +++++++++++-------- .../Private/Json/VaRestRequestJSON.cpp | 13 ++-- 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h b/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h index 5ee06bbe..d0cff3ca 100644 --- a/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h +++ b/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h @@ -62,31 +62,41 @@ template class FVaRestLatentAction : public FPendingLatentAction /** Verb (GET, PUT, POST) used by the request */ UENUM(BlueprintType) -namespace ERequestVerb +enum class ERequestVerb : uint8 { - enum Type - { - GET, - POST, - PUT, - DEL UMETA(DisplayName="DELETE"), - /** Set CUSTOM verb by SetCustomVerb() function */ - CUSTOM - }; -} + 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) -namespace ERequestContentType +enum class ERequestContentType : uint8 { - enum Type - { - 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 - }; -} + 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); @@ -113,11 +123,11 @@ class VARESTPLUGIN_API UVaRestRequestJSON : public UObject /** Creates new request with defined verb and content type */ UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct Json Request", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"), Category = "VaRest|Request") - static UVaRestRequestJSON* ConstructRequestExt(UObject* WorldContextObject, ERequestVerb::Type Verb, ERequestContentType::Type ContentType); + static UVaRestRequestJSON* ConstructRequestExt(UObject* WorldContextObject, ERequestVerb Verb, ERequestContentType ContentType); /** Set verb to the request */ UFUNCTION(BlueprintCallable, Category = "VaRest|Request") - void SetVerb(ERequestVerb::Type Verb); + void SetVerb(ERequestVerb Verb); /** Set custom verb to the request */ UFUNCTION(BlueprintCallable, Category = "VaRest|Request") @@ -126,7 +136,7 @@ class VARESTPLUGIN_API UVaRestRequestJSON : public UObject /** Set content type to the request. If you're using the x-www-form-urlencoded, * params/constaints should be defined as key=ValueString pairs from Json data */ UFUNCTION(BlueprintCallable, Category = "VaRest|Request") - void SetContentType(ERequestContentType::Type ContentType); + void SetContentType(ERequestContentType ContentType); /** Set content type of the request for binary post data */ UFUNCTION(BlueprintCallable, Category = "VaRest|Request") @@ -192,6 +202,10 @@ class VARESTPLUGIN_API UVaRestRequestJSON : public UObject /////////////////////////////////////////////////////////////////////////// // Response data access + /** Get the responce code of the last query */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Response") + ERequestStatus GetStatus(); + /** Get the responce code of the last query */ UFUNCTION(BlueprintCallable, Category = "VaRest|Response") int32 GetResponseCode(); @@ -273,10 +287,10 @@ class VARESTPLUGIN_API UVaRestRequestJSON : public UObject UVaRestJsonObject* ResponseJsonObj; /** Verb for making request (GET,POST,etc) */ - ERequestVerb::Type RequestVerb; + ERequestVerb RequestVerb; /** Content type to be applied for request */ - ERequestContentType::Type RequestContentType; + ERequestContentType RequestContentType; /** Mapping of header section to values. Used to generate final header string for request */ TMap RequestHeaders; diff --git a/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp b/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp index de20e64a..1cbc6f50 100644 --- a/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp +++ b/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp @@ -29,8 +29,8 @@ UVaRestRequestJSON* UVaRestRequestJSON::ConstructRequest(UObject* WorldContextOb UVaRestRequestJSON* UVaRestRequestJSON::ConstructRequestExt( UObject* WorldContextObject, - ERequestVerb::Type Verb, - ERequestContentType::Type ContentType) + ERequestVerb Verb, + ERequestContentType ContentType) { UVaRestRequestJSON* Request = ConstructRequest(WorldContextObject); @@ -40,7 +40,7 @@ UVaRestRequestJSON* UVaRestRequestJSON::ConstructRequestExt( return Request; } -void UVaRestRequestJSON::SetVerb(ERequestVerb::Type Verb) +void UVaRestRequestJSON::SetVerb(ERequestVerb Verb) { RequestVerb = Verb; } @@ -50,7 +50,7 @@ void UVaRestRequestJSON::SetCustomVerb(FString Verb) CustomVerb = Verb; } -void UVaRestRequestJSON::SetContentType(ERequestContentType::Type ContentType) +void UVaRestRequestJSON::SetContentType(ERequestContentType ContentType) { RequestContentType = ContentType; } @@ -179,6 +179,11 @@ void UVaRestRequestJSON::SetResponseObject(UVaRestJsonObject* JsonObject) /////////////////////////////////////////////////////////////////////////// // Response data access +ERequestStatus UVaRestRequestJSON::GetStatus() +{ + return ERequestStatus::NotStarted; +} + int32 UVaRestRequestJSON::GetResponseCode() { return ResponseCode; From 28786b384ff9187016a11f44d752818ea24b6079 Mon Sep 17 00:00:00 2001 From: "v.alyamkin" Date: Tue, 2 Aug 2016 19:28:08 +0300 Subject: [PATCH 08/16] Request status getter --- .../VaRestPlugin/Classes/Json/VaRestRequestJSON.h | 6 +++++- .../VaRestPlugin/Private/Json/VaRestRequestJSON.cpp | 13 ++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h b/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h index d0cff3ca..1df5df46 100644 --- a/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h +++ b/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h @@ -231,7 +231,7 @@ class VARESTPLUGIN_API UVaRestRequestJSON : public UObject virtual void ApplyURL(const FString& Url, UVaRestJsonObject *&Result, UObject* WorldContextObject, struct FLatentActionInfo LatentInfo); /** Apply current internal setup to request and process it */ - void ProcessRequest(TSharedRef HttpRequest); + void ProcessRequest(); ////////////////////////////////////////////////////////////////////////// @@ -256,6 +256,7 @@ class VARESTPLUGIN_API UVaRestRequestJSON : public UObject /** Event occured when the request wasn't successfull */ FOnStaticRequestFail OnStaticRequestFail; + ////////////////////////////////////////////////////////////////////////// // Data @@ -304,4 +305,7 @@ class VARESTPLUGIN_API UVaRestRequestJSON : public UObject /** Custom verb that will be used with RequestContentType == CUSTOM */ FString CustomVerb; + /** Request we're currently processing */ + TSharedRef HttpRequest = FHttpModule::Get().CreateRequest(); + }; diff --git a/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp b/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp index 1cbc6f50..b928ce98 100644 --- a/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp +++ b/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp @@ -65,7 +65,6 @@ void UVaRestRequestJSON::SetBinaryRequestContent(const TArray &Bytes) RequestBytes = Bytes; } - void UVaRestRequestJSON::SetHeader(const FString& HeaderName, const FString& HeaderValue) { RequestHeaders.Add(HeaderName, HeaderValue); @@ -125,6 +124,8 @@ void UVaRestRequestJSON::ResetRequestData() { RequestJsonObj = NewObject(); } + + HttpRequest = FHttpModule::Get().CreateRequest(); } void UVaRestRequestJSON::ResetResponseData() @@ -181,7 +182,7 @@ void UVaRestRequestJSON::SetResponseObject(UVaRestJsonObject* JsonObject) ERequestStatus UVaRestRequestJSON::GetStatus() { - return ERequestStatus::NotStarted; + return ERequestStatus((uint8)HttpRequest->GetStatus()); } int32 UVaRestRequestJSON::GetResponseCode() @@ -218,15 +219,13 @@ TArray UVaRestRequestJSON::GetAllResponseHeaders() void UVaRestRequestJSON::ProcessURL(const FString& Url) { - TSharedRef HttpRequest = FHttpModule::Get().CreateRequest(); HttpRequest->SetURL(Url); - ProcessRequest(HttpRequest); + ProcessRequest(); } void UVaRestRequestJSON::ApplyURL(const FString& Url, UVaRestJsonObject *&Result, UObject* WorldContextObject, FLatentActionInfo LatentInfo) { - TSharedRef HttpRequest = FHttpModule::Get().CreateRequest(); HttpRequest->SetURL(Url); // Prepare latent action @@ -244,10 +243,10 @@ void UVaRestRequestJSON::ApplyURL(const FString& Url, UVaRestJsonObject *&Result LatentActionManager.AddNewAction(LatentInfo.CallbackTarget, LatentInfo.UUID, ContinueAction = new FVaRestLatentAction(this, Result, LatentInfo)); } - ProcessRequest(HttpRequest); + ProcessRequest(); } -void UVaRestRequestJSON::ProcessRequest(TSharedRef HttpRequest) +void UVaRestRequestJSON::ProcessRequest() { // Set verb switch (RequestVerb) From d46d60ab546e5a7287e1a849b767d47cb97555e2 Mon Sep 17 00:00:00 2001 From: "v.alyamkin" Date: Tue, 2 Aug 2016 19:32:25 +0300 Subject: [PATCH 09/16] URL accessor --- Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h | 12 ++++++++---- .../VaRestPlugin/Private/Json/VaRestRequestJSON.cpp | 5 +++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h b/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h index 1df5df46..4828ad90 100644 --- a/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h +++ b/Source/VaRestPlugin/Classes/Json/VaRestRequestJSON.h @@ -200,13 +200,17 @@ class VARESTPLUGIN_API UVaRestRequestJSON : public UObject /////////////////////////////////////////////////////////////////////////// - // Response data access + // Request/response data access - /** Get the responce code of the last query */ - UFUNCTION(BlueprintCallable, Category = "VaRest|Response") + /** Get url of http request */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Request") + FString GetURL(); + + /** Get status of http request */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Request") ERequestStatus GetStatus(); - /** Get the responce code of the last query */ + /** Get the response code of the last query */ UFUNCTION(BlueprintCallable, Category = "VaRest|Response") int32 GetResponseCode(); diff --git a/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp b/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp index b928ce98..5e6c2c6c 100644 --- a/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp +++ b/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp @@ -180,6 +180,11 @@ void UVaRestRequestJSON::SetResponseObject(UVaRestJsonObject* JsonObject) /////////////////////////////////////////////////////////////////////////// // Response data access +FString UVaRestRequestJSON::GetURL() +{ + return HttpRequest->GetURL(); +} + ERequestStatus UVaRestRequestJSON::GetStatus() { return ERequestStatus((uint8)HttpRequest->GetStatus()); From 4ac47ad99a8aa3e7e49645c6bb82f5205f8b530b Mon Sep 17 00:00:00 2001 From: "v.alyamkin" Date: Tue, 2 Aug 2016 19:36:44 +0300 Subject: [PATCH 10/16] NULL -> nullptr refactoring --- Source/VaRestPlugin/Private/Json/VaRestJsonObject.cpp | 4 ++-- Source/VaRestPlugin/Private/Json/VaRestJsonValue.cpp | 2 +- Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/VaRestPlugin/Private/Json/VaRestJsonObject.cpp b/Source/VaRestPlugin/Private/Json/VaRestJsonObject.cpp index d117f834..db38afdf 100644 --- a/Source/VaRestPlugin/Private/Json/VaRestJsonObject.cpp +++ b/Source/VaRestPlugin/Private/Json/VaRestJsonObject.cpp @@ -125,7 +125,7 @@ UVaRestJsonValue* UVaRestJsonObject::GetField(const FString& FieldName) const { if (!JsonObj.IsValid()) { - return NULL; + return nullptr; } TSharedPtr NewVal = JsonObj->TryGetField(FieldName); @@ -325,7 +325,7 @@ UVaRestJsonObject* UVaRestJsonObject::GetObjectField(const FString& FieldName) c if (!JsonObj.IsValid()) { - return NULL; + return nullptr; } TSharedPtr JsonObjField = JsonObj->GetObjectField(FieldName); diff --git a/Source/VaRestPlugin/Private/Json/VaRestJsonValue.cpp b/Source/VaRestPlugin/Private/Json/VaRestJsonValue.cpp index ba6aa96a..fd767f9f 100644 --- a/Source/VaRestPlugin/Private/Json/VaRestJsonValue.cpp +++ b/Source/VaRestPlugin/Private/Json/VaRestJsonValue.cpp @@ -229,7 +229,7 @@ UVaRestJsonObject* UVaRestJsonValue::AsObject() if (!JsonVal.IsValid()) { ErrorMessage(TEXT("Object")); - return NULL; + return nullptr; } TSharedPtr NewObj = JsonVal->AsObject(); diff --git a/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp b/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp index 5e6c2c6c..5aad3e70 100644 --- a/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp +++ b/Source/VaRestPlugin/Private/Json/VaRestRequestJSON.cpp @@ -116,7 +116,7 @@ void UVaRestRequestJSON::ResetData() void UVaRestRequestJSON::ResetRequestData() { - if (RequestJsonObj != NULL) + if (RequestJsonObj != nullptr) { RequestJsonObj->Reset(); } @@ -130,7 +130,7 @@ void UVaRestRequestJSON::ResetRequestData() void UVaRestRequestJSON::ResetResponseData() { - if (ResponseJsonObj != NULL) + if (ResponseJsonObj != nullptr) { ResponseJsonObj->Reset(); } @@ -200,7 +200,7 @@ FString UVaRestRequestJSON::GetResponseHeader(const FString HeaderName) FString Result; FString* Header = ResponseHeaders.Find(HeaderName); - if (Header != NULL) + if (Header != nullptr) { Result = *Header; } @@ -239,7 +239,7 @@ void UVaRestRequestJSON::ApplyURL(const FString& Url, UVaRestJsonObject *&Result FLatentActionManager& LatentActionManager = World->GetLatentActionManager(); FVaRestLatentAction *Kont = LatentActionManager.FindExistingAction>(LatentInfo.CallbackTarget, LatentInfo.UUID); - if (Kont != NULL) + if (Kont != nullptr) { Kont->Cancel(); LatentActionManager.RemoveActionsForObject(LatentInfo.CallbackTarget); From a40bc5ff4703ee9280da2b14f4ca271aec4ecdfa Mon Sep 17 00:00:00 2001 From: "v.alyamkin" Date: Tue, 2 Aug 2016 19:52:17 +0300 Subject: [PATCH 11/16] Fix #70 (Possible crash on empty field name) --- .../Private/Json/VaRestJsonObject.cpp | 81 +++++++------------ 1 file changed, 31 insertions(+), 50 deletions(-) diff --git a/Source/VaRestPlugin/Private/Json/VaRestJsonObject.cpp b/Source/VaRestPlugin/Private/Json/VaRestJsonObject.cpp index db38afdf..44dd0e59 100644 --- a/Source/VaRestPlugin/Private/Json/VaRestJsonObject.cpp +++ b/Source/VaRestPlugin/Private/Json/VaRestJsonObject.cpp @@ -103,7 +103,7 @@ TArray UVaRestJsonObject::GetFieldNames() bool UVaRestJsonObject::HasField(const FString& FieldName) const { - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return false; } @@ -113,7 +113,7 @@ bool UVaRestJsonObject::HasField(const FString& FieldName) const void UVaRestJsonObject::RemoveField(const FString& FieldName) { - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return; } @@ -123,22 +123,26 @@ void UVaRestJsonObject::RemoveField(const FString& FieldName) UVaRestJsonValue* UVaRestJsonObject::GetField(const FString& FieldName) const { - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return nullptr; } TSharedPtr NewVal = JsonObj->TryGetField(FieldName); + if (NewVal.IsValid()) + { + UVaRestJsonValue* NewValue = NewObject(); + NewValue->SetRootValue(NewVal); - UVaRestJsonValue* NewValue = NewObject(); - NewValue->SetRootValue(NewVal); - - return NewValue; + return NewValue; + } + + return nullptr; } void UVaRestJsonObject::SetField(const FString& FieldName, UVaRestJsonValue* JsonValue) { - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return; } @@ -152,22 +156,18 @@ void UVaRestJsonObject::SetField(const FString& FieldName, UVaRestJsonValue* Jso float UVaRestJsonObject::GetNumberField(const FString& FieldName) const { - if (!JsonObj->HasTypedField(FieldName)) + if (!JsonObj.IsValid() || !JsonObj->HasTypedField(FieldName)) { UE_LOG(LogVaRest, Warning, TEXT("No field with name %s of type Number"), *FieldName); - } - - if (!JsonObj.IsValid()) - { return 0.0f; - } + } return JsonObj->GetNumberField(FieldName); } void UVaRestJsonObject::SetNumberField(const FString& FieldName, float Number) { - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return; } @@ -177,13 +177,9 @@ void UVaRestJsonObject::SetNumberField(const FString& FieldName, float Number) FString UVaRestJsonObject::GetStringField(const FString& FieldName) const { - if (!JsonObj->HasTypedField(FieldName)) + if (!JsonObj.IsValid() || !JsonObj->HasTypedField(FieldName)) { UE_LOG(LogVaRest, Warning, TEXT("No field with name %s of type String"), *FieldName); - } - - if (!JsonObj.IsValid()) - { return TEXT(""); } @@ -192,7 +188,7 @@ FString UVaRestJsonObject::GetStringField(const FString& FieldName) const void UVaRestJsonObject::SetStringField(const FString& FieldName, const FString& StringValue) { - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return; } @@ -202,13 +198,9 @@ void UVaRestJsonObject::SetStringField(const FString& FieldName, const FString& bool UVaRestJsonObject::GetBoolField(const FString& FieldName) const { - if (!JsonObj->HasTypedField(FieldName)) + if (!JsonObj.IsValid() || !JsonObj->HasTypedField(FieldName)) { UE_LOG(LogVaRest, Warning, TEXT("No field with name %s of type Boolean"), *FieldName); - } - - if (!JsonObj.IsValid()) - { return false; } @@ -217,7 +209,7 @@ bool UVaRestJsonObject::GetBoolField(const FString& FieldName) const void UVaRestJsonObject::SetBoolField(const FString& FieldName, bool InValue) { - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return; } @@ -233,7 +225,7 @@ TArray UVaRestJsonObject::GetArrayField(const FString& FieldN } TArray OutArray; - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return OutArray; } @@ -252,7 +244,7 @@ TArray UVaRestJsonObject::GetArrayField(const FString& FieldN void UVaRestJsonObject::SetArrayField(const FString& FieldName, const TArray& InArray) { - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return; } @@ -318,13 +310,9 @@ void UVaRestJsonObject::MergeJsonObject(UVaRestJsonObject* InJsonObject, bool Ov UVaRestJsonObject* UVaRestJsonObject::GetObjectField(const FString& FieldName) const { - if (!JsonObj->HasTypedField(FieldName)) + if (!JsonObj.IsValid() || !JsonObj->HasTypedField(FieldName)) { UE_LOG(LogVaRest, Warning, TEXT("No field with name %s of type Object"), *FieldName); - } - - if (!JsonObj.IsValid()) - { return nullptr; } @@ -338,7 +326,7 @@ UVaRestJsonObject* UVaRestJsonObject::GetObjectField(const FString& FieldName) c void UVaRestJsonObject::SetObjectField(const FString& FieldName, UVaRestJsonObject* JsonObject) { - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return; } @@ -358,8 +346,7 @@ TArray UVaRestJsonObject::GetNumberArrayField(const FString& FieldName) } TArray NumberArray; - - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return NumberArray; } @@ -381,7 +368,7 @@ TArray UVaRestJsonObject::GetNumberArrayField(const FString& FieldName) void UVaRestJsonObject::SetNumberArrayField(const FString& FieldName, const TArray& NumberArray) { - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return; } @@ -404,8 +391,7 @@ TArray UVaRestJsonObject::GetStringArrayField(const FString& FieldName) } TArray StringArray; - - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return StringArray; } @@ -427,13 +413,12 @@ TArray UVaRestJsonObject::GetStringArrayField(const FString& FieldName) void UVaRestJsonObject::SetStringArrayField(const FString& FieldName, const TArray& StringArray) { - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return; } TArray< TSharedPtr > EntriesArray; - for (auto String : StringArray) { EntriesArray.Add(MakeShareable(new FJsonValueString(String))); @@ -450,8 +435,7 @@ TArray UVaRestJsonObject::GetBoolArrayField(const FString& FieldName) } TArray BoolArray; - - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return BoolArray; } @@ -473,13 +457,12 @@ TArray UVaRestJsonObject::GetBoolArrayField(const FString& FieldName) void UVaRestJsonObject::SetBoolArrayField(const FString& FieldName, const TArray& BoolArray) { - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return; } TArray< TSharedPtr > EntriesArray; - for (auto Boolean : BoolArray) { EntriesArray.Add(MakeShareable(new FJsonValueBoolean(Boolean))); @@ -496,8 +479,7 @@ TArray UVaRestJsonObject::GetObjectArrayField(const FString& } TArray OutArray; - - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return OutArray; } @@ -523,13 +505,12 @@ TArray UVaRestJsonObject::GetObjectArrayField(const FString& void UVaRestJsonObject::SetObjectArrayField(const FString& FieldName, const TArray& ObjectArray) { - if (!JsonObj.IsValid()) + if (!JsonObj.IsValid() || FieldName.IsEmpty()) { return; } TArray< TSharedPtr > EntriesArray; - for (auto Value : ObjectArray) { EntriesArray.Add(MakeShareable(new FJsonValueObject(Value->GetRootObject()))); From 6fefd2fa7add783fee8f574a6dc5596ac201afa5 Mon Sep 17 00:00:00 2001 From: "v.alyamkin" Date: Tue, 2 Aug 2016 20:36:16 +0300 Subject: [PATCH 12/16] - 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++; From b3b7fc33ce7f18f8d1c8b6b334633a16e720631e Mon Sep 17 00:00:00 2001 From: "v.alyamkin" Date: Tue, 2 Aug 2016 20:53:30 +0300 Subject: [PATCH 13/16] Base64 encoding helpers. Close #75 --- Source/VaRestPlugin/Classes/VaRestLibrary.h | 23 +++++++++++++++++-- Source/VaRestPlugin/Private/VaRestLibrary.cpp | 16 ++++++++++--- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/Source/VaRestPlugin/Classes/VaRestLibrary.h b/Source/VaRestPlugin/Classes/VaRestLibrary.h index b909b71c..2d3153c3 100644 --- a/Source/VaRestPlugin/Classes/VaRestLibrary.h +++ b/Source/VaRestPlugin/Classes/VaRestLibrary.h @@ -52,7 +52,26 @@ class UVaRestLibrary : public UBlueprintFunctionLibrary public: /** Applies percent-encoding to text */ UFUNCTION(BlueprintCallable, Category = "VaRest|Utility") - static FString PercentEncode(const FString& Text); + static FString PercentEncode(const FString& Source); + + /** + * Encodes a FString into a Base64 string + * + * @param Source The string data to convert + * @return A string that encodes the binary data in a way that can be safely transmitted via various Internet protocols + */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Utility", meta = (DisplayName = "Base64 Encode")) + static FString Base64Encode(const FString& Source); + + /** + * Decodes a Base64 string into a FString + * + * @param Source The stringified data to convert + * @param Dest The out buffer that will be filled with the decoded data + * @return True if the buffer was decoded, false if it failed to decode + */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Utility", meta = (DisplayName = "Base64 Decode")) + static bool Base64Decode(const FString& Source, FString& Dest); ////////////////////////////////////////////////////////////////////////// @@ -60,7 +79,7 @@ class UVaRestLibrary : public UBlueprintFunctionLibrary public: /** Easy way to process http requests */ - UFUNCTION(BlueprintCallable, Category = "VaRest|Library", meta = (WorldContext = "WorldContextObject")) + UFUNCTION(BlueprintCallable, Category = "VaRest|Utility", 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)*/ diff --git a/Source/VaRestPlugin/Private/VaRestLibrary.cpp b/Source/VaRestPlugin/Private/VaRestLibrary.cpp index 87c4441d..238a3535 100644 --- a/Source/VaRestPlugin/Private/VaRestLibrary.cpp +++ b/Source/VaRestPlugin/Private/VaRestLibrary.cpp @@ -1,14 +1,14 @@ // Copyright 2016 Vladimir Alyamkin. All Rights Reserved. #include "VaRestPluginPrivatePCH.h" - +#include "Base64.h" ////////////////////////////////////////////////////////////////////////// // Helpers -FString UVaRestLibrary::PercentEncode(const FString& Text) +FString UVaRestLibrary::PercentEncode(const FString& Source) { - FString OutText = Text; + FString OutText = Source; OutText = OutText.Replace(TEXT(" "), TEXT("%20")); OutText = OutText.Replace(TEXT("!"), TEXT("%21")); @@ -36,6 +36,16 @@ FString UVaRestLibrary::PercentEncode(const FString& Text) return OutText; } +FString UVaRestLibrary::Base64Encode(const FString& Source) +{ + return FBase64::Encode(Source); +} + +bool UVaRestLibrary::Base64Decode(const FString& Source, FString& Dest) +{ + return FBase64::Decode(Source, Dest); +} + ////////////////////////////////////////////////////////////////////////// // Easy URL processing From 319a6b6fe211dc7a4660fb453488e943d178fadd Mon Sep 17 00:00:00 2001 From: "v.alyamkin" Date: Tue, 2 Aug 2016 21:23:47 +0300 Subject: [PATCH 14/16] Custom tags for requests. Close #68 --- .../VaRestPlugin/Classes/VaRestRequestJSON.h | 25 +++++++++++++++++++ .../Private/VaRestRequestJSON.cpp | 22 ++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/Source/VaRestPlugin/Classes/VaRestRequestJSON.h b/Source/VaRestPlugin/Classes/VaRestRequestJSON.h index 369d4ddf..d7962a3c 100644 --- a/Source/VaRestPlugin/Classes/VaRestRequestJSON.h +++ b/Source/VaRestPlugin/Classes/VaRestRequestJSON.h @@ -226,6 +226,31 @@ class VARESTPLUGIN_API UVaRestRequestJSON : public UObject FOnStaticRequestFail OnStaticRequestFail; + ////////////////////////////////////////////////////////////////////////// + // Tags + +public: + /** Add tag to this request */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Utility") + void AddTag(FName Tag); + + /** + * Remove tag from this request + * + * @return Number of removed elements + */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Utility") + int32 RemoveTag(FName Tag); + + /** See if this request contains the supplied tag */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Utility") + bool HasTag(FName Tag) const; + +protected: + /** Array of tags that can be used for grouping and categorizing */ + TArray Tags; + + ////////////////////////////////////////////////////////////////////////// // Data diff --git a/Source/VaRestPlugin/Private/VaRestRequestJSON.cpp b/Source/VaRestPlugin/Private/VaRestRequestJSON.cpp index 65940fee..9437c847 100644 --- a/Source/VaRestPlugin/Private/VaRestRequestJSON.cpp +++ b/Source/VaRestPlugin/Private/VaRestRequestJSON.cpp @@ -414,3 +414,25 @@ void UVaRestRequestJSON::OnProcessRequestComplete(FHttpRequestPtr Request, FHttp K->Call(ResponseJsonObj); } } + + +////////////////////////////////////////////////////////////////////////// +// Tags + +void UVaRestRequestJSON::AddTag(FName Tag) +{ + if (Tag != NAME_None) + { + Tags.AddUnique(Tag); + } +} + +int32 UVaRestRequestJSON::RemoveTag(FName Tag) +{ + return Tags.Remove(Tag); +} + +bool UVaRestRequestJSON::HasTag(FName Tag) const +{ + return (Tag != NAME_None) && Tags.Contains(Tag); +} From 732f5d89834d267f5275600f13b5cb9b0aeb50b8 Mon Sep 17 00:00:00 2001 From: "v.alyamkin" Date: Wed, 3 Aug 2016 10:56:45 +0300 Subject: [PATCH 15/16] Minor improvment for blueprint nativization --- Source/VaRestPlugin/Classes/VaRestRequestJSON.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/VaRestPlugin/Classes/VaRestRequestJSON.h b/Source/VaRestPlugin/Classes/VaRestRequestJSON.h index d7962a3c..f789f82d 100644 --- a/Source/VaRestPlugin/Classes/VaRestRequestJSON.h +++ b/Source/VaRestPlugin/Classes/VaRestRequestJSON.h @@ -2,6 +2,11 @@ #pragma once +#include "Delegate.h" +#include "Http.h" +#include "Map.h" +#include "Json.h" + #include "VaRestTypes.h" #include "VaRestRequestJSON.generated.h" From cad3ec6d4122f483209470edddbe5bb745f33194 Mon Sep 17 00:00:00 2001 From: "v.alyamkin" Date: Wed, 3 Aug 2016 11:42:24 +0300 Subject: [PATCH 16/16] Update version to release: 1.1 R 14 --- README.md | 4 ++-- VaRestPlugin.uplugin | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 46b3b0a8..671029fb 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ Key features: * Blueprintable FJsonValue wrapper - **full Json features made for blueprints!** * Both bindable events and **latent functions** are provided to control the asynchronous requests -Check the [Wiki](https://github.com/ufna/VaRest/wiki) tab for plugin usage examples and installation notes. +Check the [Wiki](https://hiazma.atlassian.net/wiki/display/VAR) for plugin usage examples and installation notes. -Current version: **1.1 R 13** (UE 4.11) +Current version: **1.1 R 14** (UE 4.11-4.12) ![SCREENSHOT](SCREENSHOT.jpg) diff --git a/VaRestPlugin.uplugin b/VaRestPlugin.uplugin index c840d989..a3e1b0f1 100644 --- a/VaRestPlugin.uplugin +++ b/VaRestPlugin.uplugin @@ -2,8 +2,8 @@ "FileVersion" : 3, "FriendlyName" : "VaRest", - "Version" : 13, - "VersionName" : "1.1-r13", + "Version" : 14, + "VersionName" : "1.1-r14", "CreatedBy" : "Vladimir Alyamkin", "CreatedByURL" : "http://alyamkin.com", "EngineVersion" : "4.11.0",