[mod_python] Custom Login with redirection back to referer

Jim Gallacher jpg at jgassociates.ca
Sun May 21 10:17:52 EDT 2006


Graham Dumpleton wrote:
> 
> On 21/05/2006, at 3:23 PM, Deron Meranda wrote:
> 
>> On 5/20/06, Jim Gallacher <jpg at jgassociates.ca> wrote:
>>> But I suspect if browser is too old to understand a 307 redirect, most
>>> web pages that user visits are almost completely unreadable anyway. :)
>>
>> I still remember coding up web pages for the old Mosaic
>> browser, so by this point what's old, new, or stone-age
>> is pretty much a blur ;)
>>
>>> Not completely on topic, but since we are talking about 30x redirects, I
>>> thought I'd mention that I've modified util.redirect to support any of
>>> the 30x codes. It's a pretty simple change, where util.redirect becomes
>>>
>>> def redirect(req, location, permanent=0, status=None, text=None)
>>>
>>> If status is not None it overrides the permanent parameter. I want this
>>> so I use util.redirect with a 303 HTTP_SEE_OTHER response after creating
>>> a resource with a POST. (for the POST-REDIRECT-GET pattern used in
>>> RESTful applications).
>>
>> It's nice to get support for more the the response codes.  I think
>> it's interesting to see how designing RESTful makes one think
>> a lot more about the why and not just how of the HTTP protocol
>> details.
>>
>> As far as the redirect() function.  The only thing that bothers
>> me a bit is having two mutually-exclusive parameters.  But I'm
>> not sure how you'd fix that will maintaining backwards compatibility.
>>
>> But I have to admit I often do things the "hard way" out of
>> habit back from the days when I coded "nph-" style CGI scripts.
>> I tend not to use the redirect() helper function, and instead
>> do everyting at a lower level.  Some day I'll convert.
> 
> Personally I am probably -1 on overloading util.redirect() to do this. 
> That function
> isn't too complicated, but probably should be kept just for the simple 
> cases. If
> someone knows enough to use other cases, they are probably knowledgeable
> enough to know how to do it properly themselves at the lower level.

One could argue, (and one will argue, since one wants to use other 30x 
codes but not maintain a separate function in one's own code ;) ), that 
util.redirect is actually broken as it only supports a subset of 30x 
responses. Perhaps it should have been call util.moved() or something.

I don't see adding a parameter to redirect() to support the other 30x 
codes as overloading. The intent of redirect has not changed, and we 
could check that the status is in valid range to enforce this. I do 
however acknowledge the concern about passing 2 mutually exclusive 
parameters but I don't see any other way to munge the code.

Here's what my new version looks like. Note that most of the changes 
consistent of head scratching comments. Actual code changes are only a 
couple of lines.

def redirect(req, location, permanent=0, status=None, text=None):
     """
     A convenience function to provide redirection
     """

     if req.sent_bodyct:
         raise IOError, "Cannot redirect after headers have already been 
sent."

     req.err_headers_out["Location"] = location

     if not status:
         if permanent:
             req.status = apache.HTTP_MOVED_PERMANENTLY
         else:
             req.status = apache.HTTP_MOVED_TEMPORARILY
     else:
         # TODO? should we verify that status is in 30x range?
         # TODO? RFC2616 has some special header requirements
         # for HTTP_NOT_MODIFIED 304 response. Should we raise an error
         # if these conditions are not met, or just assume the
         # caller knows what they are doing and have set the headers?
         # ie. Date, Etag, etc.
         # see http://rfc.net/rfc2616.html#s10.3.5
         req.status = status

     if req.status is not apache.HTTP_NOT_MODIFIED:
         # RFC-2161 says HTTP_NOT_MODIFIED (304)
         # response MUST NOT contain a message-body
         # Any others are ok
         # TODO according to RFC-2616 the reponse should not contain
         # a message body for HEAD method. Should we test here or just
         # depend on apache to truncate the body?
         # TODO we shouldn't write anything if the request is a
         # HEAD method. I believe apache will take care of this in
         # a later phase, so we won't worry about it here.

         if text is None:
             req.write('<p>The document has moved'
                      ' <a href="%s">here</a></p>\n'
                      % location)
         else:
             req.write(text)

     raise apache.SERVER_RETURN, apache.DONE


Jim


More information about the Mod_python mailing list