ngrokのドメイン名を固定した時の「Bad Request」エラーを回避する

普通にngrokを起動すると、`http://28f1ac85.ngrok.io`のように、`ngrok.io`の前に毎回違った文字列が割り当てられます。それだと少し使いづらいので、下記の記事を参考にngrokのプランをBasic以上に上げて、ドメイン名を固定しました。

[ngrokで常に同じアドレスを使う方法 -  Qiita](https://qiita.com/makopo/items/338791261f86dfec1adf)
とても分かりやすかったです:grinning:

---

**ところが、ドメインを固定した時のみ何故か「Bad Request」エラーが出てるようになりました。**
もちろん、ローカルのWebサーバーは起動しています。

結局、原因は単純だったのですが、かなりハマってしまいました。
(同じ症状の人がいないので、もしかしたらMacだけかも？)

# 症状
サブドメインを登録後、サイトの指示に従い、ターミナルから ngrok を起動します。


```
./ngrok http -subdomain=testtest 8080
```
正常に動いているっぽい。

```
ngrok by @inconshreveable                                                                                    
                                                                                              
Session Status               online
Account                      fukusin (Plan: Pro)
Version                       2.3.35
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwardinghttp://testtest.ngrok.io -> http://localhost:8080
Forwarding                    https://testtest.ngrok.io -> http://localhost:8080
                                            
Connections                   ttl     opn     rt1     rt5     p50     p90
                              3       0       0.00    0.00    0.00    0.00
```
ところが、ローカルのWebサーバーを起動し、ブラウザで`http://testtest.ngrok.io`にアクセスすると、ターミナルにエラーが出ます。

```
HTTP Requests
-------------
GET  /favicon.ico              400 Bad Request
GET  /                         400 Bad Request
```
もちろん、ローカルのWebサーバーにもリクエストが届いていません。

#原因
80番ポートで接続して、エラーの詳細を確認します。

```
Failed to complete tunnel connection
The connection to http://testtest.ngrok.io was successfully tunneled to your ngrok client, but the client failed to establish a connection to the local address localhost:80.

Make sure that a web service is running on localhost:80 and that it is a valid address.

The error encountered was: dial tcp [::1]:80: connect: connection refused
```
**Failed to complete tunnel connection ???**

正常にポート指定ができていないようで、`http://testtest.ngrok.io -> http://localhost:80`間のトンネルコネクションに失敗していました。

ngrok の仕様なのか Mac環境の問題なのかは不明ですが、対策をしていきます。


# 対策
ドメインと localhost どちらも同じポートを指定して起動すると良さそうです。

ドメインの場合　`./ngrok http -subdomain=testtest 8080`
localhost の場合　`./ngrok http -host-header=localhost 8080`

ところが、この2つのコマンドは同時に使えません。

そこで、[先ほどの記事](https://qiita.com/makopo/items/338791261f86dfec1adf#%E6%AF%8E%E5%9B%9E%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B%E3%81%AE%E3%81%8C%E9%9D%A2%E5%80%92%E3%81%AA%E5%A0%B4%E5%90%88)を参考にngrok.ymlを使って起動します。
ngrok.ymlを使うとオプションをまとめられるので、毎回の起動が楽になります。

```ngrok.yml
authtoken: <トークン文字列>
region: us
tunnels:
  process1:
    proto: http
    addr: 8080
    host_header: localhost 8080
    subdomain: testtest
```
Macの場合、`[ユーザー]/.ngrok2/ngrok.yml`に保存されています。
localhostのポートも指定したいので、記事のコードに `host_header: localhost 8080`を追加しています。

保存して、ターミナルから起動します。

```
./ngrok start process1
```
```
ngrok by @inconshreveable
                                                                                                                             
Session Status                online
Account                       fukusin (Plan: Pro)
Version                       2.3.35
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://testtest.ngrok.io -> http://localhost:8080
Forwarding                    https://testtest.ngrok.io -> http://localhost:8080

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00
```

起動画面はエラーが出た時と同じ内容ですが、ブラウザで`http://testtest.ngrok.io`にアクセスすると、今回は正常にWebサーバーに繋がります。

```                                                                                                                            
HTTP Requests
-------------
POST /                         200 OK
```

無事、Webサーバーでもリクエストが受け取れました。

---

最終的に起動コマンドを `./ngrok start process1`に変えるだけで、「Bad Request」エラーを回避できるようになりました。
参考になれば。