Загрузка приложения Python Flask на существующий сервер Apache2 и его прослушивание на другом порту
Быстрый контекст:
У меня есть сервер Ubuntu 14.04 LAMP, на котором довольно долго размещается мой ExtJS-сайт.
Недавно у меня была возможность поработать с DialogFlow, и я также сделал приложение Python Flask, которое будет служить Webhook для достижения DialogFlow.
Теперь я смог протестировать свое приложение Python. Я запускаю его, а затем использую ngrok, чтобы получить публичный IP для своего webhook. Мой пользовательский DialogFlow может отправлять запрос POST в мое приложение Python, а мое приложение Python может анализировать запрос и выдавать желаемый результат.
Теперь я хочу загрузить это приложение Python Flask на мой веб-сервер. У меня есть проблемы с большинством руководств, которые я видел:
- Они слушают порт 80 - это заблокирует существующий у меня веб-сайт
- Они не работают по SSL - большинство из них использует файл http-conf по умолчанию.
Поскольку мой DialogFlow интегрирован с Google Assistant, мое приложение Python Flask должно быть размещено на HTTPS-сервере. Я использовал Lets Encrypt, чтобы получить мой SSL.
Прежде чем продолжить, я хочу дать обзор структуры файлов моего сервера:
|----->/var/www/html/
|----->index.html
|----->FlaskAppFolder
|----->flask_test.py (my flask app)
|----->flaskapp.wsgi
Это мое default-ssl.conf
файл:
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
ServerAdmin my.email@my.domain.com
ServerName mysite.com
ServerAlias www.mysite.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/apache.crt
SSLCertificateKeyFile /etc/apache2/ssl/apache.key
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory /usr/lib/cgi-bin>
SSLOptions +StdEnvVars
</Directory>
BrowserMatch "MSIE [2-6]" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
</VirtualHost>
<VirtualHost _default_:5000>
ServerAdmin my.email@my.domain.com
ServerName mysite.com
ServerAlias www.mysite.com
WSGIScriptAlias / /var/www/html/FlaskAppFolder/flaskapp.wsgi
DocumentRoot /var/www/html/DocumentSearcher
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/apache.crt
SSLCertificateKeyFile /etc/apache2/ssl/apache.key
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory /usr/lib/cgi-bin>
SSLOptions +StdEnvVars
</Directory>
BrowserMatch "MSIE [2-6]" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
</VirtualHost>
</IfModule>
Первый VirtualHost
для порта по умолчанию 80, так что мой веб-сайт все равно будет отображаться. Второй VirtualHost
предназначен для порта 5000, порт, который использует мое приложение фляги, когда я его запускаю.
Следующее мое port.conf
файл:
Listen 80
<IfModule ssl_module>
Listen 443
</IfModule>
<IfModule mod_gnutls.c>
Listen 443
</IfModule>
Я обнаружил, что не могу добавить Listen 5000
к этому. Я пытался добавить Listen 5000
где-нибудь в файле, это может быть под Listen 50
или же Listen 443
мое приложение Python Flask сообщает, что порт уже используется.
И тогда это мои названия приложений колба flask_test.py:
import subprocess
import sys
import time
from flask import Flask
from flask import render_template
from flask import make_response
from flask import jsonify
from flask import request
import ssl
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.load_cert_chain('/path/to/my/apache.crt', '/path/to/my/apache.key')
# app = Flask(__name__)
app = Flask('flaskshell')
# function for responses
def results():
# build a request object
req = request.get_json(force=True)
# fetch action from json
action = req.get('queryResult').get('action')
parameters = req.get('queryResult').get('parameters')
keyword = parameters.get('any');
result = #some process here
output = #some process here
output = output.replace('\n', '\n \n')
return {'fulfillmentText': 'Result: \n\n' + str(output)}
# create a route for webhook
@app.route('/', methods=['GET', 'POST'])
def webhook():
# return response
return make_response(jsonify(results()))
# run the app
if __name__ == '__main__':
app.run(host='0.0.0.0', ssl_context=context)
Наконец, мой flaskapp.wsgi
файл:
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0, "/var/www/html/DocumentSearcher/")
from flask_test import app as application
По сути, я уверен, что он работает на https
вместо http
и использует порт 5000. Мое приложение Python Flask будет принимать запрос POST от DialogFlow, а затем использовать его в качестве входных данных во внутреннем процессе, а затем возвращать результат в DialogFlow для ответа.
Теперь, в моем DialogFlow Fulfillment Webhook, я добавил свой URL и порт как таковой:
https:www.mysite.com:5000
Я пробую запрос, который, как я знаю, работает, но это не так. Когда я проверяю диагностическую информацию, она сообщает, что время запроса истекло. Я знаю, что это работает, потому что, когда я подключаю локальную версию к ngrok и подключаю ее к DialogFlow, она работает просто отлично.
Теперь я не уверен, что делать дальше. Кажется, я не могу добавить порт 5000 к моему port.conf
файл, поскольку он блокирует работу моего приложения Python Flask на порту 5000. Однако, также кажется, что недостаточно просто добавить VirtualHost для порта 5000 на моем default-ssl.conf
файл.
Есть идеи, как сделать приложение Python Flask видимым для внешнего мира?