UE4/C++: http(s) リクエストに FHttpModule 系を使う場合の OnProcessRequestComplete/FHttpRequestCompleteDelegate の成否フラグの注意どころ
UE4 の FHttpModule
の OnProcessRequestComplete
/ FHttpRequestCompleteDelegate
には若干、罠どころがある💀
// UE4/C++ でフレームワークに用意された方法で HTTP リクエストを発行し、 // HTTP レスポンスを得て何かしたい場合のコード例 auto http = &FHttpModule::Get(); auto req = http->CreateRequest(); // ↓罠どころ req->OnProcessRequestComplete().BindLambda( []( auto req, auto res, auto suc ) { /* ... do something ...*/ } ); // ... URLやメソッドの設定が続き ... // リクエストを処理 req->ProcessRequest();
「罠どころ」とコメントを付けた OnProcessRequestComplete
/ FHttpRequestCompleteDelegate
へ束縛するラムダ式( or 束縛可能なオブジェクト)の第3引数が注意の必要なところ。
// OnProcessRequestComplete/FHttpRequestCompleteDelegate の関数としての型(の擬似コード) void OnProcessRequestComplete ( FHttpRequestPtr HttpRequest , FHttpResponsePtr HttpResponse , bool bSucceeded // <-- これ💀 );
↑のようになっているので、例えば GET
でコンテントを拾ってくるような場合に、束縛するファンクター内で bSucceeded
を見ればコンテントの取得成否を確認できそうな気がする。実際間違いではなく、コンテントの取得に成功している場合には、このフラグは true
で呼ばれる。
では、この第3引数の何が罠かと言うと、「 HTTP レスポンスが帰って来ればレスポンスのステータスコードがエラー系であっても true
となる可能性がある」点が罠どころ。接続先のホストが存在しないとか、応答しないとか、そういう場合は false
となるのでコンテント取得の成否として期待通りの false
を得られる。しかし、オシャレなエラーページなどのコンテントの乗ったレスポンスは帰って来るが、 HTTP ステータスコードが 404 や 500 あるいは 302 などの場合にも bSucceeded
は true
となり得て、それは大抵の場合は "リクエストにおいて期待したコンテント" の取得に対しては偽陽性的な応答で、そのような場合にも実装者は false
がこのフラグに与えられる事を期待してしまいかねない罠がある。
// 例えば適当なポエムのテキストデータを HTTP で GET リクエストし、 // ポエムのテキストデータが得られた場合にはポエムを表示、 // 得られなかった場合には失敗の表示を行いたい的な擬似コード [] ( auto, auto res, auto suc ) { if ( suc ) { // 404, 500, 302 などのレスポンスステータスコードの場合も 200 と一緒にこちらへ分岐してしまう UE_LOG( LogTemp, Log, *res->GetContentAsString() ) } else { // こちらへ来るのは接続がそもそも失敗したなどの場合 UE_LOG( LogTemp, Log, TEXT( "FAILED!" ) ) } }
"リクエストにおいて期待したコンテント" の取得の成否の判定は次のように行う必要がある。
[] ( auto, auto res, auto suc ) { if ( suc && res->GetResponseCode() >= 200 && res->GetResponseCode() < 300 ) { // "リクエストにおいて期待したコンテント" が得られた場合にのみここへ分岐する } }