script alias sometimes cut off in generated paths
Right now I've got a django app running with mod_wsgi. This is a piece of my setup...
WSGIProcessGroup application_internal
WSGIDaemonProcess application_internal python-path=/opt/application/ python-home=/opt/ENV processes=8
WSGIScriptAlias /test/application_path /opt/application/wsgi.py process-group=application_internal
WSGIPassAuthorization On
It works OK most of the time. The /test/application_path I've added to WSGIScriptAlias was requested by a client. I added it so that I could serve the application at
http://application.com/test/application_path
instead of
https://application.com/
However, I've noticed that sometimes the links generated by my application are invalid - and by invalid I mean they leave out the script alias path. So I'll get links like
https://application.com/index.html
instead of
https://application.com/test/application_path/index.html
Maddeningly, this behavior's inconsistent. Usually I get valid paths - but sometimes I don't. I've partially worked around it by creating a rewrite rule with mod_rewrite to correct the paths. This works well for the domain I'm hosting it at and I'm always able to get everything to load as expected. But there's yet another wrinkle as the site is also served up via reverse proxy to an external domain. Since the reverse proxy is configured not to rewrite any links on these pages and just forward everything at /test/application_path to my server, if my server generates invalid links (as above) they direct to the wrong part of the non-proxied site and 404.
Hopefully this all makes sense. I don't think I'm doing anything unusual/exotic. When I run this setup with a script alias path (just / ) everything is fine. I never had this problem before I added /test/application_path to the script alias. Any insight into where I might look for issues in either my mod_wsgi config or elsewhere would be much appreciated.
In WSGI applications it is very important to follow a specific algorithm to construct URLs for pages or when redirecting.
- https://peps.python.org/pep-3333/#url-reconstruction
This is so that the mount point path prefix (SCRIPT_NAME as passed by WSGI) is always included in the URL which is constructed.
Django provides its own functions and template tags which encapsulate this URL reconstruction algorithm.
- https://docs.djangoproject.com/en/5.2/ref/urlresolvers/#django.urls.reverse
- https://docs.djangoproject.com/en/5.2/ref/templates/builtins/#url
- https://docs.djangoproject.com/en/5.2/ref/templates/builtins/#static
If you don't consistently use these and instead start hard coding URL paths such as /index.html then you will not get the mount point path prefix added to URL paths.
In the first instance I would suggest checking very carefully your code to ensure you are not inadvertently generating an absolute path yourself instead of using the Django functions/template tags. Also be careful of using a hard coded relative URL path such as ./index.html in case you have situations where a handler might be called for a URL path with or without a trailing slash, as the result will not be the same for each if you use a relative path.
Another problematic case from memory when moving to mount at a sub URL path is that certain Django settings don't automatically add in the mount point path prefix when you provide a fixed absolute path. I recollect that LOGIN_URL and related settings may fall in this category.
- https://docs.djangoproject.com/en/5.1/ref/settings/#login-url
So if using these settings it looks these days like you need to avoid using a fixed URL path in those settings and instead use a named URL pattern so that standard URL reverse function is used.
The only other thing I can think of that may cause problems is that if you had strange rewrite rules in Apache to start with for other reasons, eg. related to auth etc. Do you have magic rewrite rules in Apache for any other reason?