🔣

Xcode15.3でビルドしたUnityアプリをiOS17で実行した際に%が二重にURLエンコードされる件とサーバ側回避策

2024/05/01に公開

概要

  • Xcode15.3でビルドしたUnityアプリをiOS17で実行した際に%が二重にURLエンコードされる問題があった
  • サーバ(Rails)側で回避策を講じた

環境

  • Unity2021.3.29f1
  • Xcode15.3

発生した現象

運用中のUnityアプリで、Xcodeを15.3にバージョンアップしたビルドで動作確認をしていたところ、iOS17のみサーバ(Rails)の特定APIアクセス時にサーバ側アプリケーションエラーが発生するようになりました。
iOS16以下、Androidでは従来通り問題なし。

調査経緯

サーバ側の行動ログから、当該リクエストのURLのクエリを確認すると、差異がありました。

# これまでの問題ないパターン
...&trade_tabs=[2,%204]

# 当該OS当該verのパターン
...&trade_tabs=%5B2,%25204%5D

どうも従来はエンコード1回だったのが、問題のケースでは[2, 4] → [2,%204] → %5B2,%25204%5Dと2回エンコードが行われているっぽい

というところでios 17 percent encoding unityで検索してみたところ、ヒット

For apps linked on or after iOS 17 and aligned OS versions, NSURL parsing has updated from the obsolete RFC 1738/1808 parsing to the same RFC 3986 parsing as NSURLComponents. This unifies the parsing behaviors of the NSURL and NSURLComponents APIs. Now, NSURL automatically percent- and IDNA-encodes invalid characters to help create a valid URL.

サーバ側、Railsがparamsに収める時点で1回URLのデコードが入っていますが、

# これまでの問題ないパターン
{ ..., trade_tabs: "[2, 4]" }

# 当該OS当該verのパターン
{ ..., trade_tabs: "[2,%204]" }

# (本当は生Hashじゃないんですけど概念的な記述と思ってください)

という文字列になっていて、その後Arrayに変換(JSON.parse)する時に失敗して、アプリケーションエラーを返されていた、というのが今回の不具合となります。

なお、リクエストに空白が入っていなければエラーが起こらず、配列要素数1で同APIをリクエストしている場面では、, が入らないので、当該OS当該verでも問題なくアクセスできていました。
また、問題があったのはGETリクエストでURLに付加されたパラメータのみで、POSTリクエストのbodyについては問題ありませんでした。

回避策

クライアント側はUnityの対応&バージョンアップを待つとして、サーバ側で回避策を講じます。

GETで受け取ったparamsのvalueに%xxが含まれていたら、もう一度デコードが必要とみなしてURI.decode_www_form_componentを噛ませるようにしました。
今回は問題が発生した%20決め打ちとしました。

  def patched_uri_decode(str)
    if request.get? && str&.include?("%20")
      URI.decode_www_form_component(str)
    else
      str
    end
  end
Happy Elements

Discussion