ASIHTTPRequest で POST する時の注意点

Pocket
Bookmark this on Delicious

忘れないうちにメモ。

Mac, iOS 開発でのネットワークがらみの実装で大層便利な ASIHTTPRequest というライブラリ(クラス群)があります。
これは CFNetwork のラッパーで、リクエストの非同期処理、キューイングからプログレスバーの制御まで一手にやってくれる超便利ライブラリなのですが、このライブラリを使った HTTP POST でハマったのでメモします。
このライブラリの使い方については、腐るほど出てくるので割愛。

今回は ASIFormDataRequest クラスを使って、画像をアップロードするコードで問題が発生しました。
必要な情報をセットして、NSOperationQueue に突っ込むだけの単純なプログラムなのですが、あるリクエストが成功すると、次のリクエストは必ず失敗します。失敗した場合は、次は必ず成功します。
失敗した場合だけ通るデリゲートメソッド内の処理を穴があくほど確認したのですが、どうも特別なことをしていない。
最後にパケットキャプチャでリクエストとレスポンスのヘッダを見てようやく解決しました。

結論から言うと、リクエストを投げる前に以下の1行を追加します。

[request setShouldAttemptPersistentConnection:NO];

原因は、1個目のコネクションを破棄せずに、再利用していたためでした。
元ソースには以下のように記述されているので、デフォルトはYESになります。

	// When YES, requests will keep the connection to the server alive for a while to allow subsequent requests to re-use it for a substantial speed-boost
	// Persistent connections will not be used if the server explicitly closes the connection
	// Default is YES
	BOOL shouldAttemptPersistentConnection;

失敗する時のレスポンスヘッダを見ると、このようにKeep-Alive状態で返ってきます。

Connection: Keep-Alive\r\n
Keep-Alive: timeout=15, max=100\r\n

例えば、504が発生したりすると、次のリクエストは新たにコネクションを張るため
認証に成功していたという訳。

修正後のレスポンスヘッダは下記の通り。

Connection: close\r\n

この問題は、相手先のサーバの設定にも依るようです。
Keep-Alive状態でも問題なくアップロード出来る場合もありました。
ググっても”Keep-Alive”まで検索ワードを入れないとなかなか出てこないので、丸1日ハマりました・・・。

ASIHTTPRequest documentation- All-Seeing Interactive
ASIHTTPRequestを使って簡単非同期通信 – Tomute’s Notes

Pocket
Bookmark this on Delicious