On Fri, Jul 31, 2009 at 2:33 PM, Jeff Hammel<[email protected]> wrote:
>
> On Fri, Jul 31, 2009 at 01:01:21PM -0500, Olemis Lang wrote:
>>
>> Is there any helper function in Trac I can use to clone an HTTP
>> Request object (i.e. instances of trac.web.api.Request) ?
>>
>> I already have a «real» request object provided by Trac and what I
>> really need is to obtain a Request object identical to that one, in
>> order to modify it later on.
>
> Hah! I had need of this very thing recently. I ended up just making a
> generic object and then setting the attrs I needed from the real request, but
> admittedly its a cheap hack and I'd much prefer a better solution. You can
> see what I did here:
>
> http://trac-hacks.org/browser/sharedcookieauthplugin/0.11/sharedcookieauth/sharedcookieauth.py#L22
>
Hi Jeff ! Thnx for the pointer. However I need more than that. I
really need a completely identical request, which includes «lazy»
attributes using callbacks, and so on.
I discarded the idea of using clones and I came up with a solution
based on Proxy objects (GoF pattern , yes I'm still a puritan ...),
since I realized (the third bottle of Vodka is the good one ...) that
what I really needed was to intercept and «override» the access to
attributes of the request object.
The basic intercept object looks like this :
{{{
#!python
class ObjectIntercept:
def __init__(self, obj, basecls):
self._target = obj
self._basecls = basecls
def __getattr__(self, attrnm):
val = getattr(self._target, attrnm)
if isinstance(val, types.MethodType) and val.im_class is self._basecls:
val = val.im_func.__get__(self, self.__class__)
setattr(self, attrnm, val)
return val
}}}
The next step was to implement a wrapper used to redirect the request
so that it could be processed by another IRequestHandler.
{{{
class RedirectIntercept(ObjectIntercept):
def __init__(self, reqi, env, **params):
super(RedirectIntercept, self).__init__(reqi, Request)
self.__params = params
self.__env = env
def redirect(self, url, permanent=False):
uobj = urlparse(url)
self.path_info = uobj.path
self.args = parse_qs(uobj.query)
self.args.update(self.__params)
# Needed because Trac built-in protection against CSRF attacks
self.args['__FORM_TOKEN'] = self._target.args.get('__FORM_TOKEN')
try:
RequestDispatcher(self.__env).dispatch(self)
except (RequestDone, TracError):
raise
except Exception, exc:
raise TracError("Error %s : %s" % (exc.__class__.__name__, \
exc.message))
# Return the contents provided by a different IRequestHandler
reqi = RedirectIntercept(req, env)
reqi.redirect('/path/to/new/request/handler?x=1')
}}}
This way I was able to simulate HTTP redirection without sending an
HTTP response. This is just the first part because what I really
needed was to perform such redirection and save the body of the HTTP
response using an StringIO stream. To do that I just needed to do the
following :
{{{
#!python
class IoIntercept(ObjectIntercept):
def __init__(self, reqi, strm):
super(IoIntercept, self).__init__(reqi, Request)
self.__strm = strm
def _start_response(self, status, headers):
if status.lower() != '200 ok':
self.raise_status_failed(status)
return self.__strm.write
def send_header(self, name, value):
pass
def raise_status_failed(self, code):
raise TracError('Request failed with status %s' % (code,))
}}}
I solved my problem this way :
{{{
#!python
def save_response(...):
strm = StringIO()
try:
reqi = IoIntercept(req, strm)
reqi = RedirectIntercept(reqi, self.env, **params)
try:
reqi.redirect(path)
except RequestDone:
pass
return strm.getvalue()
except TracError:
raise
except Exception, exc:
raise TracError("Error %s : %s" % (exc.__class__.__name__, \
exc.message))
finally:
strm.close()
}}}
and it works !
PS: I send the full code in here because my svn client doesnt work yet :-/
--
Regards,
Olemis.
Blog ES: http://simelo-es.blogspot.com/
Blog EN: http://simelo-en.blogspot.com/
Featured article:
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Trac
Users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/trac-users?hl=en
-~----------~----~----~----~------~----~------~--~---