HTTP/2・Authentication Tokens方式のSwift製プッシュ通知送信ライブラリを作りました

昨日プッシュ通知ライブラリ作りたいと呟いてましたが、早くも作ってしまいました( ´・‿・`)脳内イメージ通りのがそのまま形になった感じで、けっこう自信作です( ´・‿・`)

ツイート内容とちょっと重複になりますが、以下の特徴を持ちます。

  • Swift 4 の Codable 活用(そのため、Xcode 8・Swift 3では実行できない)
  • HTTP/2・Provider Authentication Tokens 方式
  • プッシュ通知のマイナーな項目( thread-identifier など)もすべて網羅(もし抜けがあったらバグなので追加対応します)
  • curl を使わずに URLSession でネットワーク処理をしているため、HTTP/2対応のcurlをインストールせずに済む
  • ❌: 現時点ではUbuntuで動かない(URLSessionがHTTP/2非対応のようなので)
❌: 現時点ではUbuntuで動かない

これは明確なデメリットなので、URLSessionではなく他のライブラリと同様にcurl叩こうかなと迷ったものの、他との差別化にもなるので、URLSession採用してみました。Ubuntu版のURLSessionがHTTP/2対応してくれるのを祈ります🙏

また、macOS上で色々なプッシュ通知を試す用途にはすごく便利なはずで、今のところはそれがメインの利用方法と考えています。

HTTP/2・Provider Authentication Tokens 方式の利点

この方式だと、以下の利点があります。

  • 開発者アカウント(またはOrganizationアカウント)ごとに1つのAuthentication Keyを発行すれば、全アプリに対して共通的に使える(どのアプリに送るかはプッシュ通知発行時にアプリIDで指定する)
  • 証明書と違い、期限切れがない

手順としては以下だけでプッシュ通知対応でき、ややこしかった以前と比べてかなり簡単になりました。

  • Authentication Keyを作成(初回のみ)
  • プッシュ通知をオンにしたApp IDを作成(証明書紐付けは不要)
  • iOSアプリにそのApp IDを紐づけてプッシュ通知をオンにして実機で起動

Firebase NotificationsもAuthentication Tokens 方式に対応 していて、かつ以下のように利用を推奨しています。

Authentication Key(認証キー)方式を推奨

こういうFirebaseのようなサービスを使えば楽ではありますが、自分で処理を書く場合、HTTP/2リクエスト時にセットする認証トークンの生成・検証処理がけっこう難しいです。また、その難しさゆえか比較的新しい(2015年12月から使えるようになった)という理由からか、この方式を使えるライブラリが少なめです。

対応言語問わず一番人気のライブラリはNodeJS版のこちらかと思います。良くできてそうなものの、iOS・Swift系開発者がこの実行環境用意するのは多少面倒だったりしますし、またSwiftの強い型で通知内容を組みたい、とも思います。

Swift版では、VaporAPNSは良いなと思って使っていましたが、出したPRが却下されたり放置されてたりで、PR活動で自分の理想的な形に近づけるのは難しく感じ、一から作ってみました。

(あと、VaporAPNSはAuthentication Keyファイルを加工して、そのオリジナルファイルをしれっと上書きする処理が入っていたり(カットしても動いたので謎🤔) と、よく見たら気になる点がちょくちょく…。)

使い方

READMEがまだちゃんと書けておらず、テストコードをコピペして載せただけになっています が、それ見るだけで大体の使い方が分かると思います。基本的に、通知に必要な要素をそのままStructに落とし込んだような構造になっているので、それを念頭に置きつつコード補完に頼れば大体スラスラ書けると思います。通知内容はコードで書くこともできますし、指定したjsonファイルを読んでセットすることもできます(Codable最高😎)。

このライブラリを元に、GUIアプリとかも作りたいなとも思っていますが、今はそこまで時間取れなさそうなので、先になりそうです。

CLIツールくらいは用意しようかなと思いましたが、色々な引数を文字列でセットするより、このライブラリのテストコード弄って所望のプッシュ通知打った方が手っ取り早いかなと思ったりしています🤔

というわけで、とりあえず今の段階では、目的に応じてどちらかで活用してみてください。

  • APNSライブラリのテストコードをいじって実行
  • 実行形式のSwiftPMプロジェクトを作って、APNS(https://github.com/mono0926/apns.git)への依存を追加して import APNS (ただし現状ではmacOSでしか動かないので注意)

単体テストはほとんど書いていない件について

これまでライブラリ系は大体単体テスト書いてましたが、今回は気付いたらほとんど書かずでした。Codable活用したせいか、書いてもコスパ悪い(念のため確認、程度になってしまう)かなと感じてしまうことが多かったり、でした。また、実際にプッシュ通知が届くかをたまに確認すれば、あとはSwiftの型の強さで安心できる感じでした。

とはいえ、本当は書くべきかなというところをサボった感もあるので、今後リファクタリングついでに、多少テスト追加していこかなとも思っています( ´・‿・`)


ちなみに今、プッシュ通知の本を書いていて(秋くらいに書き上げたい…)、そのために細かいプッシュ通知を色々検証中なのですが、VaporAPNSでその細かいところが動いていないところがあって、PR出したりしていた勢いでつい一から自作しちゃった感じです( ´・‿・`)

また、もし今バグがあっても、そうやってこの本を書きながら使っていく中で皆潰せるかな、と目論んでいます( ´・‿・`)