Issue #13 open

Why MethodHandler only support GET, POST and HEAD method?

Luo Yuhao
created an issue

OPTIONS, PUT, DELETE, TRACE, CONNECT?

Comments (4)

  1. Andriy Kornatskyy repo owner

    The HTTP method reflects a verb (action) that applies to current request, however the limited number of HTTP verbs does not cover all use cases that applies to HTTP API. So that usually leads to mixes of HTTP verbs and actions that better reflect use case, e.g. publish, activate, block, send, subscribe, etc. Thus it is recommended to limit HTTP API design to commonly used methods (GET/POST) only. Anyway CRUD HTTP API doesn’t look any better with HTTP verbs vs URI, thus consistency in API design is preferred.

  2. Andriy Kornatskyy repo owner
    • changed status to open

    There client side libraries that rely on ability to communicate with RESTful server side API, thus methods like PUT, DELETE become important. Rarely used: PATCH, OPTIONS. Unlikely to be used: CONNECT, TRACE.

    There is options attribute defined in MethodHandler (that comes from request.options). This attribute conflicts with HTTP verb.

    Possible solutions:

    1. Refactor MethodHandler and BaseHandler to rename self.options to be self.o

    2. Use method self.http_options to handle OPTIONS verb.

  3. Andriy Kornatskyy repo owner

    It is recommended to use package base handler, e.g. MembershipBaseHandler (see an example here). This way you can extend/override the existing functionality provided by BaseHandler (or MethodHandler) a way you like, e.g. for API web handler you might have something like this:

    class APIBaseHandler(BaseHandler):
    
        def __call__(self):
            method = self.request.method
            if method == 'GET':
                response = self.get()
            elif method == 'POST':
                response = self.post()
            elif method == 'DELETE':
                response = self.delete()
            elif method == 'OPTIONS':
                response = self.http_options()
            else:
                response = method_not_allowed()
            if self.cookies:
                response.cookies.extend(self.cookies)
            return response
    
        def get(self):
            return method_not_allowed()
    
        def post(self):
            return method_not_allowed()
    
        def delete(self):
            return method_not_allowed()
    
        def http_options(self):
            return method_not_allowed()
    

    If you do not use cookies in API, the __call__ method can be simplified down to this:

    class APIBaseHandler(BaseHandler):
    
        def __call__(self):
            method = self.request.method
            if method == 'GET':
                return self.get()
            elif method == 'POST':
                return self.post()
            elif method == 'DELETE':
                return self.delete()
            elif method == 'OPTIONS':
                return self.http_options()
            return method_not_allowed()
    
  4. Log in to comment