Skip to content

Commit 9ab3463

Browse files
KahncodeFalanwewing328
authored
[cpp-ue4] Added UE4.26 support, (#8964)
* [cpp-ue4] Fixed enum values not being quoted. I'm not sure when this started breaking. * [cpp-ue4] UE 4.26 Compatibility: Replaced TSharedRef<IHttpRequest by FHttpRequestRef for better portability * [cpp-ue4] Improved DateTime parsing * [cpp-ue4] Made HttpFileInput constructors explicit * [cpp-ue4] Added the possibility to retry requests easily with AsyncRetry method on the response and SetAutoRetryCount on the request WIP auto retry [cpp-ue4] Adds support for instant retry * [cpp-ue4] Using TaskGraph instead of TaskGraphMainThread for async retries * update samples * remove trailing spaces Co-authored-by: Jean-Noel Gourdol <jngourdol@stormancer.com> Co-authored-by: William Cheng <wing328hk@gmail.com>
1 parent 4bfe137 commit 9ab3463

26 files changed

Lines changed: 531 additions & 166 deletions

modules/openapi-generator/src/main/resources/cpp-ue4/api-header.mustache

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ public:
2727
{{#operations}}{{#operation}}{{#description}}/* {{{description}}} */
2828
{{/description}}bool {{operationIdCamelCase}}(const {{operationIdCamelCase}}Request& Request, const F{{operationIdCamelCase}}Delegate& Delegate = F{{operationIdCamelCase}}Delegate()) const;
2929
{{/operation}}{{/operations}}
30+
3031
private:
31-
{{#operations}}{{#operation}}void On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate) const;
32+
{{#operations}}{{#operation}}void On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate, int AutoRetryCount) const;
3233
{{/operation}}{{/operations}}
3334
bool IsValid() const;
3435
void HandleResponse(FHttpResponsePtr HttpResponse, bool bSucceeded, Response& InOutResponse) const;

modules/openapi-generator/src/main/resources/cpp-ue4/api-operations-header.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class {{dllapi}} {{classname}}::{{operationIdCamelCase}}Request : public Request
2222
{
2323
public:
2424
virtual ~{{operationIdCamelCase}}Request() {}
25-
void SetupHttpRequest(const TSharedRef<IHttpRequest>& HttpRequest) const final;
25+
void SetupHttpRequest(const FHttpRequestRef& HttpRequest) const final;
2626
FString ComputePath() const final;
2727

2828
{{#allParams}}

modules/openapi-generator/src/main/resources/cpp-ue4/api-operations-source.mustache

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ inline FString ToString(const {{classname}}::{{operationIdCamelCase}}Request::{{
2323
{
2424
{{#enumVars}}
2525
case {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}::{{name}}:
26-
return TEXT({{{value}}});
26+
return TEXT("{{{value}}}");
2727
{{/enumVars}}
2828
}
2929
{{/allowableValues}}
@@ -49,7 +49,7 @@ inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, {{classname
4949
if (JsonValue->TryGetString(TmpValue))
5050
{
5151
static TMap<FString, {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}> StringToEnum = { {{#enumVars}}
52-
{ TEXT({{{value}}}), {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}::{{name}} },{{/enumVars}} };
52+
{ TEXT("{{{value}}}"), {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}::{{name}} },{{/enumVars}} };
5353

5454
const auto Found = StringToEnum.Find(TmpValue);
5555
if(Found)
@@ -109,7 +109,7 @@ FString {{classname}}::{{operationIdCamelCase}}Request::ComputePath() const
109109
return Path;
110110
}
111111

112-
void {{classname}}::{{operationIdCamelCase}}Request::SetupHttpRequest(const TSharedRef<IHttpRequest>& HttpRequest) const
112+
void {{classname}}::{{operationIdCamelCase}}Request::SetupHttpRequest(const FHttpRequestRef& HttpRequest) const
113113
{
114114
static const TArray<FString> Consumes = { {{#consumes}}TEXT("{{{mediaType}}}"){{^-last}}, {{/-last}}{{/consumes}} };
115115
//static const TArray<FString> Produces = { {{#produces}}TEXT("{{{mediaType}}}"){{^-last}}, {{/-last}}{{/produces}} };

modules/openapi-generator/src/main/resources/cpp-ue4/api-source.mustache

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ bool {{classname}}::{{operationIdCamelCase}}(const {{operationIdCamelCase}}Reque
9696
if (!IsValid())
9797
return false;
9898
99-
TSharedRef<IHttpRequest> HttpRequest = FHttpModule::Get().CreateRequest();
99+
FHttpRequestRef HttpRequest = FHttpModule::Get().CreateRequest();
100100
HttpRequest->SetURL(*(Url + Request.ComputePath()));
101101
102102
for(const auto& It : AdditionalHeaderParams)
@@ -106,15 +106,26 @@ bool {{classname}}::{{operationIdCamelCase}}(const {{operationIdCamelCase}}Reque
106106

107107
Request.SetupHttpRequest(HttpRequest);
108108

109-
HttpRequest->OnProcessRequestComplete().BindRaw(this, &{{classname}}::On{{operationIdCamelCase}}Response, Delegate);
109+
HttpRequest->OnProcessRequestComplete().BindRaw(this, &{{classname}}::On{{operationIdCamelCase}}Response, Delegate, Request.GetAutoRetryCount());
110110
return HttpRequest->ProcessRequest();
111111
}
112112

113-
void {{classname}}::On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate) const
113+
void {{classname}}::On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate, int AutoRetryCount) const
114114
{
115115
{{operationIdCamelCase}}Response Response;
116+
Response.SetHttpRequest(HttpRequest);
117+
116118
HandleResponse(HttpResponse, bSucceeded, Response);
117-
Delegate.ExecuteIfBound(Response);
119+
120+
if(!Response.IsSuccessful() && AutoRetryCount > 0)
121+
{
122+
HttpRequest->OnProcessRequestComplete().BindRaw(this, &{{classname}}::On{{operationIdCamelCase}}Response, Delegate, AutoRetryCount - 1);
123+
Response.AsyncRetry();
124+
}
125+
else
126+
{
127+
Delegate.ExecuteIfBound(Response);
128+
}
118129
}
119130

120131
{{/operation}}

modules/openapi-generator/src/main/resources/cpp-ue4/helpers-header.mustache

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ typedef TSharedRef<TJsonWriter<>> JsonWriter;
2222
class {{dllapi}} HttpFileInput
2323
{
2424
public:
25-
HttpFileInput(const TCHAR* InFilePath);
26-
HttpFileInput(const FString& InFilePath);
25+
explicit HttpFileInput(const TCHAR* InFilePath);
26+
explicit HttpFileInput(const FString& InFilePath);
2727
2828
// This will automatically set the content type if not already set
2929
void SetFilePath(const TCHAR* InFilePath);
@@ -53,7 +53,7 @@ class HttpMultipartFormData
5353
{
5454
public:
5555
void SetBoundary(const TCHAR* InBoundary);
56-
void SetupHttpRequest(const TSharedRef<IHttpRequest>& HttpRequest);
56+
void SetupHttpRequest(const FHttpRequestRef& HttpRequest);
5757
5858
void AddStringPart(const TCHAR* Name, const TCHAR* Data);
5959
void AddJsonPart(const TCHAR* Name, const FString& JsonString);
@@ -268,11 +268,15 @@ inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, FString& Va
268268
return false;
269269
}
270270

271+
{{dllapi}} bool ParseDateTime(const FString& DateTimeString, FDateTime& OutDateTime);
272+
271273
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, FDateTime& Value)
272274
{
273275
FString TmpValue;
274276
if (JsonValue->TryGetString(TmpValue))
275-
return FDateTime::Parse(TmpValue, Value);
277+
{
278+
return ParseDateTime(TmpValue, Value);
279+
}
276280
else
277281
return false;
278282
}

modules/openapi-generator/src/main/resources/cpp-ue4/helpers-source.mustache

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ const FString& HttpMultipartFormData::GetBoundary() const
7070
return Boundary;
7171
}
7272

73-
void HttpMultipartFormData::SetupHttpRequest(const TSharedRef<IHttpRequest>& HttpRequest)
73+
void HttpMultipartFormData::SetupHttpRequest(const FHttpRequestRef& HttpRequest)
7474
{
7575
if(HttpRequest->GetVerb() != TEXT("POST"))
7676
{
@@ -183,6 +183,44 @@ void HttpMultipartFormData::AppendString(const TCHAR* Str)
183183
FormData.Append((uint8*)utf8Str.Get(), utf8Str.Length());
184184
}
185185

186+
//////////////////////////////////////////////////////////////////////////
187+
188+
bool ParseDateTime(const FString& DateTimeString, FDateTime& OutDateTime)
189+
{
190+
// Iso8601 Format: DateTime: YYYY-mm-ddTHH:MM:SS(.sss)(Z|+hh:mm|+hhmm|-hh:mm|-hhmm)
191+
{
192+
// We cannot call directly FDateTime::ParseIso8601 because it does not allow for precision beyond the millisecond, but DateTimeString might have more digits
193+
int32 DotIndex;
194+
FString StringToParse = DateTimeString;
195+
if (DateTimeString.FindChar('.', DotIndex))
196+
{
197+
int32 TimeZoneIndex;
198+
if (DateTimeString.FindChar('Z', TimeZoneIndex) || DateTimeString.FindChar('+', TimeZoneIndex) || DateTimeString.FindChar('-', TimeZoneIndex))
199+
{
200+
// The string contains a time zone designator starting at TimeZoneIndex
201+
if (TimeZoneIndex > DotIndex + 4)
202+
{
203+
// Trim to millisecond
204+
StringToParse = DateTimeString.Left(DotIndex + 4) + DateTimeString.RightChop(TimeZoneIndex);
205+
}
206+
}
207+
else
208+
{
209+
// the string does not contain a time zone designator, trim it to the millisecond
210+
StringToParse = DateTimeString.Left(DotIndex + 4);
211+
}
212+
}
213+
214+
if (FDateTime::ParseIso8601(*StringToParse, OutDateTime))
215+
return true;
216+
}
217+
218+
if (FDateTime::ParseHttpDate(DateTimeString, OutDateTime))
219+
return true;
220+
221+
return FDateTime::Parse(DateTimeString, OutDateTime);
222+
}
223+
186224
{{#cppNamespaceDeclarations}}
187225
}
188226
{{/cppNamespaceDeclarations}}

modules/openapi-generator/src/main/resources/cpp-ue4/model-base-header.mustache

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,14 @@ class {{dllapi}} Request
2525
{
2626
public:
2727
virtual ~Request() {}
28-
virtual void SetupHttpRequest(const TSharedRef<IHttpRequest>& HttpRequest) const = 0;
28+
virtual void SetupHttpRequest(const FHttpRequestRef& HttpRequest) const = 0;
2929
virtual FString ComputePath() const = 0;
30+
31+
void SetAutoRetryCount(int InCount) { AutoRetryCount = InCount; }
32+
int GetAutoRetryCount() const { return AutoRetryCount; }
33+
34+
private:
35+
int AutoRetryCount = 0;
3036
};
3137

3238
class {{dllapi}} Response
@@ -38,6 +44,8 @@ public:
3844
void SetSuccessful(bool InSuccessful) { Successful = InSuccessful; }
3945
bool IsSuccessful() const { return Successful; }
4046

47+
void AsyncRetry() const;
48+
4149
virtual void SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode);
4250
EHttpResponseCodes::Type GetHttpResponseCode() const { return ResponseCode; }
4351

@@ -47,11 +55,15 @@ public:
4755
void SetHttpResponse(const FHttpResponsePtr& InHttpResponse) { HttpResponse = InHttpResponse; }
4856
const FHttpResponsePtr& GetHttpResponse() const { return HttpResponse; }
4957

58+
void SetHttpRequest(const FHttpRequestPtr& InHttpRequest) { HttpRequest = InHttpRequest; }
59+
const FHttpRequestPtr& GetHttpRequest() const { return HttpRequest; }
60+
5061
private:
5162
bool Successful;
5263
EHttpResponseCodes::Type ResponseCode;
5364
FString ResponseString;
5465
FHttpResponsePtr HttpResponse;
66+
FHttpRequestPtr HttpRequest;
5567
};
5668

5769
{{#cppNamespaceDeclarations}}

modules/openapi-generator/src/main/resources/cpp-ue4/model-base-source.mustache

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{{>licenseInfo}}
22
#include "{{modelNamePrefix}}BaseModel.h"
33

4+
#include "Async/Async.h"
5+
46
{{#cppNamespaceDeclarations}}
57
namespace {{this}}
68
{
@@ -16,6 +18,15 @@ void Response::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
1618
}
1719
}
1820

21+
void Response::AsyncRetry() const
22+
{
23+
// Unfortunately, it is currently usafe to call ProcessRequest() directly here.
24+
// This is because the HttpManager will remove all references to this HttpRequest in FHttpManager::Tick including the new request we just added, instead of removing just one.
25+
// This will lead to the request's destruction and eventually a crash.
26+
// The only solution is therefore to ensure we are taking an extra reference to the request, and that the request is added after the queue is flushed.
27+
Async(EAsyncExecution::TaskGraph, [AddRef = FHttpRequestPtr(GetHttpRequest())](){ AddRef->ProcessRequest(); });
28+
}
29+
1930
{{#cppNamespaceDeclarations}}
2031
}
2132
{{/cppNamespaceDeclarations}}

modules/openapi-generator/src/main/resources/cpp-ue4/model-source.mustache

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ inline FString ToString(const {{classname}}::Values& Value)
1919
{
2020
{{#enumVars}}
2121
case {{classname}}::Values::{{name}}:
22-
return TEXT({{{value}}});
22+
return TEXT("{{{value}}}");
2323
{{/enumVars}}
2424
}
2525
{{/allowableValues}}
@@ -45,7 +45,7 @@ inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, {{classname
4545
if (JsonValue->TryGetString(TmpValue))
4646
{
4747
static TMap<FString, {{classname}}::Values> StringToEnum = { {{#enumVars}}
48-
{ TEXT({{{value}}}), {{classname}}::Values::{{name}} },{{/enumVars}} };
48+
{ TEXT("{{{value}}}"), {{classname}}::Values::{{name}} },{{/enumVars}} };
4949

5050
const auto Found = StringToEnum.Find(TmpValue);
5151
if(Found)
@@ -69,7 +69,7 @@ inline FString ToString(const {{classname}}::{{{enumName}}}& Value)
6969
{
7070
{{#enumVars}}
7171
case {{classname}}::{{{enumName}}}::{{name}}:
72-
return TEXT({{{value}}});
72+
return TEXT("{{{value}}}");
7373
{{/enumVars}}
7474
}
7575
{{/allowableValues}}
@@ -95,7 +95,7 @@ inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, {{classname
9595
if (JsonValue->TryGetString(TmpValue))
9696
{
9797
static TMap<FString, {{classname}}::{{{enumName}}}> StringToEnum = { {{#enumVars}}
98-
{ TEXT({{{value}}}), {{classname}}::{{{enumName}}}::{{name}} },{{/enumVars}} };
98+
{ TEXT("{{{value}}}"), {{classname}}::{{{enumName}}}::{{name}} },{{/enumVars}} };
9999

100100
const auto Found = StringToEnum.Find(TmpValue);
101101
if(Found)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
5.0.0-SNAPSHOT
1+
5.1.0-SNAPSHOT

0 commit comments

Comments
 (0)