rstudio / shiny-server

Host Shiny applications over the web.
https://rstudio.com/shiny/server
Other
712 stars 290 forks source link

SingleAppRouter.getAppSpec_p does too much work before matching URL #482

Closed jcheng5 closed 3 years ago

jcheng5 commented 3 years ago

A customer reported that a broken app_dir (e.g. root directory that doesn't exist) caused many apps on the server to be broken, not just the broken app itself. This is because during routing (i.e. getAppSpec_p()), the locations are tried one after another to see if they match the request URL. In the case of app_dir, the SingleAppRouter.getAppSpec_p method was doing a bunch of directory reading before even looking to see if the URL was a match; if that directory reading failed, the request would see a 500 error or whatever.

With this change, an error should only be seen when a broken app is actually being requested.

Testing notes

Add a section like this to the config file:

location /app {
  app_dir /blah;
  log_dir /var/log/shiny-server;
}

This should be done within the server { } directive, and it needs to come before any sibling location directives. For example:

# Instruct Shiny Server to run applications as the user "shiny"
run_as shiny;

# Define a server that listens on port 3838
server {
  listen 3838;

  location /app {
    app_dir blah;
    log_dir /var/log/shiny-server;
  }

  # Define a location at the base URL
  location / {

    # Host the directory of Shiny Apps stored in this directory
    site_dir /srv/shiny-server;

    # Log all Shiny output to files in this directory
    log_dir /var/log/shiny-server;

    # When a user visits the base URL rather than a particular application,
    # an index of the applications available in this directory will be shown.
    directory_index on;
  }
}

Before this fix, simply visiting the server's root URL would give you an error like:

An error has occurred Invalid application configuration. ENOENT: no such file or directory, scandir 'blah'

After the fix, everything works fine unless you navigate to the broken location, at which time you see the above error.