Wait for a HTTP request to be completed at game exit

Hi,

When the game exits, I need to send a HTTP request and to wait for its completion (with a timeout of a couple of seconds) before allowing the game to actually exit.

I could create the http request in the Shutdown method of a module / game instance and call Wait() on the OnProcessRequestComplete delegate of the HttpRequest.

But it would block the game main thread…

Is there a better solution?

Perhaps try the varest plugin. It has a latent request node which you can bind success and failure to events. (Apply URL is a latent function)

@3dRaven

I forgot to mention that I need to make the http request in C++. VaRest seems to dedicated to blueprints.
Moreover, how could it help me to run an http request at game exit?

Thank you

You would need to have the logic built in a way where the user triggers a quit game command => Game does http request => receives reply => calls quit game function.

If you are thinking of catching an ALT + F4 then it would be practically impossible.
The only way that could ever be done is if you had a parallel program that would ping the game and upon not receiving a reply do the request. (sort of like a watchdog in a microcontroller)

I’ll check the stock http requests in c++ and see if there is any async functions.

header

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h" 
#include "Interfaces/IHttpRequest.h" 
#include "HTTPRequestActor.generated.h"


DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FHttpRequestFinished, bool, Finished, FString, Message);
/**
 * 
 */
UCLASS(Blueprintable)
class QREQ_API AHTTPRequestActor : public AActor
{
	GENERATED_BODY()

public:

	UFUNCTION(BlueprintCallable)
	void QuitRequest(FString UrlAddressAsString, FString OutputString);
	
	

	void OnGetUsersResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);

	UPROPERTY(BlueprintAssignable)
	FHttpRequestFinished RequestFinishedDelegate;

};

.CPP

// Fill out your copyright notice in the Description page of Project Settings.


#include "HTTPRequestActor.h"
#include "HttpModule.h" 
#include "Kismet/GameplayStatics.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Interfaces/IHttpResponse.h"

void AHTTPRequestActor::QuitRequest(FString UrlAddressAsString, FString OutputString) {

    TSharedRef<IHttpRequest> HttpRequest = FHttpModule::Get().CreateRequest();

    HttpRequest->SetVerb("POST");
    HttpRequest->SetHeader("Content-Type", "application/json");
    HttpRequest->SetURL(*FString::Printf(TEXT("%s"), *UrlAddressAsString));
    HttpRequest->SetContentAsString(OutputString);
    HttpRequest->OnProcessRequestComplete().BindUObject(this, &AHTTPRequestActor::OnGetUsersResponse);    
    HttpRequest->ProcessRequest();
}


void AHTTPRequestActor::OnGetUsersResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful) 
{
    if (bWasSuccessful)
    {
        TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject());        
        TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(Response->GetContentAsString());
        FJsonSerializer::Deserialize(JsonReader, JsonObject);

        FString string_value_read = JsonObject->GetStringField("success");
        if (string_value_read == "true") {
            RequestFinishedDelegate.Broadcast(true, "Success");
            
            bool IgnorePlatformRestrictions = true;
            if (APlayerController* pc = UGameplayStatics::GetPlayerController(GetWorld(), 0)) {
                UKismetSystemLibrary::QuitGame(GetWorld(), pc, EQuitPreference::Quit, IgnorePlatformRestrictions);
            }

        }
        else {
            RequestFinishedDelegate.Broadcast(false, "Key not found response: " + Response.Get()->GetContentAsString());
            // Request failed
        }
    }
    else {
        FString Message = "Request failed [" + FString::FromInt(Response.Get()->GetResponseCode()) + "] " + Response.Get()->GetContentAsString();
        RequestFinishedDelegate.Broadcast(false, Message);
    }
}


You will need to modify

FString string_value_read = JsonObject->GetStringField("success");
if (string_value_read == "true") {
}

to the needed validation you want from the request response.

You can also bind to an exposed delegate RequestFinishedDelegate and quit that way
(you would have to remove the hard-coded quit)

Example project:
QReq.zip (125.8 KB)

You may want to expose the quit condition as a pin. Not sure what you need so kept it simple.

Executed via QuitRequest