C++ ときどき ごはん、わりとてぃーぶれいく☆

USAGI.NETWORKのなかのひとのブログ。主にC++。

UE4: FHttpModule 系の HTTP リクエスト機構を使い "同期処理" する方法

概要

UE4 で HTTP リクエストを飛ばしたい場合、 HTTP モジュールを有効化し、 FHttpModule::Get で得たオブジェクトから FHttpModule::CreateRequest し、 IHttpRequest のプラットフォームのオブジェクトを得て URL 等の必要なリクエストパラメーター及び OnProcessRequestComplete 等を設定した後、 ProcessRequest する。

この UE4 の HTTP モジュールは "非同期処理" を前提に実装され、インターフェースが提供され、 examples でも非同期処理で HTTP モジュールを扱っている例が幾つか見当たる。

この記事では "諸事情により UE4 の HTTP モジュールを同期処理したい場合" に遭遇した際にどのような実装を行えば良いか整理する。

実装

同期処理でも非同期処理でも同様の部分:

// 1. リクエストを生成
auto request = FHttpModule::Get().CreateRequest();
// 2. リクエストを設定
request->OnProcessRequestComplete().BindLambda( /* 省略 */ );
request->SetURL( /* 省略 */ );
/* 省略 */
// 3. リクエストの開始処理を呼ぶ
request->ProcessRequest();

同期処理したい場合に加える必要のある実装:

// 4.a. HTTP モジュールを強制的に作動させる
FHttpModule::Get().GetHttpManager().Flush( false );

別の実装方法:

// 4.b. HTTP モジュールを "ちまちま" と強制的に作動させる
do
{
  std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
  FHttpModule::Get().GetHttpManager().Tick( 0.010f );
}
while ( request->GetStatus() == EHttpRequestStatus::Processing );

概説

  • IHttpRequest::ProcessRequestFHttpManager へ自身のスマートポインターを登録し処理開始させるなどする
  • FHttpManager::Flush は保持中の IHttpRequest のスマートポインター群のレスポンス取得処理が完了するまで自身の Tick をマシン時間で進める
  • FHttpManager::Tick は保持中のIHttpRequest のスマートポインター群のレスポンス取得処理を進め、 IHttpRequest オブジェクトの Tick も呼ぶ
  • IHttpRequest::Tick レスポンス取得、ステータス更新、タイムアウト処理などを進める

と、いうわけで簡単に同期処理として HTTP モジュールを使いたい場合には非同期処理の実装に加えて FHttpModule::Get().GetHttpManager().Flush( false ) を呼べば良い。

参考

  1. FHttpModule | Unreal Engine
  2. FHttpManager | Unreal Engine
  3. IHttpRequest | Unreal Engine
  4. EHttpRequestStatus::Type | Unreal Engine

Note: 実際にこのような実装が可能かはそれぞれのソースコードの実装詳細を読んで確認している。