URLSession の困った挙動

こんにちは。モバイル開発チームに所属している小島です。

先日、URLSessionを使っててバグっぽい挙動を見つけたのでメモしておきます。

URLSession とは

詳しく書く必要はないかと思いますが、Swift (iOS アプリ開発) で使用する通信クライアントです。HTTP 接続で API を呼び出すのに使用しています。

どんな挙動だったか?

GET メソッドで、リクエストボディを設定した際に、0 のバイト配列でデータが送信されました。

経緯

事の発端は、弊社のクラウドサービスの API を呼び出す処理を書いていたときのことです。 https://developer.cybozu.io/hc/ja/articles/202331474#step2

リクエストパラメータはかなり複雑で、クエリ文字列で送るよりリクエストボディで送る方が json で渡せるためパラメータの構築は楽ちんです。

ところが、実際に動作させてみるとどうもうまくいきません。 最初は認証周りでうまく行ってないのかと思いましたが、curl で同じようなリクエストを出せば期待通りの結果になるので、設定してるリクエスト情報に問題はなさそうです。

仕方がないので、プロキシを通して実際の通信の中身を見てみることにしました。すると以下のような結果に...

httpbody
httpbody.png

なんと、Content−Length がちゃんと設定されているにもかかわらず、中身が全部ゼロじゃないですか😲 これではうまくいくはずもないですね。

RFC的には?

まあ、GET でリクエストボディ送るのはどうなん?とも思ってたのでググってみます。

https://tools.ietf.org/html/rfc7231#section-4.3.1

リクエストボディを送ったときの挙動は未定義で、サーバーによっては接続を拒否する場合があるとなっています。 つまり、送っては駄目とは書いてないけど、その挙動はサーバー側の実装依存ということです。

結論

というわけで、iOS アプリの開発では GET でリクエストボディを送るのはやめたほうが良さそうです。 とはいえ、全く送らないならまだしも中途半端な状態で送られるのはかなりバグっぽい挙動だと感じます。