From: Dan M. <da...@co...> - 2006-09-17 19:07:52
|
I've added java servlet-style filters to Webware, and would like to contribute the code to the project, if people are interested. I've attached files and patches -- it's a relatively small amount of code. A few patches to Application.py and Transaction.py, and then four new files. (Note: I *think* I got all the tabs right, but I'm not sure ;-) I've been working with filters for a while (I wrote the feature against 0.8.1, and just found time to port the patches to 0.9.x), and have found them to be enormously useful. Here's the basic idea: - In Application.config, the user can specify a sequence of (regex, Filter) pairs, like so: FilterMappings = [ (r'/', 'filters.Authorizer'), (r'/admin/', 'filters.admin'), (r'/customers/', 'filters.customers'), (r'/users/', 'filters.users') ] Each Filter will be a subclass of WebKit.Filter and must define a filter(trans, next) method. - When the Application receives a new request, it constructs a 'chain' of Filters which match the URL E.g. in the example above, for a request to /users/3/view, that chain would be: [ filters.Authorizer(), filters.users() ] - The Application then calls the filter(trans, next) method of the first Filter in the chain After examining and possibly modifying the transaction, each filter can pass control on to the succeeding one by calling next(trans). Or, if it can terminate the chain by just returning. - If all the filters execute and pass control to next(), control returns to the Application, which will lookup and execute a servlet as usual Some uses: - Path-based Authorization An Authorizer filter can look in the session for credentials, and, if none are found, can redirect to a login page (after storing the originally request URL in the session, possibly) - Move parameters from the URL to the Request (REST-style) Given a request of form: /users/3/<serv> a filter can modify the URL to be /users/<serv>, and store user_id=3 in the request. - Logging - Compression Many others. Basically, filters provide the user a clean, simple way to construct their own request-handling pipeline. If people are interested, I can write up some documentation. -Dan Milstein |
From: Christoph Z. <ci...@on...> - 2006-09-17 21:07:33
|
Dan Milstein wrote: > I've added java servlet-style filters to Webware, and would like to > contribute the code to the project, if people are interested. > ... > If people are interested, I can write up some documentation. That's surely interesting, thanks. I'll have a look at it and I'd also like to hear feedback from others; maybe we can include it with 0.9.3. For 0.9.2 it's unfortunately too late, I don't want to defer it again. Instead of only documentation, it would be nice to have some usage examples too, maybe a tutorial on building a small application using these and other Webware features. -- Chris |
From: Dan M. <da...@co...> - 2006-09-18 16:57:55
Attachments:
FilterChain.py
UsingFilters.html
|
Chris, Thanks for the quick response -- I didn't expect to go in 0.9.2 -- no worries about that. Two things: 1) I *did* screw up the tabs/spaces in one of the files - FilterChain.py. I've attached a fixed version. Sorry. I've got Emacs set up to use spaces by default, and going back and forth is, um, tricky. Here's hoping (but not expecting) that this is the last such mistake. 2) Attached is the start of a tutorial/how-to style doc on using filters I'm attaching it in rough form to a) give a teaser for folks on this list who want to try filters out, and b) get feedback on whether or not this is a useful kind of doc. I'll keep working on this one, but if people are feeling like it's too simple, or would work better as part of a general Webware tutorial, let me know. -Dan |
From: John D. <jdi...@te...> - 2006-09-18 18:25:17
|
I like the idea of these filters, and I can definitely see how they could be useful. Having only looked at your examples and the doc you provided, though, I do have a couple of questions/suggestions. One, according to the documentation, you set up filters in Application.config. Would it be possible to use them in a per-servlet way? In other words, instead of setting the filters per instance in the config file, could I define a filter chain in the __init__ or awake() of an application's base class (some SitePage)? Two, although I'm sure I could figure it out by actually using the filters, you documentation does not quite tie all of the pieces together for me. For example, the first thing I though of when reading "The Code" section is "Where does the import go?" Where do I import the AuthorizerFilter that you set up in the config? I'd like to see a complete (but simple) example. I know that the docs are only preliminary, but that's my $.02USD. All-in-all, though, good job. It looks like a really handy tool to have. --John > > > 2) Attached is the start of a tutorial/how-to style doc on using filters > > I'm attaching it in rough form to a) give a teaser for folks on this > list who want to try filters out, and b) get feedback on whether or > not this is a useful kind of doc. I'll keep working on this one, but > if people are feeling like it's too simple, or would work better as > part of a general Webware tutorial, let me know. > > -Dan |
From: Dan M. <da...@co...> - 2006-09-18 18:43:27
|
Thanks much for the response. Questions: > One, according to the documentation, you set up filters in > Application.config. Would it be possible to use them in a per-servlet > way? In other words, instead of setting the filters per instance in > the > config file, could I define a filter chain in the __init__ or awake > () of > an application's base class (some SitePage)? I'm not sure if I fully understand this (and I'd like to). What would it mean for them to be per-servlet? Would that mean that the chain could depend on which servlet was actually called, rather than on which filters matched the URL? One of the strengths of the way it works now is it's actually important/useful to define behavior on the pattern of the URL. That's sort of the big win. Or am I misunderstanding? Could you talk out how you'd imagine using it in a per-servlet manner? > Two, although I'm sure I could figure it out by actually using the > filters, you documentation does not quite tie all of the pieces > together > for me. For example, the first thing I though of when reading "The > Code" > section is "Where does the import go?" Where do I import the > AuthorizerFilter that you set up in the config? I'd like to see a > complete (but simple) example. I know that the docs are only > preliminary, but that's my $.02USD. Very helpful. Thanks. I'll take a pass at writing a small, complete application. In answer to your question: you don't ever have to import AuthorizerFilter -- Webware does so for you (so to speak) when it builds a chain which needs it. Your servlet code doesn't import or interact with the filter code directly. A filter can communicate with/influence servlet code, but only via the web data: a filter can modify the data in the request, or change the path, or store things in the session, or, if it wanted to do something really devious, could replace response/request objects in the transaction altogether. You could look at it as -- the filter can help set up the environment in which the servlet then executes. I'll try to make this all clearer in the docs. Thanks again -- very useful feedback. -Dan |
From: John D. <jdi...@te...> - 2006-09-18 19:36:13
|
In my initial excitement of the idea, I got a little ahead of myself. I see where you are coming from now, and why you define the filters in the config file. The big problem with putting a filter in a sevlet is that that same servlet might not have been accessed based on it's own filter. But the filter wouldn't have been called if you never loaded the servlet. Catch-22. However, I do think that there is value in being able to define a filter per-servlet. By this I mean that each sevlet could define behavior on it's own based on the path so far, with filters defined in Application.config serving as a default. Also, the filters could be processed down through the inheritance hierarchy. So the SitePage's filters would fire, then the MiddlePage's, and finally, assuming the filters allowed the request to get this far, the ChildPage's filter would be processed. But if I want that, maybe I should just use CherryPy ;-). They have (IMHO) a nice URL parsing system that seems very similar to this (at least functionally). I still like the idea of these filters in Webware (even if it's not "per-servlet"). --John > I'm not sure if I fully understand this (and I'd like to). What > would it mean for them to be per-servlet? Would that mean that the > chain could depend on which servlet was actually called, rather than > on which filters matched the URL? > > One of the strengths of the way it works now is it's actually > important/useful to define behavior on the pattern of the URL. > That's sort of the big win. > > Or am I misunderstanding? Could you talk out how you'd imagine using > it in a per-servlet manner? > |