Приложение Dash, развернутое в системе Apache2, никогда не пропускает пользователя мимо ‘Loading …’, потому что, похоже, оно не может найти свои файлы dash .js

#apache #plotly-dash

#apache #plotly-dash

Вопрос:

Я пытаюсь обслуживать (python3.8.2) dash приложение, используя сервер Apache2 и mod_wsgi , но приложение останавливается на экране «Загрузка …». Сервер возвращает 404 секунды для каждого из сценариев dash .js. У меня не было проблем при использовании встроенного локального сервера dash… но я не пытаюсь обслуживать это локально.

Мне бы хотелось получить совет о том, где я ошибаюсь, и как запустить это конкретное приложение.

Симптомы

Я могу обслуживать как простой python «hello world», так и простое приложение flask, используя мои настройки. Однако при создании простого приложения ‘dash’…

 [Error] Failed to load resource: the server responded with a status of 404 (Not Found) (polyfill@7.v1_6_0m1598005008.8.7.min.js, line 0)
... followed by 12 more similar error messages...
[Error] Failed to load resource: the server responded with a status of 404 (Not Found) (dash_renderer.v1_6_0m1598005008.min.js, line 0)
[Error] ReferenceError: Can't find variable: DashRenderer
    Global Code (hazcurves:28:103)
  

мой журнал доступа apache показывает серию запросов GET, которые получили 404 (вот один пример):

 ... "GET /_dash-component-suites/dash_renderer/dash_renderer.v1_6_0m1598005008.min.js HTTP/1.1" 404 495 "http://efehr-dev.ethz.ch/hazcurves/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Safari/605.1.15"
  

Дополнительные замечания

Когда я сравнил свой отправленный html с html из правильно функционирующего приложения Dash, я заметил разницу в именах .js. Похоже, что мой каким-то образом искажен.

Действующая версия, от https://dash-gallery.plotly.host/dash-wind-streaming /

 # Excerpt from functioning app's "footer" section
<footer>
  <script id="_dash-config" type="application/json">{"url_base_pathname": null, "requests_pathname_prefix": "/dash-wind-streaming/", "ui": false, "props_check": false, "show_undo_redo": false}</script>

  # [CGR] then there are  several components here that are variations of the following
  <script src="/dash-wind-streaming/_dash-component-suites/dash_renderer/dash_renderer.min.js?v=1.0.0amp;m=1583853516"></script>

  <script id="_dash-renderer" type="application/javascript">
        var renderer = new DashRenderer();
        </script>
  

Нижний колонтитул моего приложения делает запрос скремблированным, с параметрами запроса, включенными в имя файла.

 <footer>
  <script id="_dash-config" type="application/json">{"url_base_pathname": null, "requests_pathname_prefix": "/", "ui": false, "props_check": false, "show_undo_redo": false, "suppress_callback_exceptions": false, "update_title": "Updating..."}</script>
   
  # [CGR] then there are  several components here that are variations of the following
  <script src="/_dash-component-suites/dash_html_components/dash_html_components.v1_0_3m1598005008.min.js"></script>
  <script src="/_dash-component-suites/dash_renderer/dash_renderer.v1_6_0m1598005008.min.js"></script>
  <script id="_dash-renderer" type="application/javascript">var renderer = new DashRenderer();</script>
        </footer>
  

Теперь, эти файлы .js [расшифрованные версии] СУЩЕСТВУЕТ и _dash-component-suites , похоже, отображается в моей .local/lib/python3.8/site-packages папке.

Итак, из того, что я показал выше, у меня есть .../dash_renderer/dash_renderer.min.js и .../dash_html_components.min.js

Моя система:

Чистая система с Ubuntu 20.04.1 LTS, Apache 2.4 с установленным mod_wsgi.
В Python 3.8.2 установлены следующие соответствующие пакеты [с использованием sudo pip3] :

 dash==1.14.0
dash-core-components==1.10.2
dash-html-components==1.0.3
dash-renderer==1.6.0
dash-table==4.9.0
Flask==1.1.2
Flask-Compres=1.5.0
  

Вот мое приложение.wsgi:

 from flask import Flask
server = Flask(__name__)

import dash
import dash_core_components as dcc
import dash_html_components as html
app = dash.Dash(server=server) 
app.css.config.serve_locally = True  
app.scripts.config.serve_locally = True
app.layout = html.Div(children=["hello"])
application = app.server
  

Я смог запустить это с помощью встроенного сервера, обслуживая его на локальном сервере.

Файл конфигурации моего сайта:

 <VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /home/username/public_html

        WSGIDaemonProcess /home/username/public_html/myapp.wsgi processes=2 threads=15 display-name=%{GROUP}
        WSGIScriptAlias /hazcurves /home/username/public_html/myapp.wsgi

        <Directory /home/username/public_html>
                AllowOverride all
                Options Indexes FollowSymLinks
                <Limit GET POST OPTIONS>
                        Require all granted
                </Limit>
        </Directory>


        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
  

Некоторые из вещей, которые я признаю, пытались

  • Привет, мир в flask: работает нормально
  • Привет, мир в Dash: сбой
  • Создание псевдонима в конфигурации сервера alias _dash-component-suites/ .local/lib/python3.8/site-packages
  • изменение request_pathnames_prefix : похоже, не имеет никакого эффекта и не отображается в выходных данных html. Это дало мне 403 вместо 404. Но затем я также заметил несоответствия имен.
  • app.css.config.serve_locally = True # также попробовал False: никакого очевидного эффекта
  • app.scripts.config.serve_locally = True #также попробовал False: никакого очевидного эффекта

После попытки включить советы с веб-сайтов, которые имеют непосредственное отношение к этому вопросу, я начинаю чувствовать себя обезьяной, стучащей по клавишам, что, гм, неправильно (и небезопасно)

последнее предостережение: это мой первый опыт управления приложением на стороне сервера в мире.

Ответ №1:

Я рад сообщить, что в конце концов разобрался с этим, и что мои приложения теперь работают отлично. Вот что я узнал.

Я должен был помнить о следующем при вызове dash.Dash(...) Вместо того, что я написал, мне нужно:

 dash.Dash(__name__, requests_pathname_prefix='/hazcurves/')
  

Важные уроки следующие:

  1. Не перезаписывайте переменную сервера. Каким-то образом я терял все созданные мной конфигурации.
  2. requests_pathname_prefix необходимо сопоставить псевдоним URL (начиная с конца, заканчивающегося косой чертой).

Отвлекающий маневр (вещи, которые на самом деле не имели значения):

  1. сначала создайте экземпляр Flask
  2. конфигурации в отношении локального обслуживания
 app.css.config.serve_locally = True  
app.scripts.config.serve_locally = True
  

Итак, вот выдержки из трех моих файлов, представляющих интерес:

mysite.conf : /etc/apache2/sites-available/mysite.conf

 <VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /home/myusername/public_html


    # ---- Hazard Curves App ---- #
    # using WSGIProcessGroup within Location allows multiple apps to run
    # without interfering with each other

    WSGIDaemonProcess curves/wsgi.py processes=2 threads=15 display-name=%{GROUP}
    WSGIScriptAlias /curves /home/myusername/public_html/curves/wsgi.py
    <Location /curves>
        WSGIProcessGroup curves/wsgi.py
    </Location>
</VirtualHost>
  

wsgi.py : ~/public_html/curves/wsgi.py

 #!/usr/bin/python3

from myapp import app
application = app.server
  

myapp.py : ~/public_html/curves/myapp.py

 import dash
import dash_html_components as html

app = dash.Dash(__name__, requests_pathname_prefix='/curves/')

app.title = "Some Test"
app.layout = html.Div([html.H6("Hello World")])

if __name__ == '__main__':
    app.run_server(port=8051, debug=True) # unimportant in this context