2023-06-02 20:28:07 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "GenericPlatform/HttpRequestCommon.h"
2023-11-16 21:27:48 -05:00
# include "GenericPlatform/HttpResponseCommon.h"
2024-01-26 14:25:18 -05:00
# include "HAL/Event.h"
2024-04-09 12:13:24 -04:00
# include "HAL/IConsoleManager.h"
2023-06-02 20:28:07 -04:00
# include "Http.h"
# include "HttpManager.h"
2024-04-09 12:13:24 -04:00
# include "Logging/StructuredLog.h"
2024-01-23 16:08:08 -05:00
# include "Misc/CommandLine.h"
# include "Stats/Stats.h"
2024-05-30 15:47:58 -04:00
PRAGMA_DISABLE_DEPRECATION_WARNINGS
2024-04-09 12:13:24 -04:00
namespace UE : : HttpRequestCommon : : Private
{
TAutoConsoleVariable < bool > CVarHttpLogJsonResponseOnly (
TEXT ( " http.LogJsonResponseOnly " ) ,
true ,
TEXT ( " When log response payload, log json content only " ) ,
ECVF_SaveForNextBoot
) ;
}
2024-06-03 20:21:58 -04:00
TAutoConsoleVariable < bool > CVarHttpSetGeneralFailureReasonFromCommonCode (
TEXT ( " http.SetGeneralFailureReasonFromCommonCode " ) ,
true ,
TEXT ( " Temporary hotfixable cvar: when enabled, set general failure reason from common code instead. " ) ,
ECVF_SaveForNextBoot
) ;
2024-01-23 16:08:08 -05:00
FHttpRequestCommon : : FHttpRequestCommon ( )
: RequestStartTimeAbsoluteSeconds ( FPlatformTime : : Seconds ( ) )
, ActivityTimeoutAt ( 0.0 )
{
}
2023-06-02 20:28:07 -04:00
2023-10-04 15:14:01 -04:00
FString FHttpRequestCommon : : GetURLParameter ( const FString & ParameterName ) const
{
FString ReturnValue ;
if ( TOptional < FString > OptionalParameterValue = FGenericPlatformHttp : : GetUrlParameter ( GetURL ( ) , ParameterName ) )
{
ReturnValue = MoveTemp ( OptionalParameterValue . GetValue ( ) ) ;
}
return ReturnValue ;
}
2023-06-02 20:28:07 -04:00
EHttpRequestStatus : : Type FHttpRequestCommon : : GetStatus ( ) const
{
return CompletionStatus ;
}
2024-02-05 13:23:49 -05:00
const FString & FHttpRequestCommon : : GetEffectiveURL ( ) const
{
return EffectiveURL ;
}
2023-12-05 17:39:04 -05:00
EHttpFailureReason FHttpRequestCommon : : GetFailureReason ( ) const
{
return FailureReason ;
}
2023-06-02 20:28:07 -04:00
bool FHttpRequestCommon : : PreCheck ( ) const
{
2023-12-18 10:32:06 -05:00
// Disabled http request processing
if ( ! FHttpModule : : Get ( ) . IsHttpEnabled ( ) )
{
UE_LOG ( LogHttp , Verbose , TEXT ( " Http disabled. Skipping request. url=%s " ) , * GetURL ( ) ) ;
return false ;
}
2023-06-02 20:28:07 -04:00
// Prevent overlapped requests using the same instance
if ( CompletionStatus = = EHttpRequestStatus : : Processing )
{
UE_LOG ( LogHttp , Warning , TEXT ( " ProcessRequest failed. Still processing last request. " ) ) ;
return false ;
}
// Nothing to do without a valid URL
if ( GetURL ( ) . IsEmpty ( ) )
{
UE_LOG ( LogHttp , Warning , TEXT ( " ProcessRequest failed. No URL was specified. " ) ) ;
return false ;
}
2023-10-04 15:14:01 -04:00
if ( GetVerb ( ) . IsEmpty ( ) )
{
UE_LOG ( LogHttp , Warning , TEXT ( " ProcessRequest failed. No Verb was specified. " ) ) ;
return false ;
}
2023-06-02 20:28:07 -04:00
if ( ! FHttpModule : : Get ( ) . GetHttpManager ( ) . IsDomainAllowed ( GetURL ( ) ) )
{
UE_LOG ( LogHttp , Warning , TEXT ( " ProcessRequest failed. URL '%s' is not using an allowed domain. " ) , * GetURL ( ) ) ;
return false ;
}
2024-01-23 16:08:08 -05:00
if ( bTimedOut )
{
UE_LOG ( LogHttp , Warning , TEXT ( " ProcessRequest failed. Request with URL '%s' already timed out. " ) , * GetURL ( ) ) ;
return false ;
}
2023-06-02 20:28:07 -04:00
return true ;
}
2024-06-25 14:09:55 -04:00
bool FHttpRequestCommon : : WillTriggerMockFailure ( )
{
TOptional < int32 > MockResponseCode = FHttpModule : : Get ( ) . GetHttpManager ( ) . GetMockFailure ( GetURL ( ) ) ;
if ( MockResponseCode . IsSet ( ) )
{
if ( MockResponseCode . GetValue ( ) = = EHttpResponseCodes : : Unknown )
{
int32 HttpConnectionTimeout = FHttpModule : : Get ( ) . GetHttpConnectionTimeout ( ) ;
TWeakPtr < FHttpRequestCommon > RequestWeakPtr ( SharedThis ( this ) ) ;
FHttpModule : : Get ( ) . GetHttpManager ( ) . AddHttpThreadTask ( [ RequestWeakPtr ] ( ) {
if ( TSharedPtr < FHttpRequestCommon > RequestPtr = RequestWeakPtr . Pin ( ) )
{
RequestPtr - > SetFailureReason ( EHttpFailureReason : : ConnectionError ) ;
RequestPtr - > FinishRequestNotInHttpManager ( ) ;
}
} , HttpConnectionTimeout ) ;
}
else
{
InitResponse ( ) ;
ResponseCommon - > SetResponseCode ( MockResponseCode . GetValue ( ) ) ;
MockResponseData ( ) ;
FinishRequestNotInHttpManager ( ) ;
}
return true ;
}
return false ;
}
void FHttpRequestCommon : : InitResponse ( )
{
if ( ! ResponseCommon )
{
FHttpResponsePtr Response = CreateResponse ( ) ;
ResponseCommon = StaticCastSharedPtr < FHttpResponseCommon > ( Response ) ;
}
}
2024-08-23 17:51:09 -04:00
void FHttpRequestCommon : : PopulateUserAgentHeader ( )
{
if ( GetHeader ( TEXT ( " User-Agent " ) ) . IsEmpty ( ) )
{
SetHeader ( TEXT ( " User-Agent " ) , FPlatformHttp : : GetDefaultUserAgent ( ) ) ;
}
}
2023-12-07 13:38:15 -05:00
bool FHttpRequestCommon : : PreProcess ( )
{
ClearInCaseOfRetry ( ) ;
2024-06-25 14:09:55 -04:00
if ( ! PreCheck ( ) )
{
FinishRequestNotInHttpManager ( ) ;
return false ;
}
if ( WillTriggerMockFailure ( ) )
{
// Connect timeout mocking will trigger FinishRequest after a delay, still make sure total timeout
// works when mocking connect timeout
StartTotalTimeoutTimer ( ) ;
return false ;
}
2024-08-23 17:51:09 -04:00
PopulateUserAgentHeader ( ) ;
2024-06-25 14:09:55 -04:00
if ( ! SetupRequest ( ) )
2023-12-07 13:38:15 -05:00
{
FinishRequestNotInHttpManager ( ) ;
return false ;
}
2024-01-23 16:08:08 -05:00
StartTotalTimeoutTimer ( ) ;
2023-12-18 10:32:06 -05:00
UE_LOG ( LogHttp , Verbose , TEXT ( " %p: Verb='%s' URL='%s' " ) , this , * GetVerb ( ) , * GetURL ( ) ) ;
2023-12-07 13:38:15 -05:00
return true ;
}
2024-01-23 16:08:08 -05:00
void FHttpRequestCommon : : PostProcess ( )
{
CleanupRequest ( ) ;
}
2023-12-07 13:38:15 -05:00
void FHttpRequestCommon : : ClearInCaseOfRetry ( )
{
2024-01-23 16:08:08 -05:00
bActivityTimedOut = false ;
2023-12-07 13:38:15 -05:00
FailureReason = EHttpFailureReason : : None ;
2024-01-23 16:08:08 -05:00
bCanceled = false ;
2024-02-05 13:23:49 -05:00
EffectiveURL = GetURL ( ) ;
2024-02-15 09:54:57 -05:00
ResponseCommon . Reset ( ) ;
2023-12-07 13:38:15 -05:00
}
void FHttpRequestCommon : : FinishRequestNotInHttpManager ( )
{
if ( IsInGameThread ( ) )
{
if ( DelegateThreadPolicy = = EHttpRequestDelegateThreadPolicy : : CompleteOnGameThread )
{
FinishRequest ( ) ;
}
else
{
FHttpModule : : Get ( ) . GetHttpManager ( ) . AddHttpThreadTask ( [ StrongThis = StaticCastSharedRef < FHttpRequestCommon > ( AsShared ( ) ) ] ( )
{
StrongThis - > FinishRequest ( ) ;
} ) ;
}
}
else
{
if ( DelegateThreadPolicy = = EHttpRequestDelegateThreadPolicy : : CompleteOnHttpThread )
{
FinishRequest ( ) ;
}
else
{
FHttpModule : : Get ( ) . GetHttpManager ( ) . AddGameThreadTask ( [ StrongThis = StaticCastSharedRef < FHttpRequestCommon > ( AsShared ( ) ) ] ( )
{
StrongThis - > FinishRequest ( ) ;
} ) ;
}
}
}
2023-06-08 14:54:12 -04:00
void FHttpRequestCommon : : SetDelegateThreadPolicy ( EHttpRequestDelegateThreadPolicy InDelegateThreadPolicy )
{
DelegateThreadPolicy = InDelegateThreadPolicy ;
}
EHttpRequestDelegateThreadPolicy FHttpRequestCommon : : GetDelegateThreadPolicy ( ) const
{
return DelegateThreadPolicy ;
}
2024-09-11 05:00:46 -04:00
FString FHttpRequestCommon : : GetOption ( const FName Option ) const
{
const FString * OptionValue = Options . Find ( Option ) ;
if ( OptionValue )
{
return * OptionValue ;
}
return TEXT ( " " ) ;
}
void FHttpRequestCommon : : SetOption ( const FName Option , const FString & OptionValue )
{
Options . Add ( Option , OptionValue ) ;
}
2024-02-15 09:54:57 -05:00
void FHttpRequestCommon : : HandleRequestSucceed ( TSharedPtr < IHttpResponse > InResponse )
2024-01-10 14:19:37 -05:00
{
SetStatus ( EHttpRequestStatus : : Succeeded ) ;
2024-04-09 12:13:24 -04:00
LogResponse ( InResponse ) ;
2024-02-15 09:54:57 -05:00
OnProcessRequestComplete ( ) . ExecuteIfBound ( SharedThis ( this ) , InResponse , true ) ;
2024-01-10 14:19:37 -05:00
FHttpModule : : Get ( ) . GetHttpManager ( ) . RecordStatTimeToConnect ( ConnectTime ) ;
}
2024-06-03 20:21:58 -04:00
void FHttpRequestCommon : : HandleRequestFailed ( TSharedPtr < IHttpResponse > InResponse )
{
if ( CVarHttpSetGeneralFailureReasonFromCommonCode . GetValueOnAnyThread ( ) )
{
if ( FailureReason = = EHttpFailureReason : : None ) // Failure reason was not set by platform, will set it here
{
if ( bCanceled )
{
SetFailureReason ( EHttpFailureReason : : Cancelled ) ;
}
else if ( bTimedOut )
{
SetFailureReason ( EHttpFailureReason : : TimedOut ) ;
}
else if ( ! bUsePlatformActivityTimeout & & bActivityTimedOut )
{
SetFailureReason ( EHttpFailureReason : : ConnectionError ) ;
}
else
{
SetFailureReason ( EHttpFailureReason : : Other ) ;
}
}
SetStatus ( EHttpRequestStatus : : Failed ) ;
}
OnProcessRequestComplete ( ) . ExecuteIfBound ( SharedThis ( this ) , InResponse , false ) ;
}
2023-11-16 21:27:48 -05:00
void FHttpRequestCommon : : SetStatus ( EHttpRequestStatus : : Type InCompletionStatus )
{
CompletionStatus = InCompletionStatus ;
2024-02-15 09:54:57 -05:00
if ( ResponseCommon )
2023-11-16 21:27:48 -05:00
{
ResponseCommon - > SetRequestStatus ( InCompletionStatus ) ;
}
}
2023-12-05 17:39:04 -05:00
void FHttpRequestCommon : : SetFailureReason ( EHttpFailureReason InFailureReason )
{
2024-02-27 19:20:09 -05:00
UE_CLOG ( FailureReason ! = EHttpFailureReason : : None , LogHttp , Warning , TEXT ( " FailureReason had been set to %s, now setting to %s " ) , LexToString ( FailureReason ) , LexToString ( InFailureReason ) ) ;
2023-12-05 17:39:04 -05:00
FailureReason = InFailureReason ;
2024-02-15 09:54:57 -05:00
if ( ResponseCommon )
2023-12-05 17:39:04 -05:00
{
ResponseCommon - > SetRequestFailureReason ( InFailureReason ) ;
}
2023-12-07 13:38:15 -05:00
}
void FHttpRequestCommon : : SetTimeout ( float InTimeoutSecs )
{
TimeoutSecs = InTimeoutSecs ;
}
void FHttpRequestCommon : : ClearTimeout ( )
{
TimeoutSecs . Reset ( ) ;
2024-06-03 15:24:38 -04:00
ResetTimeoutStatus ( ) ;
}
void FHttpRequestCommon : : ResetTimeoutStatus ( )
{
2024-02-08 16:31:09 -05:00
StopTotalTimeoutTimer ( ) ;
2024-06-03 15:24:38 -04:00
bTimedOut = false ;
2023-12-07 13:38:15 -05:00
}
TOptional < float > FHttpRequestCommon : : GetTimeout ( ) const
{
return TimeoutSecs ;
}
float FHttpRequestCommon : : GetTimeoutOrDefault ( ) const
{
2024-01-23 16:08:08 -05:00
return GetTimeout ( ) . Get ( FHttpModule : : Get ( ) . GetHttpTotalTimeout ( ) ) ;
}
2024-03-21 15:03:46 -04:00
void FHttpRequestCommon : : SetActivityTimeout ( float InTimeoutSecs )
{
ActivityTimeoutSecs = InTimeoutSecs ;
}
2024-02-15 09:54:57 -05:00
const FHttpResponsePtr FHttpRequestCommon : : GetResponse ( ) const
{
return ResponseCommon ;
}
2024-01-23 16:08:08 -05:00
void FHttpRequestCommon : : CancelRequest ( )
{
2024-02-27 19:20:09 -05:00
bool bWasCanceled = bCanceled . exchange ( true ) ;
if ( bWasCanceled )
2024-01-23 16:08:08 -05:00
{
return ;
}
2024-02-08 16:31:09 -05:00
StopActivityTimeoutTimer ( ) ;
2024-02-26 18:06:19 -05:00
StopPassingReceivedData ( ) ;
2024-01-23 16:08:08 -05:00
UE_LOG ( LogHttp , Verbose , TEXT ( " HTTP request canceled. URL=%s " ) , * GetURL ( ) ) ;
FHttpModule : : Get ( ) . GetHttpManager ( ) . AddHttpThreadTask ( [ StrongThis = StaticCastSharedRef < FHttpRequestCommon > ( AsShared ( ) ) ] ( )
{
// Run AbortRequest in HTTP thread to avoid potential concurrency issue
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FHttpRequestCommon_AbortRequest ) ;
StrongThis - > AbortRequest ( ) ;
} ) ;
}
void FHttpRequestCommon : : StartActivityTimeoutTimer ( )
{
const FScopeLock CacheLock ( & HttpTaskTimerHandleCriticalSection ) ;
if ( bUsePlatformActivityTimeout )
{
return ;
}
# if !UE_BUILD_SHIPPING
static const bool bNoTimeouts = FParse : : Param ( FCommandLine : : Get ( ) , TEXT ( " NoTimeouts " ) ) ;
if ( bNoTimeouts )
{
return ;
}
# endif
if ( bActivityTimedOut )
{
return ;
}
2024-03-21 15:03:46 -04:00
float HttpActivityTimeout = GetActivityTimeoutOrDefault ( ) ;
2024-01-25 11:01:33 -05:00
if ( HttpActivityTimeout = = 0 )
{
return ;
}
2024-01-23 16:08:08 -05:00
StartActivityTimeoutTimerBy ( HttpActivityTimeout ) ;
ResetActivityTimeoutTimer ( TEXTVIEW ( " Connected " ) ) ;
}
void FHttpRequestCommon : : StartActivityTimeoutTimerBy ( double DelayToTrigger )
{
2024-03-12 17:33:11 -04:00
if ( ActivityTimeoutHttpTaskTimerHandle ! = nullptr )
{
UE_LOG ( LogHttp , Warning , TEXT ( " Request %p already started activity timeout timer " ) , this ) ;
return ;
}
2024-01-23 16:08:08 -05:00
2024-06-25 14:09:55 -04:00
TWeakPtr < FHttpRequestCommon > RequestWeakPtr ( SharedThis ( this ) ) ;
2024-01-23 16:08:08 -05:00
ActivityTimeoutHttpTaskTimerHandle = FHttpModule : : Get ( ) . GetHttpManager ( ) . AddHttpThreadTask ( [ RequestWeakPtr ] ( ) {
2024-06-25 14:09:55 -04:00
if ( TSharedPtr < FHttpRequestCommon > RequestPtr = RequestWeakPtr . Pin ( ) )
2024-01-23 16:08:08 -05:00
{
2024-06-25 14:09:55 -04:00
RequestPtr - > OnActivityTimeoutTimerTaskTrigger ( ) ;
2024-01-23 16:08:08 -05:00
}
} , DelayToTrigger + 0.05 ) ;
}
void FHttpRequestCommon : : OnActivityTimeoutTimerTaskTrigger ( )
{
const FScopeLock CacheLock ( & HttpTaskTimerHandleCriticalSection ) ;
ActivityTimeoutHttpTaskTimerHandle . Reset ( ) ;
2024-03-01 13:19:35 -05:00
if ( EHttpRequestStatus : : IsFinished ( GetStatus ( ) ) )
{
UE_LOG ( LogHttp , Warning , TEXT ( " Request %p had finished when activity timeout timer trigger at [%s] " ) , this , * FDateTime : : Now ( ) . ToString ( TEXT ( " %H:%M:%S:%s " ) ) ) ;
return ;
}
2024-01-23 16:08:08 -05:00
if ( FPlatformTime : : Seconds ( ) < ActivityTimeoutAt )
{
// Check back later
UE_LOG ( LogHttp , VeryVerbose , TEXT ( " Request %p check response timeout at [%s], will check again in %.5f seconds " ) , this , * FDateTime : : Now ( ) . ToString ( TEXT ( " %H:%M:%S:%s " ) ) , ActivityTimeoutAt - FPlatformTime : : Seconds ( ) ) ;
StartActivityTimeoutTimerBy ( ActivityTimeoutAt - FPlatformTime : : Seconds ( ) ) ;
return ;
}
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FHttpRequestCommon_AbortRequest ) ;
bActivityTimedOut = true ;
AbortRequest ( ) ;
2024-03-21 15:03:46 -04:00
UE_LOG ( LogHttp , Log , TEXT ( " Request [%s] timed out at [%s] because of no responding for %0.2f seconds " ) , * GetURL ( ) , * FDateTime : : Now ( ) . ToString ( TEXT ( " %H:%M:%S:%s " ) ) , GetActivityTimeoutOrDefault ( ) ) ;
2024-01-23 16:08:08 -05:00
}
void FHttpRequestCommon : : ResetActivityTimeoutTimer ( FStringView Reason )
{
const FScopeLock CacheLock ( & HttpTaskTimerHandleCriticalSection ) ;
if ( bUsePlatformActivityTimeout )
{
return ;
}
2024-01-25 11:01:33 -05:00
if ( ! ActivityTimeoutHttpTaskTimerHandle )
{
return ;
}
2024-03-21 15:03:46 -04:00
ActivityTimeoutAt = FPlatformTime : : Seconds ( ) + GetActivityTimeoutOrDefault ( ) ;
2024-01-23 16:08:08 -05:00
UE_LOG ( LogHttp , VeryVerbose , TEXT ( " Request [%p] reset response timeout timer at %s: %s " ) , this , * FDateTime : : Now ( ) . ToString ( TEXT ( " %H:%M:%S:%s " ) ) , Reason . GetData ( ) ) ;
}
void FHttpRequestCommon : : StopActivityTimeoutTimer ( )
{
const FScopeLock CacheLock ( & HttpTaskTimerHandleCriticalSection ) ;
if ( bUsePlatformActivityTimeout )
{
return ;
}
2024-01-25 11:01:33 -05:00
if ( ! ActivityTimeoutHttpTaskTimerHandle )
2024-01-23 16:08:08 -05:00
{
2024-01-25 11:01:33 -05:00
return ;
2024-01-23 16:08:08 -05:00
}
2024-01-25 11:01:33 -05:00
FHttpModule : : Get ( ) . GetHttpManager ( ) . RemoveHttpThreadTask ( ActivityTimeoutHttpTaskTimerHandle ) ;
ActivityTimeoutHttpTaskTimerHandle . Reset ( ) ;
2024-01-23 16:08:08 -05:00
}
void FHttpRequestCommon : : StartTotalTimeoutTimer ( )
{
const FScopeLock CacheLock ( & HttpTaskTimerHandleCriticalSection ) ;
# if !UE_BUILD_SHIPPING
static const bool bNoTimeouts = FParse : : Param ( FCommandLine : : Get ( ) , TEXT ( " NoTimeouts " ) ) ;
if ( bNoTimeouts )
{
return ;
}
# endif
float TimeoutOrDefault = GetTimeoutOrDefault ( ) ;
if ( TimeoutOrDefault = = 0 )
{
return ;
}
if ( bTimedOut )
{
return ;
}
// Timeout include retries, so if it's already started before, check this to prevent from adding timer multiple times
if ( TotalTimeoutHttpTaskTimerHandle )
{
return ;
}
TWeakPtr < IHttpRequest > RequestWeakPtr ( AsShared ( ) ) ;
TotalTimeoutHttpTaskTimerHandle = FHttpModule : : Get ( ) . GetHttpManager ( ) . AddHttpThreadTask ( [ RequestWeakPtr ] ( ) {
if ( TSharedPtr < IHttpRequest > RequestPtr = RequestWeakPtr . Pin ( ) )
{
TSharedPtr < FHttpRequestCommon > RequestCommonPtr = StaticCastSharedPtr < FHttpRequestCommon > ( RequestPtr ) ;
RequestCommonPtr - > OnTotalTimeoutTimerTaskTrigger ( ) ;
}
} , TimeoutOrDefault ) ;
}
void FHttpRequestCommon : : OnTotalTimeoutTimerTaskTrigger ( )
{
const FScopeLock CacheLock ( & HttpTaskTimerHandleCriticalSection ) ;
bTimedOut = true ;
2024-03-01 13:19:35 -05:00
if ( EHttpRequestStatus : : IsFinished ( GetStatus ( ) ) )
2024-01-23 16:08:08 -05:00
{
2024-03-01 13:19:35 -05:00
return ;
2024-01-23 16:08:08 -05:00
}
2024-03-01 13:19:35 -05:00
StopActivityTimeoutTimer ( ) ;
QUICK_SCOPE_CYCLE_COUNTER ( STAT_FHttpRequestCommon_AbortRequest ) ;
UE_LOG ( LogHttp , Warning , TEXT ( " HTTP request timed out after %0.2f seconds URL=%s " ) , GetTimeoutOrDefault ( ) , * GetURL ( ) ) ;
AbortRequest ( ) ;
2024-01-23 16:08:08 -05:00
}
void FHttpRequestCommon : : StopTotalTimeoutTimer ( )
{
const FScopeLock CacheLock ( & HttpTaskTimerHandleCriticalSection ) ;
if ( TotalTimeoutHttpTaskTimerHandle )
{
FHttpModule : : Get ( ) . GetHttpManager ( ) . RemoveHttpThreadTask ( TotalTimeoutHttpTaskTimerHandle ) ;
TotalTimeoutHttpTaskTimerHandle . Reset ( ) ;
}
}
2024-02-08 16:31:09 -05:00
2024-01-23 16:08:08 -05:00
void FHttpRequestCommon : : Shutdown ( )
{
FHttpRequestImpl : : Shutdown ( ) ;
2024-02-26 18:06:19 -05:00
StopPassingReceivedData ( ) ;
2024-01-23 16:08:08 -05:00
StopActivityTimeoutTimer ( ) ;
StopTotalTimeoutTimer ( ) ;
2023-12-07 13:38:15 -05:00
}
2024-01-19 15:35:30 -05:00
2024-01-26 14:25:18 -05:00
void FHttpRequestCommon : : ProcessRequestUntilComplete ( )
{
checkf ( ! OnProcessRequestComplete ( ) . IsBound ( ) , TEXT ( " OnProcessRequestComplete is not supported for sync call " ) ) ;
SetDelegateThreadPolicy ( EHttpRequestDelegateThreadPolicy : : CompleteOnHttpThread ) ;
FEvent * Event = FPlatformProcess : : GetSynchEventFromPool ( true ) ;
OnProcessRequestComplete ( ) . BindLambda ( [ Event ] ( FHttpRequestPtr HttpRequest , FHttpResponsePtr HttpResponse , bool bSucceeded ) {
Event - > Trigger ( ) ;
} ) ;
ProcessRequest ( ) ;
Event - > Wait ( ) ;
FPlatformProcess : : ReturnSynchEventToPool ( Event ) ;
}
2024-06-25 14:09:55 -04:00
void FHttpRequestCommon : : HandleStatusCodeReceived ( int32 StatusCode )
{
if ( ResponseCommon )
{
ResponseCommon - > SetResponseCode ( StatusCode ) ;
}
TriggerStatusCodeReceivedDelegate ( StatusCode ) ;
}
2024-01-19 15:35:30 -05:00
void FHttpRequestCommon : : TriggerStatusCodeReceivedDelegate ( int32 StatusCode )
{
if ( DelegateThreadPolicy = = EHttpRequestDelegateThreadPolicy : : CompleteOnHttpThread )
{
OnStatusCodeReceived ( ) . ExecuteIfBound ( SharedThis ( this ) , StatusCode ) ;
}
else if ( OnStatusCodeReceived ( ) . IsBound ( ) )
{
FHttpModule : : Get ( ) . GetHttpManager ( ) . AddGameThreadTask ( [ StrongThis = AsShared ( ) , StatusCode ] ( )
{
StrongThis - > OnStatusCodeReceived ( ) . ExecuteIfBound ( StrongThis , StatusCode ) ;
} ) ;
}
}
2024-02-05 13:23:49 -05:00
void FHttpRequestCommon : : SetEffectiveURL ( const FString & InEffectiveURL )
{
EffectiveURL = InEffectiveURL ;
2024-02-15 09:54:57 -05:00
if ( ResponseCommon )
2024-02-05 13:23:49 -05:00
{
ResponseCommon - > SetEffectiveURL ( EffectiveURL ) ;
}
}
2024-02-26 18:06:19 -05:00
bool FHttpRequestCommon : : SetResponseBodyReceiveStream ( TSharedRef < FArchive > Stream )
{
const FScopeLock StreamLock ( & ResponseBodyReceiveStreamCriticalSection ) ;
ResponseBodyReceiveStream = Stream ;
bInitializedWithValidStream = true ;
return true ;
}
2024-04-09 12:13:24 -04:00
float FHttpRequestCommon : : GetElapsedTime ( ) const
{
return ElapsedTime ;
}
2024-05-30 15:47:58 -04:00
void FHttpRequestCommon : : StartWaitingInQueue ( )
{
TimeStartedWaitingInQueue = FPlatformTime : : Seconds ( ) ;
}
float FHttpRequestCommon : : GetTimeStartedWaitingInQueue ( ) const
{
check ( TimeStartedWaitingInQueue ! = 0 ) ;
return TimeStartedWaitingInQueue ;
}
2024-02-26 18:06:19 -05:00
bool FHttpRequestCommon : : PassReceivedDataToStream ( void * Ptr , int64 Length )
{
const FScopeLock StreamLock ( & ResponseBodyReceiveStreamCriticalSection ) ;
if ( ! ResponseBodyReceiveStream )
{
return false ;
}
ResponseBodyReceiveStream - > Serialize ( Ptr , Length ) ;
return ! ResponseBodyReceiveStream - > GetError ( ) ;
}
void FHttpRequestCommon : : StopPassingReceivedData ( )
{
const FScopeLock StreamLock ( & ResponseBodyReceiveStreamCriticalSection ) ;
ResponseBodyReceiveStream = nullptr ;
}
2024-03-21 15:03:46 -04:00
2024-04-09 12:13:24 -04:00
2024-03-21 15:03:46 -04:00
float FHttpRequestCommon : : GetActivityTimeoutOrDefault ( ) const
{
return ActivityTimeoutSecs . Get ( FHttpModule : : Get ( ) . GetHttpActivityTimeout ( ) ) ;
2024-03-21 16:22:12 -04:00
}
2024-03-21 15:03:46 -04:00
2024-03-21 16:22:12 -04:00
bool FHttpRequestCommon : : SetContentAsStreamedFileDefaultImpl ( const FString & Filename )
{
UE_LOG ( LogHttp , Verbose , TEXT ( " FHttpRequestCommon::SetContentAsStreamedFileDefaultImpl() - %s " ) , * Filename ) ;
if ( CompletionStatus = = EHttpRequestStatus : : Processing )
{
UE_LOG ( LogHttp , Warning , TEXT ( " FHttpRequestCommon::SetContentAsStreamedFileDefaultImpl() - attempted to set content on a request that is inflight " ) ) ;
return false ;
}
RequestPayload = MakeUnique < FRequestPayloadInFileStream > ( * Filename ) ;
return true ;
}
bool FHttpRequestCommon : : OpenRequestPayloadDefaultImpl ( )
{
if ( ! RequestPayload )
{
return true ;
}
if ( ! RequestPayload - > Open ( ) )
{
return false ;
}
if ( ( GetVerb ( ) . IsEmpty ( ) | | GetVerb ( ) . Equals ( TEXT ( " GET " ) , ESearchCase : : IgnoreCase ) ) & & RequestPayload - > GetContentLength ( ) > 0 )
{
UE_LOG ( LogHttp , Warning , TEXT ( " An HTTP Get request cannot contain a payload. " ) ) ;
return false ;
}
return true ;
}
void FHttpRequestCommon : : CloseRequestPayloadDefaultImpl ( )
{
if ( RequestPayload . IsValid ( ) )
{
RequestPayload - > Close ( ) ;
}
}
2024-04-09 12:13:24 -04:00
# define UE_HTTP_LOG_RESPONSE_PRIVATE(Condition, Format, ...) \
if ( Condition ) \
{ \
UE_LOG ( LogHttp , Warning , Format , # # __VA_ARGS__ ) ; \
} \
else \
{ \
UE_LOG ( LogHttp , Verbose , Format , # # __VA_ARGS__ ) ; \
}
void FHttpRequestCommon : : LogResponse ( const TSharedPtr < IHttpResponse > & InResponse )
{
2024-05-16 10:44:04 -04:00
bool bShouldLogResponse = FHttpModule : : Get ( ) . GetHttpManager ( ) . ShouldLogResponse ( GetURL ( ) ) ;
2024-04-09 12:13:24 -04:00
UE_HTTP_LOG_RESPONSE_PRIVATE ( bShouldLogResponse , TEXT ( " %p %s %s completed with code %d after %.2fs. Content length: %ld " ) , this , * GetVerb ( ) , * GetURL ( ) , InResponse - > GetResponseCode ( ) , ElapsedTime , InResponse - > GetContentLength ( ) ) ;
TArray < FString > AllHeaders = InResponse - > GetAllHeaders ( ) ;
for ( const FString & HeaderStr : AllHeaders )
{
if ( ! HeaderStr . StartsWith ( TEXT ( " Authorization " ) ) & & ! HeaderStr . StartsWith ( TEXT ( " Set-Cookie " ) ) )
{
UE_HTTP_LOG_RESPONSE_PRIVATE ( bShouldLogResponse , TEXT ( " %p Response Header %s " ) , this , * HeaderStr ) ;
}
}
if ( ! bShouldLogResponse | | InResponse - > GetContentLength ( ) = = 0 )
{
return ;
}
if ( UE : : HttpRequestCommon : : Private : : CVarHttpLogJsonResponseOnly . GetValueOnAnyThread ( ) )
{
bool bIsContentTypeJson = ! InResponse - > GetHeader ( TEXT ( " Content-Type " ) ) . Compare ( TEXT ( " application/json " ) , ESearchCase : : IgnoreCase ) ;
if ( ! bIsContentTypeJson )
return ;
}
const TArray < uint8 > & Content = InResponse - > GetContent ( ) ;
FUtf8StringView ResponseStringView ( reinterpret_cast < const UTF8CHAR * > ( Content . GetData ( ) ) , Content . Num ( ) ) ;
int32 StartPos = 0 ;
int32 EndPos = 0 ;
// The response payload could exceed the maximum length supported by UE_LOG/UE_LOGFMT, so log it line by line if there are multiple lines
while ( StartPos < ResponseStringView . Len ( ) )
{
EndPos = ResponseStringView . Find ( " \n " , StartPos ) ;
if ( EndPos ! = INDEX_NONE )
{
FUtf8StringView Line ( & ResponseStringView [ StartPos ] , EndPos - StartPos ) ;
UE_LOGFMT ( LogHttp , Warning , " {Line} " , Line ) ;
}
else
{
FUtf8StringView Remain ( & ResponseStringView [ StartPos ] , ResponseStringView . Len ( ) - StartPos ) ;
UE_LOGFMT ( LogHttp , Warning , " {Remain} " , Remain ) ;
break ;
}
StartPos = EndPos + 1 ;
}
2024-05-30 15:47:58 -04:00
}
PRAGMA_ENABLE_DEPRECATION_WARNINGS