Repository: plotly/dash

Issue:
Assets are not prefixed with `requests_pathname_prefix`.
The assets files should be prefixed with the `requests_pathname_prefix` like other resources.



Discussion:

Resolving patch:
diff --git a/dash/_utils.py b/dash/_utils.py
--- a/dash/_utils.py
+++ b/dash/_utils.py
@@ -20,6 +20,18 @@ def format_tag(tag_name, attributes, inner='', closed=False, opened=False):
             '{}="{}"'.format(k, v) for k, v in attributes.items()]))
 
 
+def get_asset_path(requests_pathname, routes_pathname, asset_path):
+    i = requests_pathname.rfind(routes_pathname)
+    req = requests_pathname[:i]
+
+    return '/'.join([
+        # Only take the first part of the pathname
+        req,
+        'assets',
+        asset_path
+    ])
+
+
 class AttributeDict(dict):
     """
     Dictionary subclass enabling attribute lookup/assignment of keys/values.
diff --git a/dash/dash.py b/dash/dash.py
--- a/dash/dash.py
+++ b/dash/dash.py
@@ -24,6 +24,7 @@
 from ._utils import AttributeDict as _AttributeDict
 from ._utils import interpolate_str as _interpolate
 from ._utils import format_tag as _format_tag
+from ._utils import get_asset_path as _get_asset_path
 from . import _configs
 
 
@@ -329,9 +330,9 @@ def _relative_url_path(relative_package_path='', namespace=''):
                     'Serving files from absolute_path isn\'t supported yet'
                 )
             elif 'asset_path' in resource:
-                static_url = flask.url_for('assets.static',
-                                           filename=resource['asset_path'],
-                                           mod=resource['ts'])
+                static_url = self.get_asset_url(resource['asset_path'])
+                # Add a bust query param
+                static_url += '?m={}'.format(resource['ts'])
                 srcs.append(static_url)
         return srcs
 
@@ -942,6 +943,12 @@ def add_resource(p, filepath):
                 elif f == 'favicon.ico':
                     self._favicon = path
 
+    def get_asset_url(self, path):
+        return _get_asset_path(
+            self.config.requests_pathname_prefix,
+            self.config.routes_pathname_prefix,
+            path)
+
     def run_server(self,
                    port=8050,
                    debug=False,
diff --git a/dash/version.py b/dash/version.py
--- a/dash/version.py
+++ b/dash/version.py
@@ -1 +1 @@
-__version__ = '0.26.2'
+__version__ = '0.26.3'


Test patch:
diff --git a/tests/test_configs.py b/tests/test_configs.py
--- a/tests/test_configs.py
+++ b/tests/test_configs.py
@@ -2,6 +2,7 @@
 # noinspection PyProtectedMember
 from dash import _configs
 from dash import exceptions as _exc
+from dash._utils import get_asset_path
 import os
 
 
@@ -88,6 +89,21 @@ def test_pathname_prefix_environ_requests(self):
         _, routes, req = _configs.pathname_configs()
         self.assertEqual('/requests/', req)
 
+    def test_pathname_prefix_assets(self):
+        req = '/'
+        routes = '/'
+        path = get_asset_path(req, routes, 'reset.css')
+        self.assertEqual('/assets/reset.css', path)
+
+        req = '/requests/'
+        path = get_asset_path(req, routes, 'reset.css')
+        self.assertEqual('/requests/assets/reset.css', path)
+
+        req = '/requests/routes/'
+        routes = '/routes/'
+        path = get_asset_path(req, routes, 'reset.css')
+        self.assertEqual('/requests/assets/reset.css', path)
+
 
 if __name__ == '__main__':
     unittest.main()