[mod_python] multiple requests to authenhandler for a single url

Jim Gallacher jg.lists at sympatico.ca
Wed Oct 5 19:00:42 EDT 2005


I wonder if this is just the way apache is supposed to work? Perhaps
it's a feature, not a bug? I can see the logic of checking the
authorization for each subdirectory.

 From the apache documentation I found the following somewhat related
information which may give some insight...  or it may be totally
irrelevant ;).

http://httpd.apache.org/docs/2.0/howto/htaccess.html
"""
When (not) to use .htaccess files

<snip />

The first of these is performance. When AllowOverride  is set to allow
the use of .htaccess files, Apache will look in every directory for
.htaccess files. Thus, permitting .htaccess files causes a performance
hit, whether or not you actually even use them! Also, the .htaccess file
is loaded every time a document is requested.

Further note that Apache must look for .htaccess files in all
higher-level directories, in order to have a full complement of
directives that it must apply. (See section on how directives are
applied.) Thus, if a file is requested out of a directory
/www/htdocs/example, Apache must look for the following files:

/.htaccess
/www/.htaccess
/www/htdocs/.htaccess
/www/htdocs/example/.htaccess

And so, for each file access out of that directory, there are 4
additional file-system accesses, even if none of those files are
present. (Note that this would only be the case if .htaccess files were
enabled for /, which is not usually the case.)
See  I see that apache will attempt to read .htaccess for all the
subdirectories in a request.
"""

The important point is that apache attempts to read the .htaccess file
for each subdirectory. It's not too much of a stretch to imagine that it
may call the auth handler once for each subdirectory in a url as well.

What happens if you set "AllowOverride None"?
Note that AllowOverride is only available in a <Directory> section.

None of this is a solution to your problem, but it may spark some ideas.

Regards,
Jim


reghigh wrote:
> I am encountering the following issue (which has already been raised on 
> this list about a year ago~[1]) relating to multiple calls to 
> authenhandler. To demonstrate I have the following:
> 
> apache2 httpd.conf
> ******************
> 
> <VirtualHost *:80>
>   ServerName static
>   DocumentRoot <omitted>
> 
>   PythonPath "['<omitted>'] + sys.path"
>   PythonAuthenHandler test
>   PythonDebug On
> 
>   <Location />
>       AuthType Basic
>       AuthName "Restricted Area"
>       Require valid-user
>   </Location>
> </VirtualHost>
> 
> test.py
> *******
> 
> from mod_python import apache
> 
> count = 0
> 
> def authenhandler(req):
> 
>     pw = req.get_basic_auth_pw()
>     user = req.user
>     global count
>     count += 1
>     raise Exception('%s, %s, %s, %s, %s, %s' % \
>         (req.handler, req.unparsed_uri,
>         req.path_info, req.used_path_info))
> 
> Results
> *******
> 
> Note output is trimmed for readability~[2]
> 
> url: http://static/x
> 
> Exception: None, /x, , 2
> 
> url: http://static/x/y
> 
> Exception: None, /y, , 2
> Exception: None, /x/y, /y, 2
> 
> url: http://static/x/y/z
> 
> Exception: None, /z, , 2
> Exception: None, /y/z, /y, 2
> Exception: None, /x/y/z, /y/z, 2
> 
> etc
> 
> Note that this is invariant to url naming used: /<1>/<2>/.../<n>
> 
> produces exceptions with unparsed uri sections:
>   /<n>
>   /<n-1>/<n>
>   ......
> 
>  From now on will use notation <url> -> (url1, url2, ....) to mean a 
> given url produced an exceptions in order with unparsed_uri = url1, url2 
> etc
> 
> Varying Location Directive
> ==========================
> 
> Now experimentation yielded the following. If Location directive was 
> changed say to
> 
> <Location /x>
> 
> Then
> 
>   /x -> (/x) = 1 request
>   /xx -> not processed by handler
>   /x/y -> (/x/y) = 1 request
>   /x/x/y -> (/x/y, /x/x/y) = 2 requests
> 
> <Location ~ "^/[xy]">
> (NB: this all works with <LocationMatch "^/[xy]">)
> 
> Then
> 
>   /x -> (/x) = 1R
>   /xx -> (/xx) = 1R
>   /x/y -> (/y, /x/y) = 2R
>   /x/z/ -> (/x/z) = 1R
>   /x/y/z -> (/y/z, /x/y/z) = 2R
>   /x/y/z/x -> (/y/z/x, /x/y/z/x) = 2R
>   /x/y/x -> (/x, /y/x, /x/y/x) = 3R
>   /x/y/ -> (/y/, /x/y/) = 2R
> 
> This suggests that somehow the Location directive (i have also confirmed 
> similar behaviour using the <Directory>) gives rise to multiple requests 
> to authenhandler. However this matching to generate requests as shown 
> above does not occur in any simple way (it seems to match from the left 
> hand side of the url string but once it encounters a non-match it halts).
> 
> Multiple calls not only cause serious overhead if authenticating off a 
> database but also play havoc with a system based access control via urls 
> since you want to match against the full url but the authenhandler gets 
> the full url last out of all the urls it gets passed. What i want is for 
> the Location directive to generate a single call to the authenhandler 
> with the whole uri being passed.
> 
> Does anyone have any ideas what is causing this and how I could solve 
> the problem.
> 
> Regards,
> 
> Tristan
> 
> ------------------
> 
> [1] http://www.modpython.org/pipermail/mod_python/2004-November/016750.html
> Complete summary here: http://www.scanmine.com/mp/mod_python_b_p.html
> 
> [2] For example
> 
> Exception: None, /y, , 2, None
> Exception: None, /x/y, /y, 2, None
> 
> in full was:
> 
> <pre>
> Mod_python error: "PythonAuthenHandler test"
> 
> Traceback (most recent call last):
> 
>   File 
> "/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/mod_python/apache.py", 
> line 299, in HandlerDispatch
>     result = object(req)
> 
>   File "/Users/rgrp/Sites/python/test.py", line 11, in authenhandler
>     raise Exception('%s, %s, %s, %s, %s' % \
> 
> Exception: None, /y, , 2, None
> 
> </pre>
> 
> <pre>
> Mod_python error: "PythonAuthenHandler test"
> 
> Traceback (most recent call last):
> 
>   File 
> "/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/mod_python/apache.py", 
> line 299, in HandlerDispatch
>     result = object(req)
> 
>   File "/Users/rgrp/Sites/python/test.py", line 11, in authenhandler
>     raise Exception('%s, %s, %s, %s, %s' % \
> 
> Exception: None, /x/y, /y, 2, None
> 
> </pre>
> _______________________________________________
> Mod_python mailing list
> Mod_python at modpython.org
> http://mailman.modpython.org/mailman/listinfo/mod_python
> 




More information about the Mod_python mailing list