iOS開発でlocalhostに接続したい!って事有りませんか?私はFirebase Hosting上で動くAngularのWebアプリを開発していて、スマホ側にはWebアプリだけだと完結できないネイティブな機能が必要なので、Swift使ってWkWebkitからWebアプリにアクセスしつつ、特定のページではURLを横取りしてインテントを立ち上げる、ということを行っています。
Firebase自体はクライアント側開発環境がとても充実しているし、サクサク感だとかログの自由度とか考えるとlocalhostに接続してゆきたいんですね。いちいちデプロイしなくてもコード変更がそのままホットロードされるというのは劇的な時間短縮だぞ、と。
でもそんな事出来るの?ってか無理でしょ?だってlocalhostだよ?iOSは別端末だよ?localhost上のエミュレーターででもアクセスするの?なんて調べもせずに思考停止していたところを少しだけ重い腰上げて調べてみました。結論から言うと、出来ます。ステップは下記の通り。
- 母艦localhost (Mac) のOSネットワーク共有設定 (引用元)
- iOS端末を母艦にUSB接続。
- システム設定→共有を開く。
- もし左側タブ「インターネット共有」にチェックが入っているようならば、一旦外す。
- 左側タブでインターネット共有の項目をクリックした時に右側に表示されるインターネット共有オプションで、iPhone USBにチェックを入れる。
- 左側タブでインターネット共有のチェックをオンにする。ポップアップで確認を求めてくるが気にせず「OK」で進める。
- ポップアップを閉じたあとの同じ画面で、インターネット共有オプションのダイアログ上部に「xxx.local」という表記があるはず。xxx.localがlocalhostのインターネット共有上でのホスト名となる。
- でもこのままだとまだxxx.local:5000 (うちの環境ではAngularアプリのポートは5000に設定してる)には接続できない。まあ待て。引用元でもちゃんと「ローカルサーバーのIPバインディングとか設定してあげないとそのまんまじゃつながらないかもね」とRailsの例を引用して警告してくれてる。
- 何だよ無理なのかよと嘆きつつ、問題の切り分けをするために一応母艦上でxxx.local:5000でアクセスしてみると、真っ白なページに「Invalid Host header」だけ吐き出してる。
- 母艦localhost (Mac) のlocalhost起動設定 (引用元) – Angular編
- AngularでInvalid Host Headerエラーが出て困ってるよ!って人の記事を発見。Key Takeawayは以下の2つ。
- –host $IP でIPバインディングちゃんとしましょうね ($IP = 0.0.0.0 としとけばオープンコネクションになるね)。
- –disable-host-check 指定してあげないとね。
- ということで、「ng serve –port 5000 –host 0.0.0.0 –disable-host-check」でローカルホストを起動。
- これでiOS端末側でブラウザを開き、xxx.local:5000を叩くとWebアプリが表示される!あともう一歩!
- AngularでInvalid Host Headerエラーが出て困ってるよ!って人の記事を発見。Key Takeawayは以下の2つ。
- 母艦localhost (Mac) のCORS設定 – Angular編
- 上記でホスト名が xxx.local で起動するんだけどね、俺のプロジェクトはFirebase Hosting上でホスティングされたAngularのコードからFirebase Functionsを呼び出しているんだね。Firebase HostingとFirebase Functionsはそれぞれ別ドメインの運用となるのでCORS問題が発生するよ。だから、PC上のlocalhostで開発を行うときには、Functionsが許可するドメインとして、”localhost:5000″ とかやっていたわけです。
- 今回の変更で、Hostingは “localhost” ではなく “xxx.local” としてFunctionsのREST APIを呼び出すわけなので、CORS許可アクセス元ドメインも全て変更しましょう。私はここんとこ忘れていてしばらく悩んでしまいました。色んな所にコード散らばってるので上のステップよりもめんどくさいけどね、でもSwiftのWebkitからのlocalhostアクセスによる開発、快適すぎてこの作業やってもお釣りいっぱい戻ってくるから。頑張ろう。
- この作業が終われば、iOS端末側のブラウザでWebアプリが一通り動くようになるはず。
- 母艦localhost (Mac) のlocalhost起動設定 (引用元) – Firebase Functions編
- 俺のiOSアプリだと、Firebase Function もアプリから直接叩くことがあるから、Angular 同様にオープン接続に設定しよう。引用元に記載されたとおり、デフォルトがlocalhost決め打ちになってるfirebase serveで別デバイスから接続するためには、接続元をオープンに設定してあげましょう。
- ということで、「firebase serve –only functions –port 5001 –host 0.0.0.0」でローカルホストを起動。
- iOS端末側のSwiftプロジェクト設定 (引用元)
- Swift側のロード用URLをxxx.local:5000に直し、ビルドしてデバッグ起動してみたがどうにもアプリのブラウザコンポーネントではロードできない。コンソールを見るとNSURLErrorDomainエラーを吐いている。
- 一発目の試行では-1200 (NSURLErrorSecureConnectionFailed) を吐いていた (誰かがNSURLErrorDomainコードごとのエラーをまとめてくれてる、有り難いことだ)。そりゃそうか、ドメイン変えただけじゃ、httpsのままだし。localhost接続ならばhttpだよね、ということで、プロトコルをhttpに変更。
- 二発目の試行で-1022 (NSURLErrorAppTransportSecurityRequiresSecureConnection) を吐いてる。引用元の記事に従ってSwiftのプロジェクト設定を変更。
- Swiftのプロジェクト設定を開く。
- 上部のタブバーから「Info」を開く。plistの画面ですね。そこで項目にマウスポインターを当てると薄く (+) が表示されるので、そこから App Transport Security Settings を追加する。それ自体はDictionary項目だから、項目左端の ‘>’ をクリックして開き、その行に表示される (+) で子要素を追加。Allow Arbitrary Loads を選択して、デフォルトの値 ‘No’ を ‘Yes’ に書き換える。
- プロジェクトを再ビルド。
- と、ここまでやったらようやく私の環境ではiOSのデバッグ環境でAngularとFirebase Functionsのローカルホスト環境上での一気通貫開発ができるようになりましたよ、と。同じ悩みを持ってた人の役に立てたらいいな。
