OK, this time it works, and for bonus points it correctly returns 200
OK for the OPTIONS method:

>>> app._gen_request('DELETE', '/releases', status=405)
<Response 405 Method Not Allowed '405 Method Not Allow'>
>>> app._gen_request('DELETE', '/releases', status=405).headers[1]
('Allow', 'GET, POST')
>>> app._gen_request('OPTIONS', '/releases', status=200)
<Response 200 OK '200 OK\n\n\n\n   '>
>>> app._gen_request('OPTIONS', '/releases', status=200).headers[1]
('Allow', 'GET, POST')

Doing this in Routes turned out to be harder than expected, and in any
case it would have required coordinated changes across Pylons &/or
apps too.  Instead I overrode dispatch() in my PylonsApp (subclassed
from the default pylons.wsgiapp.PylonsApp) in my app's config/
middleware.py as shown in the diffs below.

My routes are always explicit about methods (quite painlessly, as
recently described), I don't need pylons.decorators.rest now, and the
annoying duplication is removed.

Enjoy,
Mike

-from pylons.wsgiapp import PylonsApp
+from pylons.wsgiapp import PylonsApp as _PylonsApp
+from webob.exc import HTTPMethodNotAllowed, HTTPNotFound, HTTPOk

then:

methods = ['GET', 'PUT', 'POST', 'DELETE']

class PylonsApp(_PylonsApp):
    def dispatch(self, controller, environ, start_response):
        if not controller:
            try:
                old_method = environ['REQUEST_METHOD']
                allowed_methods=[]
                mapper = config['routes.map']
                for method in methods:
                    environ['REQUEST_METHOD'] = method
                    if mapper.match(environ['PATH_INFO']):
                        allowed_methods.append(method)
                if allowed_methods:
                    exc = HTTPOk() if old_method =='OPTIONS' else
HTTPMethodNotAllowed()
                    exc.allow = allowed_methods
                    return exc(environ, start_response)
            finally:
                environ['REQUEST_METHOD'] = old_method

            return HTTPNotFound()(environ, start_response)
        else:
            return _PylonsApp.dispatch(self, controller, environ,
start_response)


On Dec 15, 8:11 pm, "Mike Burrows (asplake)" <[email protected]>
wrote:
> Hi Shailesh,
>
> Yes I'm aware of (and use) the rest decorators.  I kinda like though
> the simplification of having all routing in one place, and (although
> this is perhaps a more personal thing) having a good source of meta
> data describing the application - it seems a pity to me to hide all
> this information inside decorators that provide no protocol for
> extracting it again.
>
> Your solution is succinct and as nice as any I've seen but it's still
> not completely DRY - you need to remember to maintain the dispatcher
> and the allowed list together.  An improved decorator could fix that
> for you though I guess.  Picky I know, but there's competition for
> frameworks out there and these things frustrate me!
>
> Regards,
> Mike
>
> On Dec 15, 8:44 pm, Shailesh Kochhar <[email protected]> wrote:
>
> > Mike,
>
> > I do something like this in my controllers:
>
> > import pylons.decorators.rest as rest
> > from app.lib.errors import MethodNotAllowedError
>
> > class QuestionController(BaseController):
>
> >     �[email protected]_on(GET='get_questions', POST='add_questions')
> >      def questions(self, id):
> >          raise MethodNotAllowedError(method=request.method, allowed=["GET", 
> > "POST"])
>
> > MethodNotAllowedError is an exception class I wrote which serializes to a 
> > 405 error.
>
> >    - Shailesh
>
> > Mike Burrows (asplake) wrote:
> > > Apologies - I was too hasty.  I was fooled into thinking that 405's
> > > were being generated but all I was seeing was the logging of
> > > exceptions.  A full solution needs a change somewhere in the
> > > middleware stack I guess.   We can pretend I never posted but please
> > > reply if you would like to me to pursue this further!
>
> > > On Dec 15, 9:19 am, "Mike Burrows (asplake)" <[email protected]>
> > > wrote:
> > >> I should add that you use this only on the last route for any given
> > >> path, or you'll never reach the later ones!
>
> > >> Mike
>
> > >> On Dec 15, 9:13 am, "Mike Burrows (asplake)" <[email protected]>
> > >> wrote:
>
> > >>> This is a followup to an issue raised off topic in the thread "Generic
> > >>> routes for API 
> > >>> functions"http://groups.google.com/group/pylons-discuss/browse_thread/thread/34...
> > >>> .
> > >>> I said there that I didn't like that a 404 is raised if routes match
> > >>> on path but not on HTTP method.  I have since found a solution though,
> > >>> and it's simple enough:
> > >>>     from pylons.controllers.util import abort
> > >>>     def method_condition(method):
> > >>>         # A condition function capable of generating status codes
> > >>>         def check_method(environ, result):
> > >>>             if environ and 'REQUEST_METHOD' in environ and \
> > >>>                 environ['REQUEST_METHOD'] not in method:
> > >>>                 abort(405)
> > >>>             else:
> > >>>                 return True
> > >>>         return check_method
> > >>> Use with
> > >>>     conditions={'function': method_condition(method)}
> > >>> on your route.  I have a helper that generates either this form or the
> > >>> simpler
> > >>>     conditions={'method': method}
> > >>> form depending on the presence of a status code, but I didn't want to
> > >>> obscure the solution unecessarily.
> > >>> Enjoy,
> > >>> Mike
> > >>> [email protected]http://positiveincline.comhttp://twitter.com/asplake
>
> > > --
>
> > > You received this message because you are subscribed to the Google Groups 
> > > "pylons-discuss" 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 
> > > athttp://groups.google.com/group/pylons-discuss?hl=en.

--

You received this message because you are subscribed to the Google Groups 
"pylons-discuss" 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/pylons-discuss?hl=en.


Reply via email to