webapp - how to execute some common functionality before request handlers..?

238 views
Skip to first unread message

peterk

unread,
Jun 9, 2008, 8:42:17 AM6/9/08
to Google App Engine
I may be overthinking this..so sorry if there's an obvious
solution.. :) I'm sort of new to Python. I'd appreciate any help.

Basically I'm using the webapp framework, and I have my request
handlers..but before a request is handled, I have some common work I'd
like to execute, that I don't want to replicate inside each handler
(predominantly authentication stuff). In fact, I'll have multiple
classes with handlers for doing different work, and I'll need to run
this stuff before the handlers are called in each class One way that
works (at least for one class) is to extract the work into a function
and call the function first inside the handlers, but I don't want to
have to replicate that function across my handler classes, and I'd
like to avoid the function call inside my get(), post() etc. functions
also, if I can.

I tried overriding webapp.RequestHandler's __init__, but this doesn't
work. I had a root around the source code, and it doesn't have an
__init__ function. Its setup seems to happen in a function called
initialize, which expects a request and response as parameters
(parameters I can't provide).

So basically, is there some other way to customise what happens just
before a request handler function is called?

Many thanks for any help..

peterk

unread,
Jun 9, 2008, 11:07:57 AM6/9/08
to Google App Engine
I found a solution that works, so far.

Rather than overriding any functions in the RequestHandler class,
overriding the __call__ function in WSGIApplication allows me to (for
example) check the request headers for authentication info etc. and
return a 401 if it's not there or the right credentials aren't there.
Basically to do whatever I need to do before passing back and calling
the WSGIApplication classes's own __call__ function which resumes the
request handling as normal.

The idea here was to sort of replicate the ruby on rails idea of
having before_filters - common code that executes before any handlers
execute. This seems to work for me for now, but if anyone has ideas of
a more elegant/simpler approach, please let me know :)

Many thanks.

glenc

unread,
Jun 10, 2008, 9:27:04 AM6/10/08
to Google App Engine
Hi Peter,

I am prototyping an app now and this is something that I will need to
do too. I had initially assumed that this would be accomplished by
using @decorators on the get()/post() methods (as this is how a
similar functionality is implemented in TurboGears, which I have some
experience developing with) however, thinking more about the scoping
issues and so on and the way RequestHandlers are constructed compared
to the way the same thing is done in TurboGears, I'm not sure that the
decorator paradigm is the correct one for AppEngine.

Your method is interesting and seems like a valid way to go for now,
although does seem unnecessarily hacky. I'm hoping that someone can
offer a method that requires less delving into __ land ...

Mahmoud

unread,
Jun 10, 2008, 10:34:45 AM6/10/08
to Google App Engine
Why not put all the shared/preprocessing functionality in a base
class?

Class BaseHandler:
def get(self):
user = self.ensure_logged_in()
if user:
self.Put(user)

def post(self):
user = self.ensure_logged_in()
if user:
self.Post(user)

Then subclass and override Post() and Get()

peterk

unread,
Jun 10, 2008, 10:58:32 AM6/10/08
to Google App Engine
Hehe, thanks, that's indeed another possible solution. Although its
less transparent in that subclass handler functions would need to
invoke the super class's base function ( i think?), which is an extra
line of code in each handler function. And subclasses which mightn't
necessarily need to handle every request type would under this scheme
still do a certain minimum amount of processing instead of being
immediately discarded e.g. subclass A might only want to handle gets
and posts, but put or delete requests will still be processed to a
point by the base class.

They're not necessarily dealbreakers though, and that kind of
arrangement could allow more flexibility and is certainly less 'hack-
y' than overriding WSGIApplication functions..

Chad

unread,
Jun 10, 2008, 11:39:35 AM6/10/08
to Google App Engine
I was trying to figure out the exact same issue.. I would have liked
to use a common baseclass(es) and put the auth in the __init__ method
but it also broke for me.

I'm not using this solution but you can always use the bind auth to a
handler in the config file..

http://code.google.com/appengine/docs/configuringanapp.html under
"Requiring Login or Administrator Status"

peterk

unread,
Jun 10, 2008, 12:04:58 PM6/10/08
to Google App Engine
I think you need to be using the Google Users API to do things that
way, though? Or do you?

I'm rolling my own authentication. Plus I guess I'd like to be able to
stick in some other processing there prior to handling a request if I
need to. But if you're using Google Users then that would be by far
the simplest way, for sure..

Nick Johnson

unread,
Jun 10, 2008, 12:56:20 PM6/10/08
to Google App Engine
You can extend webapp.RequestHandler with your own class, and
implement initialize(self, request, response) - just remember to call
the parent class's version before doing anything.

On Jun 9, 1:42 pm, peterk <peter.ke...@gmail.com> wrote:

peterk

unread,
Jun 10, 2008, 3:16:07 PM6/10/08
to Google App Engine
This would be a more direct and elegant solution, but I've ran into
some problems with the implementation, problems I had before when I
tried to do something similar..maybe they'd be easily solved with a
better understanding of Python.

Basically the problem is if I try to set the response header (e.g. to
a 401, forbidden), while it will prompt the user for a user/pass (via
http authentication), if the user clicks cancel it just goes on and
continues the handler processing anyway. Simply setting the response
at that stage, during initialize, doesn't seem to over ride what comes
next.

Overriding the WSGIApplication's __call__ method gives you access to
start_response, which allows you to make a final and definitive
response, without any handler processing continuing if appropriate
(i.e. if authentication details are incorrect). I tried using that
here (it's usage is response.wsgi_write(start_response), but it says
it doesn't recognise start_response here.

My understanding here is limited though, maybe there is a way to do
this in RequestHandler's initialize?

Ross Ridge

unread,
Jun 10, 2008, 3:54:05 PM6/10/08
to Google App Engine
peterk wrote:
> Hehe, thanks, that's indeed another possible solution. Although its
> less transparent in that subclass handler functions would need to
> invoke the super class's base function ( i think?), which is an extra
> line of code in each handler function.

No, with Mahmoud's suggestion the subclass's handler methods have
names like "Get" and "Post". The framework calls the "get" and "post"
methods of base class which in turn calls the "Get" and "Post" methods
of the subclass.

> And subclasses which mightn't
> necessarily need to handle every request type would under this scheme
> still do a certain minimum amount of processing instead of being
> immediately discarded e.g. subclass A might only want to handle gets
> and posts, but put or delete requests will still be processed to a
> point by the base class.

I don't see this as being a problem. Your application is unlikely to
receive many requests that it's not supposed to handle. On the other
hand you probably want to handle this case in a better way than
throwing an exception about the sublcass is missing a Delete method.

An alternative using __metaclass__:

class common_request_handler_type(type):
methods = frozenset(["get", "post"])

handlers = {}
for method in methods:
handlers[method] = eval("lambda self, *args:"
"(self.common(),"
" self._impl_%s(*args))[1]" % method)

def __new__(cls, name, bases, attrs):
for attr in attrs.keys():
if attr in cls.methods:
attrs["_impl_" + attr] = attrs[attr]
attrs[attr] = cls.handlers[attr]
return type.__new__(cls, name, bases, attrs)

class my_common_request_handler(webapp.RequestHandler):
__metaclass__ = common_request_handler_type

def common(self):
pass


class my_request_handler(my_common_request_handler):
def get(self):
self.response.write("<p>Test response")

This makes writing request handlers with a common handler method more
simple, but its at the expense of much more complicated
implementation.

Ross Ridge

peterk

unread,
Jun 10, 2008, 4:50:00 PM6/10/08
to Google App Engine
> No, with Mahmoud's suggestion the subclass's handler methods have
> names like "Get" and "Post".  The framework calls the "get" and "post"
> methods of base class which in turn calls the "Get" and "Post" methods
> of the subclass.

I just tried this, and it doesn't seem to work without explicitly
calling the base class's handler function? That's what I meant by an
extra line of code in each of the subclass handler functions (e.g.
BaseClass.get() or BaseClass.post() etc.).. Maybe I'm missing
something, though.

I've also noticed that sending a response and stopping further code
from executing seems to be a general problem for me using overrides of
the RequestHandler class. In a subclass of the RequestHandler class,
if authorization isn't there or isn't correct, this function gets
called:

def forbidden(self):
self.response.headers['WWW-Authenticate'] = 'Basic realm=Cocom'
self.response.set_status(401)

But the rest of the handler code seems to continue to execute anyway,
appending supposedly protected data to the response, despite the 401
header. If a user clicks cancel on the HTTP Auth user/pass prompt,
that data will show anyway. I have tried using sys.exit() and raise
SystemExit here, but they don't seem to work (they throw errors).

If overriding the __call__ function in WSGIApplication, the forbidden
function can look like this:

def forbidden(self,start_response):
response = webapp.Response()
response.headers['WWW-Authenticate'] = 'Basic realm=Cocom'
response.set_status(401)
response.wsgi_write(start_response)

This seems to trigger an immediate response without any further data
being appended to the response by the remainder of the handler
function. Though I admit I'm left a little uneasy if that code is
executing at all (it probably shouldn't be if the user isn't
authorised!). The wsgi_write(start_response) seems to trigger the
response immediately, but it seems you can't use that in the
RequestHandler class..

A solution to this may be blindingly and embarrassingly obvious, I've
a feeling I'm missing something small :p Thanks for your help and
patience! :)

peterk

unread,
Jun 10, 2008, 4:37:07 PM6/10/08
to Google App Engine
> No, with Mahmoud's suggestion the subclass's handler methods have
> names like "Get" and "Post".  The framework calls the "get" and "post"
> methods of base class which in turn calls the "Get" and "Post" methods
> of the subclass.

I just tried this..unless I'm doing something wrong, though, the super
class function is not invoked unless you call it explicitly in the
overriding subclass function. This is what I mean by an extra line of
code in the subclass handler functions. Again, maybe I'm not fully
understanding python inheritance, but it doesn't seem to work for me
without a BaseClass.get() call or BaseClass.post() call in the sub-
class handlers.

Not that this is necessarily a HUGE deal, but I've actually run into
the same issue again of the script continuing to execute and appending
a body to the response, with the data that's supposed to be protected,
if the user just even hits cancel on the user/password prompt. To
perhaps be a little clearer, if the authorization header isn't there
or contains incorrect credentials, this function is called:

def forbidden(self):
self.response.headers['WWW-Authenticate'] = 'Basic realm=Cocom'
self.response.set_status(401)

When overriding the RequestHandler's initialize or handler functions
to call this first, this doesn't stop the rest of the script executing
and appending the supposedly protected data to the response's body. I
tried using sys.exit() and raise SystemExit, but neither seems to work
(they give me an error).

However, if I override the WSGIApplication __call__ function, then
that forbidden method can look like this:

def forbidden(self,start_response):
response = webapp.Response()
response.headers['WWW-Authenticate'] = 'Basic realm=Cocom'
response.set_status(401)
response.wsgi_write(start_response)

This seems to immediately respond to the request with a 401, and no
further data (although I admit I'm uneasy to know what exactly happens
after this code has executed..does the rest of the handler execute,
and if so, what happens to the data it generates?). And it is a bit
more hack-y to override this than to subclass the RequestHandler
class, for sure. Unfortunately, like I said earlier, the
wsti_write(start_response) bit, which seems to trigger the immediate
response, doesn't seem to work in overrides of RequestHandler
functions.

I've a feeling there must be a very simple answer to all this that I'm
missing :) Thanks so much for your patience and help..

Ross Ridge

unread,
Jun 10, 2008, 7:24:03 PM6/10/08
to Google App Engine
Rpss Ridge write:
> No, with Mahmoud's suggestion the subclass's handler methods have
> names like "Get" and "Post". �The framework calls the "get" and "post"
> methods of base class which in turn calls the "Get" and "Post" methods
> of the subclass.

peterk wrote:
> I just tried this, and it doesn't seem to work without explicitly
> calling the base class's handler function? That's what I meant by an
> extra line of code in each of the subclass handler functions (e.g.
> BaseClass.get() or BaseClass.post() etc.).. Maybe I'm missing
> something, though.

You've probably missed the fact that you need to give your subclass
handler functions different names then they would normally would
have. Like "Get" instead of "get".

> I've also noticed that sending a response and stopping further code
> from executing seems to be a general problem for me using overrides of
> the RequestHandler class. In a subclass of the RequestHandler class,
> if authorization isn't there or isn't correct, this function gets
> called:

All you have to do is not call the "Get" function in your subclass:

class BaseClass(webapp.RequestHandler):
def get(self):
if is_authorized():
return self.Get()
self.forbidden()

class RequestClass(BaseClass):
def Get(self): # NOTE THE INITIAL CAPITAL LETTER
self.response.write("<p>Normal response")

Ross Ridge

Dado

unread,
Jun 10, 2008, 8:37:39 PM6/10/08
to Google App Engine
Please start this issue: <http://code.google.com/p/googleappengine/
issues/detail?id=468>

peterk

unread,
Jun 11, 2008, 12:14:41 PM6/11/08
to Google App Engine
Ross - thanks very much for your posts, this would be a very nice
solution, but I've run into one problem:

My baseclass looks a little like this:

class BaseClass(webapp.RequestHandler):
def get(self):
if is_authorized():
return self.Get()
self.forbidden()

But some get handlers in my subclasses will have more parameters
passed to them (i.e. from the URL). I have one Get handler now, for
example:

def Get(self, id):

(which was previously get(self, id))

But the base Get is:

def Get(self):

So it throws an error because of the extra id parameter. Will I have
to write a baseclass handler for every possible set of parameters that
sub class handlers might need, or is there an easier way to handle
this?

Thanks again very much for your help, it's GREATLY appreciated :)

Ross Ridge

unread,
Jun 11, 2008, 4:11:03 PM6/11/08
to Google App Engine


peterk wrote:
> My baseclass looks a little like this:
>
> class BaseClass(webapp.RequestHandler):
> def get(self):
> if is_authorized():
> return self.Get()
> self.forbidden()
>
> But some get handlers in my subclasses will have more parameters
> passed to them (i.e. from the URL). I have one Get handler now, for
> example:
>
> def Get(self, id):
>
> (which was previously get(self, id))

That's pretty easy to solve:

def get(self, *args):
if is_authorized():
return self.Get(*args)
self.forbidden()

Ross Ridge

peterk

unread,
Jun 11, 2008, 5:59:02 PM6/11/08
to Google App Engine
Perfect! Thanks so much :) You're a saint!

This is pretty much the ideal solution. I can build 'pre-handler'
functionality into the baseclass transparently, or call optional ones
specifically in subclass handlers if needs be. Best of both worlds, I
think.
Reply all
Reply to author
Forward
0 new messages