﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
23350	mod_wsgi authentication/authorization docs result in extra memory usage	Graham Dumpleton	Daniel Craigmile	"The documentation at:

* https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/apache-auth/

uses the examples:


{{{
WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
WSGIPythonPath /path/to/mysite.com

WSGIProcessGroup %{GLOBAL}
WSGIApplicationGroup django

<Location ""/secret"">
    AuthType Basic
    AuthName ""Top Secret""
    Require valid-user
    AuthBasicProvider wsgi
    WSGIAuthUserScript /path/to/mysite.com/mysite/wsgi.py
</Location>

}}}

and

{{{
WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py

WSGIProcessGroup %{GLOBAL}
WSGIApplicationGroup django

<Location ""/secret"">
    AuthType Basic
    AuthName ""Top Secret""
    AuthBasicProvider wsgi
    WSGIAuthUserScript /path/to/mysite.com/mysite/wsgi.py
    WSGIAuthGroupScript /path/to/mysite.com/mysite/wsgi.py
    Require group secret-agents
    Require valid-user
</Location>
}}}

Although these will work, they cause the Django application code to be loaded more than once into the same process. That is, you end up with an instance in one sub interpreter which handles web request, and another instance in another sub interpreter which handles just authentication and authorisation.

Ideally you do no want two copies as that simply increases overall memory usage.

The original mod_wsgi documentation does point to this in the statements:

    ''By default the auth providers are executed in context of first interpreter created by Python, ie., '%{GLOBAL}' and always in the Apache child processes, never in a daemon process. The interpreter can be overridden using the 'application-group' option to the script directive. The namespace for authentication groups is shared with that for application groups defined by WSGIApplicationGroup.''

    ''Because the auth provider is always run in the Apache child processes and never in the context of a mod_wsgi daemon process, if the authentication check is making use of the internals of some Python web framework, it is recommended that the application using that web framework also be run in embedded mode and the same application group. This is the case as the Python web frameworks often bring in a huge amount of code even if using only one small part of them. This will result in a lot of memory being used in the Apache child processes just to support the auth provider.''

To combat this double of memory usage the mod_wsgi documentation gives the example of:

{{{
WSGIAuthUserScript /usr/local/django/mysite/apache/auth.wsgi application-group=django
}}}

It is this use of the  {{{application-group}}} argument for {{{WSGIAuthUserScript}}} and {{{WSGIAuthGroupScript}}} that the Django documentation doesn't use.

The Django examples therefore should really use:

{{{
WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
WSGIPythonPath /path/to/mysite.com

WSGIProcessGroup %{GLOBAL}
WSGIApplicationGroup django

<Location ""/secret"">
    AuthType Basic
    AuthName ""Top Secret""
    Require valid-user
    AuthBasicProvider wsgi
    WSGIAuthUserScript /path/to/mysite.com/mysite/wsgi.py application-group=django
</Location>

}}}

and

{{{
WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py

WSGIProcessGroup %{GLOBAL}
WSGIApplicationGroup django

<Location ""/secret"">
    AuthType Basic
    AuthName ""Top Secret""
    AuthBasicProvider wsgi
    WSGIAuthUserScript /path/to/mysite.com/mysite/wsgi.py application-group=django
    WSGIAuthGroupScript /path/to/mysite.com/mysite/wsgi.py application-group=django
    Require group secret-agents
    Require valid-user
</Location>
}}}

On the presumption that there is only the one Django application, it may actually be better to turn that around and force the Django application to run in the main interpreter anyway. This is better as some third party extension modules for Python do not work properly in sub interpreters.

Thus may be better to use:

{{{
WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
WSGIPythonPath /path/to/mysite.com

WSGIProcessGroup %{GLOBAL}
WSGIApplicationGroup %{GLOBAL}

<Location ""/secret"">
    AuthType Basic
    AuthName ""Top Secret""
    Require valid-user
    AuthBasicProvider wsgi
    WSGIAuthUserScript /path/to/mysite.com/mysite/wsgi.py
</Location>

}}}

and

{{{
WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py

WSGIProcessGroup %{GLOBAL}
WSGIApplicationGroup %{GLOBAL}

<Location ""/secret"">
    AuthType Basic
    AuthName ""Top Secret""
    AuthBasicProvider wsgi
    WSGIAuthUserScript /path/to/mysite.com/mysite/wsgi.py
    WSGIAuthGroupScript /path/to/mysite.com/mysite/wsgi.py
    Require group secret-agents
    Require valid-user
</Location>
}}}"	Cleanup/optimization	closed	Documentation	1.6	Normal	fixed	afraid-to-commit		Ready for checkin	1	0	0	0	1	0
