itoma(2)：unvt/itoma（ベクトルタイルのためのArcGIS REST API 実装ツール） をhttps対応させる

## はじめに
[unvt/itoma](https://github.com/unvt/itoma)はベクトルタイルのためのArcGIS REST API 実装ツールです。今年の3月末、国土地理院からFOSS4Gツールとして公開されました。

私も、[前回の記事](https://qiita.com/T-ubu/private/f40f6dd23724cae92db4)で unvt/itoma を試していました。その結果、どうも http://localhost でホストしたベクトルタイルサーバーをArcGIS Onlineで読み込めない、ということに気がつきました。

なんでだろうと少し調べてみると、少し前にArcGIS Onlineはhttp対応をやめていたようです（[こちらの記事](https://communityhub.esriuk.com/technicalsupport/2020/4/14/arcgis-online-https-only-enforcement) ）。なるほどArcGIS Onlineでは、ベクトルタイルレイヤの読み込みについては、httpで指定しても、スタイルファイルを読みに行く先が https://localhost になっている。これではローカルでhttpホストだと見られない、というわけです。

せっかくの itoma の機能がもったいない。**どうにかitomaをhttps対応させてみよう、具体的にはlocalhostのhttps化をやってみようと思いました。その結果をこの記事にまとめます**

オープンソース、FOSS4Gツールの素敵なところですが、コードがオープンなので私もunvt/itomaをフォークして実験してみました。今後、itomaがさらに発展するといいなと思います。

## 環境
* Windows 10 (Enterprise)
* Docker version 20.10.8, build 3967b7d
* つかったDocker container unvt/nanban


## 手順
### Step1: httpsのためのドメインとSSL認証取得
このステップのためには以下の二つの記事を参考にしました。（ありがとうございます。）

https://blog.jxck.io/entries/2020-06-29/https-for-localhost.html

https://crieit.net/posts/localhost-127-0-0-1-HTTPS

#### 1-1. ドメイン取得
ドメインについて長期間利用できる保証は必要ないので、無料のdomainサービス（[freenom.com](https://my.freenom.com/)）を使ってvt-itomas.mlというドメインをとり、localhostを127.0.0.1にするAレコードを追加しました。これでlocalhost.vt-itomas.mlが127.0.0.1になるかなと思います。（つまづきメモ： ドメインの利用可否をチェックしたあと、ドメインの検索窓のドメインで.mlなどをつけて申請しないと上手くいきません。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/a03a3c24-afc0-ebb5-520e-c7b763e5cfcb.png)

#### 1-2. Let's Encryptで認証ファイル取得
[Let's Encrypt](https://letsencrypt.org/)でのSSL証明書は前にもとったことがあるので、自分の実験用サーバーにCertbotはすでに入っている。そこのcertbotを使って、今回あらたに取得したドメインのための証明書をとった。

```
certbot --version
sudo certbot certonly --manual -d localhost.（自分のドメイン） --preferred-challenges dns
```
ドメインに証明書をとるとき、途中でTXTをデプロイ（実装しなさい）というように言われるので、ドメインの管理サイトで指定の文字列を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/5e525fcc-22aa-4fde-c51c-13f8b4c12640.png)

最初、ワイルドカード（*.vt-itomas.ml）で証明書をとろうとしたら（上図）失敗しましたが、localhost.vt-itomas.mlで取得したら成功。（最初の時はdigして値が返ってくるのを確認しなかったので、多分テキストの登録が反映されていなかっただけだと思いますが。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/99db0873-8024-ed26-62df-ffa10e95aa6e.png)

サーバーの中にpemファイルが出来ています。Let's encryptだと、cert.pem, chain.pem, fullchain.pem, privkey.pemの4つが出来ていると思います。これで、localhost.vt-itomas.ml のSSL証明書がとれたはず（そしてこれが127.0.0.1にいくはず）。
privkey.pem　と　fullchain.pem　はローカル環境にもってきてitomaの中に入れておきます。


### Step2: itomaを改造
unvt/itomaをフォークして、github.com/ubukawa/itomaにもってきました。これをクローンして作業をします。

#### 2-1: 作業環境を整える
itomaを動かすにはLinuxの方がいいでしょうから、dockerでunvt/nanbanをスタートします。これには、unvt/itoma がもう入っているので、アンインストールします。

```
（itomaをクローンしておく）
cd itoma
Docker run -it --rm -v ${PWD}:/data -p 8080:8080 unvt/nanban
cd /data
npm uninstall -g @unvt/itoma
```

また、sshのkeyを入れておくフォルダssh-keyを作って、そこにprivkey.pemとfullchain.pemを入れておきます。（2つのファイルは他の人に渡らないようgitignoreに登録しておく。）

#### 2-2: nodejsモジュール追加 
私の実力ではあんまり難しいことはできないですが、httpsのため、nodeパッケージのspdyを追加します。

```
npm install spdy
```

#### 2-3: src/command/serve.ts をいじる 
見てみるとこのファイル（src/command/serve.ts）がhttpホスティングのことをやっているみたいです。ここをいじります。

##### 変数を追加
spdyパッケージを追加したので、tsファイルの中でも定義します。また、sshキーへのパスを定義します（外部でやるときはconfigファイルとか.envファイルから読ませましょう）。

```ts:変数の追加
const spdy = require('spdy') // test for https
const privkeyPath = 'ssh-key/privkey.pem' //for https (it should be stored in config)
const fullchainPath = 'ssh-key/fullchain.pem' //for https (it should be stored in config)
```
##### serverPromiseの修正
過去のunvt/marbleなどの経験で、httpからhttpsに切り替えたことがあります。その時のコードを参考に、だいたいこんな感じだろうということで修正してみました。（下の通り）

```ts:serverPromiseの修正
  const serverPromise = new Promise<Server>((resolve) => {
    /*
    const server = app.listen(port, () => {
      console.log(`itoma listening on port ${port}\n`)
      console.log(`MapLibre interface: http://localhost:${port}/maplibre`)
      console.log(`Mapbox interface  : http://localhost:${port}/mapbox`)
      console.log(`ArcGIS interface  : http://localhost:${port}/arcgis`)
      resolve(server)
    })
    */
   //test (from here)
    const server = spdy.createServer({
      key: fs.readFileSync(privkeyPath),
      cert: fs.readFileSync(fullchainPath)
    }, app).listen(port, () => {
      console.log(`itoma listening on port ${port}\n`)
      console.log(`MapLibre interface: https://localhost:${port}/maplibre`)
      console.log(`Mapbox interface  : https://localhost:${port}/mapbox`)
      console.log(`ArcGIS interface  : https://localhost:${port}/arcgis`)
      resolve(server)
    })
    //test (until here)
  })
```

という作業をフォークしたレポジトリでやりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/e06636ee-9ed5-c31a-971e-333c8cb3465a.png)


#### 2-4: Distをつくる
npm run buildをして、distをつくります。そして出来たdistの中のcli.jsがitomaのツールのようです。itomaの代わりにdist/cli.jsを実行すればよいというようなイメージです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/a41a17d0-20bd-6776-ea7d-78f8c271d2ad.png)

 
### Step3. 改造したitomaを動かして見てみる
2-4の作業から同じところでつづけます。前にitomaを実験したときのレポジトリ[ubukawa/itoma-test](https://github.com/ubukawa/itoma-test)からtestフォルダのスタイルをもってきます。そして、dist/cli.js serve itoma-test/test/style.ymlと実行してみました。（strictモードでもやりました。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/c1ea3c71-31d1-40a5-9b6b-14f78c0f8cc5.png)

HTTPSにしているので、以下のようにアドレスをうつとローカルホストになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/eef301b0-83ee-295a-6067-519031ef8abe.png)

MapLibreのリンク先では参照スタイルのURLがhttpになっているので見られませんでした。どこかを直します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/565c39b1-a70f-f4b0-10eb-340fbb9ae034.png)

おもしろいことにArcGISは見られました。（以下はstrictモード）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/d3a60858-3ba7-d875-0bc7-3a9490c271a1.png)


そして、ArcGIS Online用のindexもなんとhttpsで見られるようになりました。このURLをArcGISで読めば、ローカルホストながらhttpsなので中身がみられそうですね。今度実験します。（今日は眠たいのでここまで）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/da43fb58-3875-6a27-ea43-becaba50978b.png)

あと、以下の画面に出ているdepuricationのことも今後調べます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/f8661f1e-8449-cb87-b7c2-3e704b60164f.png)

## まとめ
このブログを書きながらでしたが、unvt/itomaをフォークし、これをhttps化したローカルホストで使えそうというところまできました。これにより、今後、ArcGIS Onlineでもプレビューを見られるようになるはずです。

## 謝辞
今回の作業にあたっては、ローカルホストのhttps化に関して非常によい取組みがまとめられており助けられました。リンクで示した2つのブログに感謝します。また、unvt/itomaの開発者の皆様に敬意を表します。




## References
* UNVT/itoma https://github.com/unvt/itoma
* ArcGIS関係の参考
    * [ArcGIS Online HTTPS Only Enforcement - CommunityHub](https://communityhub.esriuk.com/technicalsupport/2020/4/14/arcgis-online-https-only-enforcement)
* ローカルホストのhttps化の参考
    * [ローカル開発環境のhttps化　| blog.jxck.io](https://blog.jxck.io/entries/2020-06-29/https-for-localhost.html)
    * [localhost(127.0.0.1)をHTTPS化して開発環境を作る - Crieit](https://crieit.net/posts/localhost-127-0-0-1-HTTPS)
* 作業で使ったもの
    * ドメインの取得　[Freenom](https://www.freenom.com/)
    * SSL認証の取得　[Let's Encrypt](https://letsencrypt.org/)
* 自分の過去の記事
    * [ベクトルタイルのためのArcGIS Rest API実装ツール unvt/itoma を試してみる](https://qiita.com/T-ubu/private/f40f6dd23724cae92db4)
* 作業用レポジトリ　https://github.com/ubukawa/itoma