Django WSGI list enabled modules - django

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.

Related

HTTP headers list

I am studying Django and have created a page that shows all HTTP headers in a request using request.META dictionary. I'm running it locally and it the page shows me a weird amount of headers like 'TEMP' containing the path to my Windows temp folder, or 'PATH' with my full path parameters and much more information that I don't really find necessary to share in my browser requests (like installed applications).
Is it normal? What do I do about it?
So, let's jump quickly into Django's source code:
django/core/handlers/wsgi.py
class WSGIRequest(http.HttpRequest):
def __init__(self, environ):
...
self.META = environ
self.META['PATH_INFO'] = path_info
self.META['SCRIPT_NAME'] = script_name
...
This handler is used by default in runserver command and every other wsgi server. The environ dictionary comes from the underlying web server. And it is filled with lots of data. You can read more about environ dictionary here in the official wsgi docs:
https://www.python.org/dev/peps/pep-0333/#environ-variables
Also note that any web server is free to add its own variables to environ. I assume that's why you see things like TEMP. They are probably used internally by the web server.
If you wish to get headers only then wsgi mandates that headers have to start with HTTP_ prefix with the exception of CONTENT_TYPE and CONTENT_LENGTH headers.
So Django's docs are misleading. The META field contains more then headers only. It is neither correct nor incorrect, it's just how it is. Special care has to be taken when dealing with META. Leaking some of the data might be a serious security issue.

Django REMOTE_USER does not exist but HTTP_REMOTE_USER does

All,
I have what should be a very simple problem. I am trying to use Django authentication using the REMOTE_USER variable following these instructions: https://docs.djangoproject.com/en/1.8/howto/auth-remote-user/.
Then, to test that this is working, I am using the postman chrome extension. There I am setting a header variable with the name "REMOTE-USER" and then text for a superuser, and then I'm hitting the django admin page. I don't automatically login.
I set a break point in the process_request function in the RemoteUserMiddleware class. When I make the request, I see that request.META["HTTP_REMOTE_USER"] exists but request.META["REMOTE_USER"] does not exist. The default RemoteUserMiddleware variable uses header="REMOTE_USER". It seems that HTTP Header variables gets a HTTP_ prefix, so I don't understand how this would ever work.
I feel like I must be missing something obvious. Thanks!
The REMOTE_USER is meant to be an environment variable set by your web server (e.g. Apache), not an HTTP header. If it was an HTTP header, then users would be able to spoof the header, and log in as any user they wanted.
All http headers are prefixed HTTP_ so that you can distinguish between them and environment variables.
You can set the environment variable with the development server as follows.
REMOTE_USER=admin ./manage.py runserver

Resource interpreted as Font but transferred with MIME type font/woff: | Django Framework

I know in Apache One adds
RewriteEngine On
RewriteRule !(\.ico\.gif|\.png|\.jpe?g|\.css|\.js|\.php|\.eot|\.svg|\.ttf|\.woff|\.otf|^public/.*)$ index.php [nocase,last]
but How I do with Django, these rules
So, you are serving static files in Django dev server?
In settings.py I think you need:
if DEBUG:
import mimetypes
mimetypes.add_type("application/font-woff", ".woff", True)
...from info given in these questions on SO:
Resource interpreted as Font but transferred with MIME type application/x-font-woff
Django development server and MIME types

How to simulate mod_wsgi prefix in django tests?

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.

How to access mod_ssl environment variables from django using mod_wsgi?

I'm trying to get the client's certificate and sign an xml file using it.
I have added the following to my virtual hosts:
SSLVerifyClient optional
SSLVerifyDepth 1
SSLOptions +stdEnvVars
This should allow mod_ssl to get the user's certificate. But I don't know how to pass it along to my django app. Any help is appreciated. Thanks.
You should use
SSLOptions +StdEnvVars
SSLOptions +ExportCertData
in apache config to have SSL_CLIENT_CERT in the environment.
With flask, it will be in request.environ['SSL_CLIENT_CERT']
Based on the discusson of the other answer, it might be request.META['SSL_CLIENT_CERT'] for django.
Those Apache configuration directives mean that mod_ssl environment variables should now be available in the environment inherited by Django. You can therefore access them using the os.environ object in your Django view:
import os
client_cert = os.environ['SSL_CLIENT_CERT']
The SSL_CLIENT_CERT variable contains the PEM-encoded client certificate.
SSLOptions +StdEnvVars +ExportCertData
SSL_CLIENT_CERT will contain the PEM encoded certificate.
SSL_CLIENT_CERT_CHAIN_n (where n is a number) and SSL_SERVER_CERT are also included, but probably uninteresting.
It's a pity that one can't configure exactly which items you want added to the environment. It would be much more svelte having only what's needed (for me common name and that the verify succeeded - though that may be implied with verify required, and for you the client cert PEM).