SIOJRequestJSON.h 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // Modifications Copyright 2018-current Getnamo. All Rights Reserved
  2. // Copyright 2014 Vladimir Alyamkin. All Rights Reserved.
  3. #pragma once
  4. #include "Delegates/Delegate.h"
  5. #include "Http.h"
  6. #include "Runtime/Core/Public/Containers/Map.h"
  7. #include "Runtime/Json/Public/Dom/JsonObject.h"
  8. #include "Runtime/Json/Public/Dom/JsonValue.h"
  9. #include "LatentActions.h"
  10. #include "CULambdaRunnable.h"
  11. #include "Engine/LatentActionManager.h"
  12. #include "SIOJTypes.h"
  13. #include "SIOJRequestJSON.generated.h"
  14. /**
  15. * @author Original latent action class by https://github.com/unktomi
  16. */
  17. template <class T> class SIOJSON_API FSIOJLatentAction : public FPendingLatentAction
  18. {
  19. public:
  20. virtual void Call(const T &Value)
  21. {
  22. Result = Value;
  23. Called = true;
  24. }
  25. void operator()(const T &Value)
  26. {
  27. Call(Value);
  28. }
  29. void Cancel();
  30. FSIOJLatentAction(FWeakObjectPtr RequestObj, T& ResultParam, const FLatentActionInfo& LatentInfo) :
  31. Called(false),
  32. Request(RequestObj),
  33. ExecutionFunction(LatentInfo.ExecutionFunction),
  34. OutputLink(LatentInfo.Linkage),
  35. CallbackTarget(LatentInfo.CallbackTarget),
  36. Result(ResultParam)
  37. {
  38. }
  39. virtual void UpdateOperation(FLatentResponse& Response) override
  40. {
  41. Response.FinishAndTriggerIf(Called, ExecutionFunction, OutputLink, CallbackTarget);
  42. }
  43. virtual void NotifyObjectDestroyed()
  44. {
  45. Cancel();
  46. }
  47. virtual void NotifyActionAborted()
  48. {
  49. Cancel();
  50. }
  51. private:
  52. bool Called;
  53. FWeakObjectPtr Request;
  54. public:
  55. const FName ExecutionFunction;
  56. const int32 OutputLink;
  57. const FWeakObjectPtr CallbackTarget;
  58. T &Result;
  59. };
  60. /** Generate a delegates for callback events */
  61. DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRequestComplete, class USIOJRequestJSON*, Request);
  62. DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRequestFail, class USIOJRequestJSON*, Request);
  63. DECLARE_MULTICAST_DELEGATE_OneParam(FOnStaticRequestComplete, class USIOJRequestJSON*);
  64. DECLARE_MULTICAST_DELEGATE_OneParam(FOnStaticRequestFail, class USIOJRequestJSON*);
  65. /**
  66. * General helper class http requests via blueprints
  67. */
  68. UCLASS(BlueprintType, Blueprintable)
  69. class SIOJSON_API USIOJRequestJSON : public UObject
  70. {
  71. GENERATED_UCLASS_BODY()
  72. public:
  73. //////////////////////////////////////////////////////////////////////////
  74. // Construction
  75. /** Creates new request (totally empty) */
  76. UFUNCTION(BlueprintCallable, meta = (DisplayName = "Construct Json Request (Empty)", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"), Category = "SIOJ|Request")
  77. static USIOJRequestJSON* ConstructRequest(UObject* WorldContextObject);
  78. /** Creates new request with defined verb and content type */
  79. UFUNCTION(BlueprintCallable, meta = (DisplayName = "Construct Json Request", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"), Category = "SIOJ|Request")
  80. static USIOJRequestJSON* ConstructRequestExt(UObject* WorldContextObject, ESIORequestVerb Verb, ESIORequestContentType ContentType);
  81. /** Set verb to the request */
  82. UFUNCTION(BlueprintCallable, Category = "SIOJ|Request")
  83. void SetVerb(ESIORequestVerb Verb);
  84. /** Set custom verb to the request */
  85. UFUNCTION(BlueprintCallable, Category = "SIOJ|Request")
  86. void SetCustomVerb(FString Verb);
  87. /** Set content type to the request. If you're using the x-www-form-urlencoded,
  88. * params/constaints should be defined as key=ValueString pairs from Json data */
  89. UFUNCTION(BlueprintCallable, Category = "SIOJ|Request")
  90. void SetContentType(ESIORequestContentType ContentType);
  91. /** Set content type of the request for binary post data */
  92. UFUNCTION(BlueprintCallable, Category = "SIOJ|Request")
  93. void SetBinaryContentType(const FString &ContentType);
  94. /** Set content of the request for binary post data */
  95. UFUNCTION(BlueprintCallable, Category = "SIOJ|Request")
  96. void SetBinaryRequestContent(const TArray<uint8> &Content);
  97. /** Sets optional header info */
  98. UFUNCTION(BlueprintCallable, Category = "SIOJ|Request")
  99. void SetHeader(const FString& HeaderName, const FString& HeaderValue);
  100. //////////////////////////////////////////////////////////////////////////
  101. // Destruction and reset
  102. /** Reset all internal saved data */
  103. UFUNCTION(BlueprintCallable, Category = "SIOJ|Utility")
  104. void ResetData();
  105. /** Reset saved request data */
  106. UFUNCTION(BlueprintCallable, Category = "SIOJ|Request")
  107. void ResetRequestData();
  108. /** Reset saved response data */
  109. UFUNCTION(BlueprintCallable, Category = "SIOJ|Response")
  110. void ResetResponseData();
  111. /** Cancel latent response waiting */
  112. UFUNCTION(BlueprintCallable, Category = "SIOJ|Response")
  113. void Cancel();
  114. //////////////////////////////////////////////////////////////////////////
  115. // JSON data accessors
  116. /** Get the Request Json object */
  117. UFUNCTION(BlueprintCallable, Category = "SIOJ|Request")
  118. USIOJsonObject* GetRequestObject();
  119. /** Set the Request Json object */
  120. UFUNCTION(BlueprintCallable, Category = "SIOJ|Request")
  121. void SetRequestObject(USIOJsonObject* JsonObject);
  122. /** Get the Response Json object */
  123. UFUNCTION(BlueprintCallable, Category = "SIOJ|Response")
  124. USIOJsonObject* GetResponseObject();
  125. /** Set the Response Json object */
  126. UFUNCTION(BlueprintCallable, Category = "SIOJ|Response")
  127. void SetResponseObject(USIOJsonObject* JsonObject);
  128. ///////////////////////////////////////////////////////////////////////////
  129. // Request/response data access
  130. /** Get url of http request */
  131. UFUNCTION(BlueprintCallable, Category = "SIOJ|Request")
  132. FString GetURL();
  133. /** Get status of http request */
  134. UFUNCTION(BlueprintCallable, Category = "SIOJ|Request")
  135. ESIORequestStatus GetStatus();
  136. /** Get the response code of the last query */
  137. UFUNCTION(BlueprintCallable, Category = "SIOJ|Response")
  138. int32 GetResponseCode();
  139. /** Get value of desired response header */
  140. UFUNCTION(BlueprintCallable, Category = "SIOJ|Response")
  141. FString GetResponseHeader(const FString HeaderName);
  142. /** Get list of all response headers */
  143. UFUNCTION(BlueprintCallable, Category = "SIOJ|Response")
  144. TArray<FString> GetAllResponseHeaders();
  145. //////////////////////////////////////////////////////////////////////////
  146. // URL processing
  147. /** Open URL with current setup */
  148. UFUNCTION(BlueprintCallable, Category = "SIOJ|Request")
  149. virtual void ProcessURL(const FString& Url = TEXT("http://alyamkin.com"));
  150. /** Open URL in latent mode */
  151. UFUNCTION(BlueprintCallable, Category = "SIOJ|Request", meta = (Latent, LatentInfo = "LatentInfo", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
  152. virtual void ApplyURL(const FString& Url, USIOJsonObject *&Result, UObject* WorldContextObject, struct FLatentActionInfo LatentInfo);
  153. /** Apply current internal setup to request and process it */
  154. void ProcessRequest();
  155. //////////////////////////////////////////////////////////////////////////
  156. // Request callbacks
  157. private:
  158. /** Internal bind function for the IHTTPRequest::OnProcessRequestCompleted() event */
  159. void OnProcessRequestComplete(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
  160. void OnProcessRequestCompleteBinaryResult(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
  161. public:
  162. /** Event occured when the request has been completed */
  163. UPROPERTY(BlueprintAssignable, Category = "SIOJ|Event")
  164. FOnRequestComplete OnRequestComplete;
  165. /** Event occured when the request wasn't successfull */
  166. UPROPERTY(BlueprintAssignable, Category = "SIOJ|Event")
  167. FOnRequestFail OnRequestFail;
  168. /** Event occured when the request has been completed */
  169. FOnStaticRequestComplete OnStaticRequestComplete;
  170. /** Event occured when the request wasn't successfull */
  171. FOnStaticRequestFail OnStaticRequestFail;
  172. //////////////////////////////////////////////////////////////////////////
  173. // Tags
  174. public:
  175. /** Add tag to this request */
  176. UFUNCTION(BlueprintCallable, Category = "SIOJ|Utility")
  177. void AddTag(FName Tag);
  178. /**
  179. * Remove tag from this request
  180. *
  181. * @return Number of removed elements
  182. */
  183. UFUNCTION(BlueprintCallable, Category = "SIOJ|Utility")
  184. int32 RemoveTag(FName Tag);
  185. /** See if this request contains the supplied tag */
  186. UFUNCTION(BlueprintCallable, Category = "SIOJ|Utility")
  187. bool HasTag(FName Tag) const;
  188. protected:
  189. /** Array of tags that can be used for grouping and categorizing */
  190. TArray<FName> Tags;
  191. //////////////////////////////////////////////////////////////////////////
  192. // Data
  193. public:
  194. /** Request response stored as a string */
  195. UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "SIOJ|Response")
  196. FString ResponseContent;
  197. /** Is the response valid JSON? */
  198. UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "SIOJ|Response")
  199. bool bIsValidJsonResponse;
  200. /** If this is true it will call back on the binary callback instead of json */
  201. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SIOJ|Response")
  202. bool bShouldHaveBinaryResponse;
  203. TFunction<void(TArray<uint8>&)> OnProcessURLCompleteCallback;
  204. TArray<uint8> ResultBinaryData;
  205. protected:
  206. /** Latent action helper */
  207. FSIOJLatentAction<USIOJsonObject*>* ContinueAction;
  208. /** Internal request data stored as JSON */
  209. UPROPERTY()
  210. USIOJsonObject* RequestJsonObj;
  211. UPROPERTY()
  212. TArray<uint8> RequestBytes;
  213. UPROPERTY()
  214. FString BinaryContentType;
  215. /** Response data stored as JSON */
  216. UPROPERTY()
  217. USIOJsonObject* ResponseJsonObj;
  218. /** Verb for making request (GET,POST,etc) */
  219. ESIORequestVerb RequestVerb;
  220. /** Content type to be applied for request */
  221. ESIORequestContentType RequestContentType;
  222. /** Mapping of header section to values. Used to generate final header string for request */
  223. TMap<FString, FString> RequestHeaders;
  224. /** Cached key/value header pairs. Parsed once request completes */
  225. TMap<FString, FString> ResponseHeaders;
  226. /** Http Response code */
  227. int32 ResponseCode;
  228. /** Custom verb that will be used with RequestContentType == CUSTOM */
  229. FString CustomVerb;
  230. /** Request we're currently processing */
  231. FHttpRequestRef HttpRequest = FHttpModule::Get().CreateRequest();
  232. };