-
-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
[WIP] Inspect environment variables and set routing prefixes, add catchall endpoint #53
Conversation
I think let's 🔪 |
R/dash.R
Outdated
@@ -268,7 +268,14 @@ Dash <- R6::R6Class( | |||
TRUE | |||
}) | |||
|
|||
|
|||
route$add_handler('get', '/*', function(request, response, keys, ...) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you have to move this around so that it gets declared after the other routes or does it work like this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh nvm, the original route wasn't removed: https://github.com/plotly/dashR/pull/53/files#diff-1881af3720f8f49fd3a44e51c9fb5a0dR180
Let's 🔪 the original route since /*
should catch /
.
Also, this route needs to be prefixed by routes_pathname_prefix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I noticed that when I glanced at the Python code but forgot to insert here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in 62d7dd9
R/dash.R
Outdated
@@ -370,8 +377,32 @@ Dash <- R6::R6Class( | |||
# private fields defined on initiation | |||
name = NULL, | |||
serve_locally = NULL, | |||
routes_pathname_prefix = NULL, | |||
requests_pathname_prefix = NULL, | |||
routes_pathname_prefix = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This syntax is interesting - is this like a function that gets called whenever this variable is accessed? Or is it just a function shorthand?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realized this isn't going to work the way we want, so I've 🔨 a bit, hopefully the refactored implementation of the routes/requests pathname prefixes is closer to the Python logic.
R/dash.R
Outdated
routes_pathname_prefix = NULL, | ||
requests_pathname_prefix = NULL, | ||
routes_pathname_prefix = { | ||
routes_prefix <- Sys.getenv("DASH_ROUTES_PATHNAME_PREFIX") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These variables are also defined in the constructor:
routes_pathname_prefix = '/',
requests_pathname_prefix = '/',
The order of preference should be:
- Did the user supply it in the constructor? If so, then use that.
- If not, then check the environment
- If not in the environment, then use the default.
In Python, for (1), the only way to check if a user supplied it while keeping a default argument was to set that default argument to None
. That way, if it's not None
, then we can assume that the user set it. (If the default was /
, then we wouldn't know whether the user explicitly supplied that or if its just the default).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, perfect. This makes sense. I’ll just use NULL
instead of None
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in 5fba10f
ffc7f13
to
5fba10f
Compare
f56385f
to
62d7dd9
Compare
fixed in 5fba10f |
- parses the request URL to identify the dependency that should be returned - calls get_package_mapping to determine the local path to the requested dependency, and the name of the R package which contains it - returns UTF-8 encoded version of dependency from local package source - calls get_mimetype to determine the correct MIME type for the dependency being returned, based on its file extension
Previously, we encountered an This is possible when using a component like
...has been replaced with: Lines 244 to 260 in 7fa2581
The new code handles inputs which may contain |
I've tried to address the most recent round of PR comments, and I think I've licked the |
version = "16.2.0", | ||
src = list(href = "https://unpkg.com/react@16.2.0", | ||
file = "lib/react@16.2.0"), | ||
meta = NULL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this is just white space removal, but a few things strike me as odd about this code:
- "react-prod" is react-16. This is different than the python side - we allow users to switch to react 16 optionally but it's not a "prod" vs "dev" distinction.
- On the python side, we handle this in dash-renderer using the same structure as the rest of the component repos (https://github.com/plotly/dash-renderer/blob/1c7c75d3127a742093f59bd34ea23b9a84be1ac9/dash_renderer/__init__.py). I would be worried about DashR handling these versions independently of dash-renderer as we don't want DashPy to be distributed with a different version than DashR
This is non-blocking and not a high priority, but something to maybe break out into its own issue and consider down the line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should add a debug=TRUE
option to DashR, so that component developers can optionally request specific (development) versions of dependencies, replicating functionality currently available in Dash for Python.
This item is on the roadmap for DashR, but I'll open an issue more clearly outlining what's required, and link here for future reference.
R/utils.R
Outdated
"/", | ||
paste(dep$src$file, | ||
dep$script, | ||
sep = "/") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is only used as a file path, could we use file.path
? I recognize that it's being used below, but just to get into the habit of never constructing file paths by hand.
(unless this variable is also used as a script tag / url pathname? By reading the code below it didn't seem like it but I might've missed something)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in 3a61d02
R/utils.R
Outdated
modified <- as.integer(Sys.time()) | ||
} | ||
|
||
# we don't want to serve the JavaScript source maps here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add a comment like "until we have full support for a debug=TRUE mode"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call. I could open an issue for this as well, I'll have a look at what's needed to approach parity based on what's currently available in Dash for Python.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in b6af99b
R/utils.R
Outdated
sep = "/") | ||
|
||
# remove n>1 slashes and replace with / if present |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you prefix this comment with something like "htmltools sometimes includes multiple //
- replace these with /
".
That way, the reader knows that //
is coming from htmltools and not necessarily the dash-renderer API. In the future if you refactor out htmltools
, then the reader will know that this //
won't need to be handled because htmltools
was the source of the issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've started the process of 🔪 htmltools
, managed to remove nearly all references to this package, but not quite there yet. I opened an issue earlier this week which attempts to enumerate all the spots in the code and comments that are involved:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah - My suggestion here is mostly just to get in the habit of writing these types of commits - if there is something in the code that looks odd, it's good to get in the habit of explaining why we have to do stuff like this and where the problem originated.
In this case, everyone involved in this PR is now aware of the issue and you will be the one refactoring it shortly. However, imagine the case where this refactor might happen 6 months from now by someone else. If they didn't know that this //
was originating from htmltools
, then they might not feel comfortable removing this block of code. Perhaps they might think that dash-renderer
(a 3rd party piece of code) sometimes introduces a //
in certain scenarios, scenarios that might not necessarily be tested in integration tests.
So, it's not strictly necessary in this scenario where we plan on fixing this up in a couple of weeks, but it's a good habit to get into and a healthy way to start thinking about comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For sure, decisions like these seem apparent now that I'm staring at the same code over and over again, but for anyone else (or me even a year from now), statements like this are hard to comprehend in total isolation.
I'll be a bit more diligent about making these sorts of commits, it benefits everyone from the author, to the reviewer, and even savvy users who decide to take a look under the hood.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in b77c94d
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working through all of these suggestions!
💃 Once you've considered a few small suggestions concerning comments
This PR will introduce a 'catchall' endpoint
/*
, which will be added as the final handler in theroutr
stack.Additionally, DashR does not inspect local environment variables when initializing an app;
routes_pathname_prefix
andrequests_pathname_prefix
must be set manually. For greater parity with Dash for Python, the following route-related variables should be checked before setting route prefixes toNULL
:DASH_URL_BASE_PATHNAME
DASH_ROUTES_PATHNAME_PREFIX
DASH_REQUESTS_PATHNAME_PREFIX
Two additional helper functions are proposed in this PR:
get_package_mapping
: given path to dependency, package string from request URL, and list of dependencies, attempts to build apackage_map
. The mapping is then used to resolve local paths to dependencies within the R packages that provide them. A list is returned with the R package name providing the dependency, as well as a local path to the file.get_mimetype
: resolve dependency MIME type based on file extension, currently supportsapplication/JavaScript
,application/json
,text/css
.Lastly, previous versions of DashR did not include a
_dash-component-suites
handler. This PR alsoressource_route
(which resolves a duplicate route error for the React JS upon relaunching an existing DashR app in the current workspace)dashR::resolve_dependencies
andregister_dependencies
htmltools
dash_suite
handler to serve dependency files, following the Dash conventionCache-Control
header, and setting the cache lifetime viacomponents_cache_max_age
dash_renderer
,react
,react-dom
) as being part of thedash_renderer
"package", to mirror behaviour in Dash for PythonThis PR is a work in progress, aiming to implement similar behaviour as found in
_configs.py
:https://github.com/plotly/dash/blob/f590166be2ca476c8970512fd9b23aaf26541ae8/dash/_configs.py#L8
...and in
dash.py
:https://github.com/plotly/dash/blob/1249ffbd051bfb5fdbe439612cbec7fa8fff5ab5/dash/dash.py#L488
Closes #52.