Black Lives Matter. Please consider donating to Black Girls Code today.

Mod_wsgi guide with dash>=1.0

Is there a new guide to using mod_wsgi with Dash>1.0?

In particular, it’s unclear to me from this topic Mod_wsgi and dash - virtual host configuration how to set up requests_pathname_prefix while maintaining the ability to set the route through mod_wsgi (i.e. it seems that the way it’s set up in that example, you have to set the route twice, once in mod_wsgi, and then again in the app definition).

I used to follow this example Dash - 'Error loading layout' but it seems that approach no longer works with Dash>=1.0

@nedned you seem to have a lot of experience with this, would be awesome if you get a chance to share any thoughts.

It seems that if I want to run using integrated mod_wsgi and generally follow the current integration guide https://dash.plot.ly/integrating-dash, I need to something like this. It works, it just seems messy.

app1.py

import dash
import dash_html_components as html

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

wsgi.py

from werkzeug.wsgi import DispatcherMiddleware
from flask_app import flask_app
from app1 import app as app1

application = DispatcherMiddleware(flask_app, {
    '/app1': app1.server,
})

myapp.conf

WSGIScriptAlias /my_apps /whatever/wsgi.py

The DispatcherMiddleware is only needed if you’re integrating multiple WSGI apps together. So if you wanted multiple Dash (or other WSGI apps) which you’d add in the DispatcherMiddleware config, then yep, this is the right way to go. If not, then you’re right, it’s slightly more involved than required. I think you should be able to just drop the DispatcherMiddleware and set requests_pathname_prefix to /my_apps/ (or whatever you’ve set up as the WSGIScriptAlias alias). Although I it’s been a while since I’ve played around with the prefix stuff so this might not be quite right. But I think something along these lines should work.

By the way, if you’re not already using it, I’d recommend using mod_wsgi-express for running WSGI apps with mod_wsgi.

Thanks Ned, I think I obscured what I thought was awkward. It’s that I have to specify /myapps twice, once in the Dash app, and once again in the mod_wsgi configuration. I think that’s true whether I’m running one app or multiple. And it doesn’t seem trivial (though surely doable) to pass that information back to Dash from mod_wsgi in the form of some environment variable or something.

I liked running on the system mod_wsgi because then I can just run on port 80 and also not worry about adding it to startup config, etc. But it sounds like everything would be much easier if I just run on another port, with either gunicorn or mod_wsgi-express.

Thanks again.

Dash and your WSGI server are two separate systems, so ultimately your custom prefix will need to be configured in both. Best-practice is of course to only define the value once, and environment variables are a common way to solve this problem. It’s what I would be using.

Once you have exported an environment variable you can use it in your httpd.conf and also access it from your Dash app. I personally use direnv to automatically associate apply env variables on changing directories. Once you’ve got a sensible workflow worked out, I think this is the path of least resistance. Always keen to hear suggestions from others though!

mod_wsgi-express is really just a wrapper around mod_wsgi that gives you sensible defaults and allows you to spin up separate Apache processes on arbitrary ports. It makes using apache+mod_wsgi feel more like using something like gunicorn.