How to simulate mod_wsgi prefix in django tests? - django

I'm using mod_wsgi with a url prefix. my setup is:
Alias /prefix /path_to_wsgi_file/file.wsgi
<Directory /path_to_wsgi_file>
Options ExecCGI
SetHandler wsgi-script
...
</Directory>
I would like my django tests to simulate this situation so I could avoid differences between the testing and real env. That means I want request.get_full_path() to contain the /prefix
Any way to do that?
EDIT: after going through the source to understand what FORCE_SCRIPT_NAME does, looks like it's used when wsgi.py calls set_script_prefix() of urlresolvers.
My problem is that this isn't called when I run "manage.py test".
I guess I could call this method myself in the test.
Any better suggestions?

Usually, you'll have the SCRIPT_NAME properly configured on the Web server and let reverse handle everything for you. If you want to configure a particular prefix to be applied, you can configure FORCE_SCRIPT_NAME, which will override any particular SCRIPT_NAME that may be configured or not.
This will allow you to reverse and serve URLs on a given /prefix.

Related

Using lets encrypt without control over the root directory

I'm running a Django website and using lets encrypt for my SSL. Configuration of the framework is such that I can't allow access on: http://url.com/.xxxx
What I can allow free access to is:
http://url.com/static/.xxxx
My /static/ URL can accept and host any random files lets encrypt needs. Is there a way to have certbot support /static/ instead of just using / for the URL?
Thanks
EDIT
I've found a work around that is acceptable for me. Further digging, I found that /.well-known/ is always the base directory for SSL checking. That means we can add a static directory which will work nicely with certbot. Here's how, firstly add this into your apache config:
Alias /.well-known/ /var/www/XXXXX/website/static/.well-known/
<Directory /var/www/XXXXX/website/static/.well-known/>
Require all granted
</Directory>
Then add this into your settings.py file:
STATIC_ENCRYPT_URL = '/.well-known/'
STATIC_ENCRYPT_ROOT = '/var/www/XXXXX/website/static/'
Add this into your urls.py:
urlpatterns = [
...
] + static(settings.STATIC_ENCRYPT_URL, document_root=settings.STATIC_ENCRYPT_ROOT)
Reset your webserver. Now you have a special url /.well-known/ which will host any file certbot requires.
I'd still like a better answer than this.
In case other users come this way like I did from Google, here's how I improved this situation:
I was unsatisfied by my options when it came to creating ACME challenges for Let's Encrypt when running a Django application. So, I rolled my own solution and created a Django app! Basically, you can manage your ACME challenges as just another object, and the app will produce the proper end-point URL.
Simply pip install django-letsencrypt and follow the README to be on your way.

django multisite with only one wgsi file

I'm using a virtual dedicated server which allow not to change apache virtual hosts. So I'm stuck with only one wsgi file.
There is few doc about multisite in django, so I believe the answer to my question is NO, but I prefere to be sure : is there any way to declare more than one website inside a wsgi file ? Or must I use some middleware ?
If you cannot change the VirtualHost at all then you may not get very far. You at least need to be able to add additional ServerAlias directives to the VirtualHost such that the extra hostnames get mapped to that WSGI application. If they are all a sub domain then a wildcard can be used, but you still need to be able to add the wildcard ServerAlias for sub domains to the VirtualHost.

Nginx+FastCGI+Django Remove URL Prefix before passing to Django

I've setup Nginx to fastcgi_pass to Django and don't want to serve Django from "/". I want to prefix the URLs with something like "/django/sample/" but then have Nginx remove that prefix before it gets passed to Django - this way Django's internals will act like it's actually serving from "/".
I've tried updating the Django app to include the prefix in the URLs routed, like this:
urlpatterns = patterns('',
'^', include(base_urlpatterns), # iff you wish to maintain the un-prefixed URL's too
'^your_prefix/', include(base_urlpatterns),
)
And I currently do a fastcgi_pass like so:
#django sample
location /django/sample {
include fastcgi_params;
fastcgi_pass 127.0.0.1:8024;
}
But this isn't a graceful solution as any URL in my django app then has to make sure to include a prefix like "/django/sample". And it also means that when I run locally VS on the server the URLs may need to be different.
I build quite a few django apps that'll be running from one server and don't want to always have to do this tom-foolery with URLs and remember to update all the URLs in Django.
I've been googling for a while trying to figure out how to do this with nginx but haven't seen anything.
So, I'm looking to use Nginx to remove the "/django/sample" in the request before it gets passed to Django. Anyone done this before?
You're approaching this the wrong way round. There's no reason to remove the prefix before passing to Django: as long as you configure your server correctly, Django will be aware of it, and will automatically use it in things like the {% url %} tag and reverse() call (which of course you're using for all your URL references internally).
The documentation for deploying with FastCGI gives some details of how to set the prefix, in particular the advice that if you can't get it to work any other way, you can explicitly set FORCE_SCRIPT_NAME to the value of your prefix.

Django WSGI list enabled modules

I am using Django on Apache with mod_wsgi. I would like to use X-Sendfile for sending files, but with fallback when the X-Sendfile is not available.
Is there any way to list loaded Apache modules or to check whether the X-Sendfile is enabled or not directly from Django? I tried to dump the request variable, but there's no such information.
Add into Apache configuration:
<IfModule mod_xsendfile.c>
Setenv apache.modules.mod_xsendfile On
</IfModule>
The request meta variables, ie., WSGI environ dictionary, would then have an entry for 'apache.modules.mod_xsendfile' with value 'On'. You can check for presence of variable and modify behaviour accordingly.

Running the django admin over https using apache2

I have a django web application that's running on apache 2.2.14 and I want to run the admin application over https.
Having read considerable discussions on using a proxy, writing middleware, running alternative wsgi scripts, the chaps in #httpd came to my rescue. The solution is so simple, I was surprised I didn't find it online, so I'm curious to see if I've made some glaring assumptions or errors.
One complication was that I also wanted to run one of my django apps in the site over https, that is everything on /checkout.
Essentially, if a user requests a URI starting with /admin or /checkout on http, they are to be redirected to that URI but on https. Conversely, if a user requests a URI that does not start with /admin or /checkout on https, they are to be redirected to that URI but on http.
The key to solving this problem was to use Redirect and RedirectMatch directives in my VirtualHost configuration.
<VirtualHost *:80>
... host config stuff ...
Redirect /admin https://www.mywebsite.com/admin
Redirect /checkout https://www.mywebsite.com/checkout
</VirtualHost>
<VirtualHost *:443>
... ssl host config stuff ...
RedirectMatch ^(/(?!admin|checkout).*) http://www.mywebsite.com$1
</VirtualHost>
Another approach is to use #secure_required decorator. This will automatically rewrite the requested url and redirect to https://... version of the URL. Then you don't have to have Redirect in *:80 configuration. *:443 configuration may still be required for performance purpose if you want other traffic to go through normal http traffic.
I tried your solution, but ran into several problems. First, the formatting on the admin site disappeared, as if it could not find the admin static files. Second, if I tried to reach the non-admin site through https, the browser would not find it and redirect me to Yahoo search. Oddly, if I edited the yahoo search URL to eliminate all text except my correct URL (minus the http://), it would continue to search through yahoo for my site. However, typing the exact same URL afresh sent me to my site.
I solved all of these issues by simply removing the
RedirectMatch ^(/(?!admin|checkout).*) http://www.mywebsite.com$1
directive.
I should mention that I don't have a /checkout section on my site and am only trying to secure /admin. ... and yes, I did substitute my URL for "mywebsite.com"
What you described should work, but there may be a problem in the future if you need to make changes to which paths are/are not HTTPS. Because this method requires the ability to correctly modify the Apache config file it means you do not want novices in the loop. Screw up the config file and your site can go 500-error in the blink of an eye.
We chose to have a simple text file that had a list of the must-be-HTTPS paths. Anyone on the project can edit it and it is checked for correctness when it is loaded. We handle any needed redirects to/from HTTPS in middleware and it seems to work just fine. This method will also work if you are running anything other than Apache.