Getting HTTP Response Synchronously

I have set up a multiplayer dedicated server that runs using PHP scripts and MySQL databases. I am trying to access the server via HTTP to send/receive game data, starting with something as simple as getting the server status.

I have been able to contact the server successfully with this code:

void ANetwork::getContentsOfURL(FString URL)
{
	serverResponse = NULL;

	TSharedRef<IHttpRequest> HttpRequest = FHttpModule::Get().CreateRequest();
	HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json"));
	HttpRequest->SetURL(URL);
	HttpRequest->SetVerb(TEXT("POST"));

	//Creating JSON Object
	FString json = "{\"auth\":\"" + authenticator = "\"";

	json += "}";

	HttpRequest->SetContentAsString(json);
	HttpRequest->OnProcessRequestComplete().BindUObject(this, &ANetwork::OnResponseReceived);
	HttpRequest->ProcessRequest();
}

void ANetwork::OnResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
{
	GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, Response->GetContentAsString());

	if (!Response.IsValid())
	{
		serverResponse = "FAIL";
	}
	else
	{
		serverResponse = Response->GetContentAsString();
	}
}

And this echoes the proper codes to the debugger, so I know the server is working and the code is in fact getting what it needs to get. However, I need to be able to get the HTTP response as an FString and return it to the caller so that I can use it in-game. Right now this method is asynchronous, which prevents me from returning the response.

How can I make a synchronous HTTP Request so that I can return the response as a string to the caller?

i.e.

FString ANetwork::getContentsOfURL(FString URL)

Did you found a solution for this? Iā€™m facing a similar problem: Sync http requests? - Multiplayer & Networking - Epic Developer Community Forums

Why not simply declare a dynamic multicast in this class that is sending/receiving the http request - and when you receive it here in your above code, take the DYNAMIC DELEGATE MULTICAST #Params() and do a delegate.broadcast()ā€¦ that way you can subscribe to it wherever you need and pickup the response and pass any args you want along the way

Are you sure that you want a synchronous function, because it will likely stall execution for a long time 20ms+ as php/mysql can also take some time, so it would look to the user as if application is stuck for a split second (most likely). A better way is to use Delegates as walldiv suggested or if you like blueprints you can basically inherent your network class from a blueprint and use the varest plugin to implement the requests and responses easily in blueprints.

This class will execute your http request synchronously, but beware using it in your main game thread.

class FSyncHttpExecutor
{
public:
    static TSharedPtr<IHttpResponse, ESPMode::ThreadSafe> ExecuteRequest(TSharedRef<IHttpRequest> HttpRequest, float LoopDelay = 0.1)
    {
        bool bStartedRequest = HttpRequest->ProcessRequest();
        if (!bStartedRequest)
        {
            UE_LOG(LogMyGame, Error, TEXT("Failed to start HTTP Request."));
            return nullptr;
        }

        TSharedPtr<IHttpResponse, ESPMode::ThreadSafe> Response = HttpRequest->GetResponse();
        while (true)
        {
            int32 Code = Response->GetResponseCode();

            if (Code != 0)
                break;

            FPlatformProcess::Sleep(LoopDelay);
        }

        return Response;
    }
};
1 Like

About HTTP response, maybe get some inspiration from this plugin: