為替レート等を確認するLINE BOTを作りたくて、先ずは、先人の解説を真似てHerokuにオウム返しのBOTを作ってみました。2度目は、為替データ等データベースは自前サーバにあるので、自前サーバ(DTI VPSのCentOS 6)にオウム返しサーバを立ててみました。
発生した問題
1度目同様、LINE Developersでチャネルを作成し、Webhook URL
に自前サーバのアクセスポイントを設定したのですが、LINE Developersのページでは、以下のようなエラーが表示され、何かおかしいことになっているようでした。
Webhookが無効なHTTPステータスコードを返しました(期待されるステータスコードは200です)
試したこと
localhostで試してみる
自前サーバには開発ツールを入れてないので、手元の開発PCであれば詳しく原因追求できるだろうと試してみることにしました。
その際、Chromeの拡張機能のRestlet Clientを使って、以下のお試しJSONを入力しました。
{
"events" : [
{
"replyToken": "012345",
"message": {
"type": "text",
"text": "こんにちは"
}
}
]
}
まず、オウム返しBOTの初期化処理にて、アクセストークンやChannel Secretを間違えている(設定できていない)ことを疑ったのですが、仕込んだログを見る限りではきちんと設定できています。
先述したJSONをPOSTした際、code 400, message Bad request syntax
等と表示されます。さらに、ログ表示が化けてしまい、エラーの内容がよくわかりません(結局ログが読めない件は解決していません)。
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://XXX.XXX.XXX.XXXX:5000/ (Press CTRL+C to quit)
121.95.125.202 - - [29/Jul/2018 17:29:06] code 400, message Bad request syntax ('\x16\x03\x01\x02\x00\x01\x00\x01ü\x03\x0û\x117\'G\x1dÙµÉ5\x0bÛ}âÇ ]+XÀÿ\x08¼\x1b\x80\x19ÿæa\x13\x01\x13\x02\x13\x03À+À/À,À0̨̩À\x13À\x14\x00\x9c\x00\x9d\x00/\x005\x00')
121.95.125.202 - - [29/Jul/2018 17:29:06] "üeëù®rû7'GÙµÉ5
(中略)
HTTPStatus.BAD_REQUEST -
解決策
結論を言うと、自前サーバと開発PCでは、エラーの原因が異なっていました(開発PCでのエラーの原因は未だに不明です)。
/var/log/httpd/ssl_error_log
を見れば一目瞭然でした。
mod_wsgi (pid=9081): Failed to exec Python script file '/var/www/py/bot/app.py'.
mod_wsgi (pid=9081): Exception occurred processing WSGI script '/var/www/py/bot/app.py'.
Traceback (most recent call last):
File "/var/www/py/bot/app.py", line 23, in <module>
YOUR_CHANNEL_ACCESS_TOKEN = ini['line']['access_token']
File "/opt/rh/rh-python35/root/usr/lib64/python3.5/configparser.py", line 956, in __getitem__
raise KeyError(key)
KeyError: 'line'
オウム返しBOTでは、アクセストークンとChannel SecretをINIファイルに外出ししているのですが、それが読めていませんでした。
WSGI scriptと同じフォルダにあるINIファイルを読むように変更して解決しました。
from configparser import ConfigParser
ini = ConfigParser()
ini.read('bot.ini')
from configparser import ConfigParser
ini = ConfigParser()
config_file = os.path.join(os.path.dirname(__file__), 'bot.ini')
ini.read(config_file)
環境と条件
- ホストOS: CentOS 6
- ゲストOS: Ubuntu 16.04
- Python 3.5