AlamofireのRequest Paramater エンコードをカスタマイズする

最近、PHP(CakePHP2,CakePHP3,Lumen)、iPhoneアプリ(Objective-C,Swift)とAndroidアプリの運用をしていて頭ん中がカオスになっているわたなべです。

とある趣味アプリで、Alamofireを使って某APIを使おうとしてハマったのでメモっときます。

AlamofireのRequest Paramater エンコード

基本的には、RFC3986に従ってエンコードされるのですが、'/' と '?' がエンコードされません。実際のエンコード処理にはこんなコメントがあります。

// does not include "?" or "/" due to RFC 3986 - Section 3.4

RFC 3986 - Section 3.4ってなんだよ?ってことで、RFC3986 日本語訳を見るとこんな風に書いてあります。

スラッシュ ("/") と疑問符 ("?") の文字は、query 要素の中のデータを表すかもしれない。 いくつかの古い、エラーのある実装では、それが相対的参照 (Section 5.1) の基底 URI として使用される場合、階層的な区切りを探す時に query データと path データの区別に失敗する事が多いので、そのようなデータを正しく扱わないかもしれない事に注意せよ。 しかし、query 構成要素はしばしば "key=value" の対の形式で識別するための情報を運ぶために使用され、そこで頻繁に使用された値は別の URI の参照なので、時にはそれらの文字をパーセントエンコーディングする事を避けるほうがユーザビリティのためにはよい。

https://triple-underscore.github.io/RFC3986-ja.html#section-3.4

時にはそれらの文字をパーセントエンコーディングする事を避けるほうがユーザビリティのためにはよい。」これを根拠に'/' と '?'がエンコードされないようです。。。

普通に使用している分には気づかなかったのですが、APIを使うためにSignetureを生成する場合に、ハッシュ化する元の文字列が変わってしまうため問題が起こります。

ParameterEncodingを独自実装

AlamofireのParameterEncodingには、一般的に使用するURLエンコード以外にも以下のエンコードが定義されています。

  • URL
  • URLEncodedInURL
  • JSON
  • PropertyList
  • Custom

今回はCustomを使用して、'/' と '?'もエンコードするようにカスタマイズします。

Alamofireのencode処理を参考に作ったのがこんなの。

gist.github.com

この関数で作成したエンコーディング処理を以下のように指定することで独自にエンコードすることができます。

gist.github.com

わかってしまえば、たいしたことではないのですが、なかなか原因がわからずちょっと手こずりました(;_;