#9805: reverse() does not add SCRIPT_NAME to the returned URL if called from
middleware modules
-------------------------------------+--------------------------------------
          Reporter:  ElliottM        |         Owner:  mtredinnick
            Status:  new             |     Milestone:             
         Component:  Core framework  |       Version:  1.0        
        Resolution:                  |      Keywords:             
             Stage:  Unreviewed      |     Has_patch:  1          
        Needs_docs:  0               |   Needs_tests:  0          
Needs_better_patch:  0               |  
-------------------------------------+--------------------------------------
Changes (by mtredinnick):

  * owner:  nobody => mtredinnick

Old description:

> For example, take the following middleware.py file, with one example
> middleware thing that redirects you to the login page if you are not
> logged in:
>
> {{{login_url=reverse('login')
>
> class LoginMiddleware():
>         def process_request(self, request):
>                 if(request.user.is_anonymous() and
> request.path!=login_url):
>                         #force login
>                         return
> HttpResponseRedirect(login_url+'?next='+request.path)}}}
>
> In this case, login_url will be correct except for the fact that it will
> be missing the SCRIPT_NAME. Putting the reverse() call inside the
> process_request function solves the problem, but it makes no sense at all
> to call that reverse function for every request when it can be called
> once at server startup.
>
> The cause is in django.core.handles.wsgi and
> django.core.handlers.modpython
>
> {{{
> if self._request_middleware is None:
>    self.load_middleware()
>
> set_script_prefix(req.get_options().get('django.root', ''))
> }}}
>
> As you can see, "set_script_prefix" is called AFTER middleware is loaded,
> so the script name is still unset when reverse() is called in the
> middleware above. Moving the set_script_prefix call above the
> load_middleware function solves the problem.

New description:

 For example, take the following middleware.py file, with one example
 middleware thing that redirects you to the login page if you are not
 logged in:

 {{{
 #!python
 login_url=reverse('login')

 class LoginMiddleware():
         def process_request(self, request):
                 if(request.user.is_anonymous() and
 request.path!=login_url):
                         #force login
                         return
 HttpResponseRedirect(login_url+'?next='+request.path)
 }}}

 In this case, login_url will be correct except for the fact that it will
 be missing the SCRIPT_NAME. Putting the reverse() call inside the
 process_request function solves the problem, but it makes no sense at all
 to call that reverse function for every request when it can be called once
 at server startup.

 The cause is in django.core.handles.wsgi and
 django.core.handlers.modpython

 {{{
 #!python
 if self._request_middleware is None:
    self.load_middleware()

 set_script_prefix(req.get_options().get('django.root', ''))
 }}}

 As you can see, "set_script_prefix" is called AFTER middleware is loaded,
 so the script name is still unset when reverse() is called in the
 middleware above. Moving the set_script_prefix call above the
 load_middleware function solves the problem.

Comment:

 (Fixed description formatting.)

 This isn't really fixing the problem, so much as hiding it. Loading the
 middlewares should not require access to SCRIPT_NAME (it can change
 between requests and the middleware is only loaded once). So the code you
 give actually contains a small bug -- probably not observable for
 something like the "logout" view, but a bug nonetheless, as it could
 reverse to a different URL for a different request.

 There's a metnion in another ticket that we might add a kind of "lazy"
 reverse() that resolves upon usage, rather than declaration. When I find
 that ticket, I'll drop in a comment here and wontfix this one. Leaving
 open for now to remind me to hunt down the other case.

-- 
Ticket URL: <http://code.djangoproject.com/ticket/9805#comment:2>
Django <http://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-updates@googlegroups.com
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to