UE5 hangs when using future/promises when making HTTP requests

Hi,

I am using this link - Call REST API using HTTP & JSON from UE5 C++ | Community tutorial - as a reference to make HTTP requests to REST API and get responses. I am using future/promise so that I can get the response string and return it to blueprint where I can print the string.

This is how my code looks like:

TSharedRef<IHttpRequest, ESPMode::ThreadSafe> build_get_request(...)
{
  auto& http_module = FHttpModule::Get();
  TSharedRef<IHttpRequest, ESPMode::ThreadSafe> request = http_module.CreateRequest();
  request->SetVerb(TEXT("GET"));
  request->SetURL("REST_API_URL");
  return request;
}

FString send_get_request(...)
{
  auto http_request = build_get_request(...);

  TPromise<FString> http_response_promise;
  TFuture<FString> http_response_future = http_response_promise.GetFuture();

  static auto callback = [&http_response_promise](FHttpRequestPtr request_ptr, FHttpResponsePtr response_ptr, bool connected_successfully) mutable {
    if (!connected_successfully)
    {
      switch (request_ptr->GetStatus())
      {
        case EHttpRequestStatus::Failed_ConnectionError:
          UE_LOG(LogTemp, Error, TEXT("Connection failed"));
          break;
        default:
          UE_LOG(LogTemp, Error, TEXT("Request failed"));
      }
      http_response_promise.SetValue("ERROR");
      return;
    }
    if (response_ptr->GetResponseCode() != EHttpResponseCodes::Ok)
    {
      auto response_code = static_cast<EHttpResponseCodes::Type>(response_ptr->GetResponseCode());
      UE_LOG(LogTemp,
             Error,
             TEXT("%s"),
             *EHttpResponseCodes::GetDescription(response_code).ToString());
      http_response_promise.SetValue("ERROR");
      return;
    }

    UE_LOG(LogTemp, Display, TEXT("Response %s"), *response_ptr->GetContentAsString());
    // Set the promise value here
    http_response_promise.SetValue(response_ptr->GetContentAsString());
  };
  http_request->OnProcessRequestComplete().BindLambda(
      [](FHttpRequestPtr request_ptr, FHttpResponsePtr response_ptr, bool connected_successfully) {
        callback(request_ptr, response_ptr, connected_successfully);
      });
  if (!http_request->ProcessRequest())
  {
    return "Couldn't start request";
  }
  UE_LOG(LogTemp, Display, TEXT("Request has been started"));
  auto response = http_response_future.Get();
  return response;
}

When I hit Play in UE5 editor, it hangs. I tried to debug and it seems it blocks in TFuture::Get() call when it calls TFutureState::GetResult(). I can see the below loop which blocks for a long time:

const InternalResultType& GetResult() const
{
  while (!IsComplete())
  {
    WaitFor(FTimespan::MaxValue());
  }

  return *Result.GetTypedPtr();
}

How can I get this working properly?

It’s blocking because Get() waits until the value is available before continuing. If you want to do async c++ functions in blueprints I’d suggest doing it like this Creating Asynchronous Blueprint Nodes - Old UE4 Wiki

Thanks for the response. The problem is when I call ProcessRequest, it puts the request to some queue which later gets picked up by another thread which sends the request. When this request gets completed, that callback function gets called where I would expect it to set the promise value and thus unblock Get() which doesn’t happen in my case - it blocks infinitely.

You’re right that http requests are processed in a different thread. However, the OnProcessRequestComplete() delegate is called on the game thread which is why it blocks infinitely as the delegate will never be called.

Really? I thought it would be called from the other thread which is processing responses (usually this is what happens right?). That’s a weird design in UE5 then.

In 5.3 they actually added a way to change which thread a request will be completed on by using this: IHttpRequest::SetDelegateThreadPolicy | Unreal Engine 5.2 Documentation

still wouldn’t recommend this way of doing it since you would be blocking the game thread until its done