1
1
from __future__ import print_function
2
2
3
- import itertools
4
3
import os
5
- import random
6
4
import sys
7
5
import collections
8
6
import importlib
14
12
import mimetypes
15
13
16
14
from functools import wraps
15
+ from future .moves .urllib .parse import urlparse
17
16
18
17
import flask
19
18
from flask_compress import Compress
25
24
from .fingerprint import build_fingerprint , check_fingerprint
26
25
from .resources import Scripts , Css
27
26
from .development .base_component import ComponentRegistry
28
- from .exceptions import PreventUpdate , InvalidResourceError
27
+ from .exceptions import PreventUpdate , InvalidResourceError , ProxyError
29
28
from .version import __version__
30
29
from ._configs import get_combined_config , pathname_configs
31
30
from ._utils import (
@@ -1332,7 +1331,8 @@ def enable_dev_tools(
1332
1331
1333
1332
if dev_tools .silence_routes_logging :
1334
1333
logging .getLogger ("werkzeug" ).setLevel (logging .ERROR )
1335
- self .logger .setLevel (logging .INFO )
1334
+
1335
+ self .logger .setLevel (logging .INFO )
1336
1336
1337
1337
if dev_tools .hot_reload :
1338
1338
_reload = self ._hot_reload
@@ -1449,6 +1449,7 @@ def run_server(
1449
1449
self ,
1450
1450
host = os .getenv ("HOST" , "127.0.0.1" ),
1451
1451
port = os .getenv ("PORT" , "8050" ),
1452
+ proxy = os .getenv ("DASH_PROXY" , None ),
1452
1453
debug = False ,
1453
1454
dev_tools_ui = None ,
1454
1455
dev_tools_props_check = None ,
@@ -1475,6 +1476,14 @@ def run_server(
1475
1476
env: ``PORT``
1476
1477
:type port: int
1477
1478
1479
+ :param proxy: If this application will be served to a different URL
1480
+ via a proxy configured outside of Python, you can list it here
1481
+ as a string of the form ``"{input}::{output}"``, for example:
1482
+ ``"http://0.0.0.0:8050::https://my.domain.com"``
1483
+ so that the startup message will display an accurate URL.
1484
+ env: ``DASH_PROXY``
1485
+ :type proxy: string
1486
+
1478
1487
:param debug: Set Flask debug mode and enable dev tools.
1479
1488
env: ``DASH_DEBUG``
1480
1489
:type debug: bool
@@ -1555,25 +1564,51 @@ def run_server(
1555
1564
]
1556
1565
raise
1557
1566
1558
- if self ._dev_tools .silence_routes_logging :
1559
- # Since it's silenced, the address doesn't show anymore.
1567
+ # so we only see the "Running on" message once with hot reloading
1568
+ # https://stackoverflow.com/a/57231282/9188800
1569
+ if os .getenv ("WERKZEUG_RUN_MAIN" ) != "true" :
1560
1570
ssl_context = flask_run_options .get ("ssl_context" )
1561
- self .logger .info (
1562
- "Running on %s://%s:%s%s" ,
1563
- "https" if ssl_context else "http" ,
1564
- host ,
1565
- port ,
1566
- self .config .requests_pathname_prefix ,
1567
- )
1571
+ protocol = "https" if ssl_context else "http"
1572
+ path = self .config .requests_pathname_prefix
1573
+
1574
+ if proxy :
1575
+ served_url , proxied_url = map (urlparse , proxy .split ("::" ))
1576
+
1577
+ def verify_url_part (served_part , url_part , part_name ):
1578
+ if served_part != url_part :
1579
+ raise ProxyError (
1580
+ """
1581
+ {0}: {1} is incompatible with the proxy:
1582
+ {3}
1583
+ To see your app at {4},
1584
+ you must use {0}: {2}
1585
+ """ .format (
1586
+ part_name ,
1587
+ url_part ,
1588
+ served_part ,
1589
+ proxy ,
1590
+ proxied_url .geturl (),
1591
+ )
1592
+ )
1593
+
1594
+ verify_url_part (served_url .scheme , protocol , "protocol" )
1595
+ verify_url_part (served_url .hostname , host , "host" )
1596
+ verify_url_part (served_url .port , port , "port" )
1568
1597
1569
- # Generate a debugger pin and log it to the screen.
1570
- debugger_pin = os . environ [ "WERKZEUG_DEBUG_PIN" ] = "-" . join (
1571
- itertools . chain (
1572
- "" . join ([ str ( random . randint ( 0 , 9 )) for _ in range ( 3 )])
1573
- for _ in range ( 3 )
1598
+ display_url = (
1599
+ proxied_url . scheme ,
1600
+ proxied_url . hostname ,
1601
+ ( ":{}" . format ( proxied_url . port ) if proxied_url . port else "" ),
1602
+ path ,
1574
1603
)
1575
- )
1604
+ else :
1605
+ display_url = (protocol , host , ":{}" .format (port ), path )
1606
+
1607
+ self .logger .info ("Dash is running on %s://%s%s%s\n " , * display_url )
1608
+ self .logger .info (" Warning: This is a development server. Do not use app.run_server" )
1609
+ self .logger .info (" in production, use a production WSGI server like gunicorn instead.\n " )
1576
1610
1577
- self .logger .info ("Debugger PIN: %s" , debugger_pin )
1611
+ if not os .environ .get ("FLASK_ENV" ):
1612
+ os .environ ["FLASK_ENV" ] = "development"
1578
1613
1579
1614
self .server .run (host = host , port = port , debug = debug , ** flask_run_options )
0 commit comments