Re: Re: Simple RESTful API - make a patch

"Joseph S. Tate" <[email protected]> Tue, 15 Nov 2016 22:56:19 +0000
Newsgroups gmane.comp.python.cherrypy
Message-ID <CA+WDQbGNMH_2By9+hZB-NUNvV__Wa3uNEPXsSsrNPVkoONbyjw@mail.gmail.com>
Ahh. I see in the ticket that you're already working it. Thanks!

On Tue, Nov 15, 2016 at 5:55 PM Joseph S. Tate <[email protected]>
wrote:

> you're almost there. Go to https://github.com/cherrypy/cherrypy/ and
> click the "New Pull Request" button. Then click the "compare across forks"
> link. Then you can pick your repo and branch as the "head fork".
>
> On Tue, Nov 15, 2016 at 8:15 AM Kearney Taaffe <[email protected]>
> wrote:
>
> Man, I feel stupid. I work with Git at work, but, all we do is just branch
> and merge. I forked the project (since I couldn't seem to branch) and made
> a branch with the ticket number.
>
> https://github.com/gitKearney/cherrypy/tree/feature/1516_fix_get_PATCH_body
>
> I don't know if you can check that out and merge it. I created a tests
> folder, with a simple server and controller, and a caller file that uses
> "requests" to send a PATCH request.
>
>
>
>
> Kearney J. Taaffe
> (817) 239-2783
>
> On Tue, Nov 15, 2016 at 12:43 AM, Joseph S. Tate <[email protected]>
> wrote:
>
> Ideally you'd submit a pull request from your branch with a test that
> proves that the fix works. Perhaps by copying and modifying a test for PUT
> or POST. Then I'll merge it in.
>
> Joseph
>
> On Mon, Nov 14, 2016 at 11:24 AM Kearney Taaffe <[email protected]>
> wrote:
>
> @Josheph, sorry, my response wasn't very explicit. Changing the line 315
> in cherrypy._cprequest.py from
>
> methods_with_bodies = ('POST', 'PUT')
>
>
> to
>
> methods_with_bodies = ('POST', 'PUT', 'PATCH')
>
>
> worked.
>
> I posted the new PATCH() method to show that the body and route param were
> printed to the log
>
>
>
> On Thursday, November 10, 2016 at 10:10:32 AM UTC-6, Kearney Taaffe wrote:
>
> I'm making an API in CherryPy. I must admit, it's super easy, and I'd like
> to turn this example into something that the CherryPy community puts on
> it's website as a "how to API"
>
> The problem I'm having is how to handle an HTTP PATCH request. The
> following code fails with the error for HTTP PATCH requests
>
> AttributeError: 'Request' object has no attribute 'json'
>
>
> Here's my main.py
> import cherrypy
>
>
> from controllers.userController import UserController
>
>
>
>
> def CORS():
>     """Allow web apps not on the same server to use our API
>     """
>     cherrypy.response.headers["Access-Control-Allow-Origin"] = "*"
>     cherrypy.response.headers["Access-Control-Allow-Headers"] = (
>         "content-type, Authorization, X-Requested-With"
>     )
>
>     cherrypy.response.headers["Access-Control-Allow-Methods"] = (
>         'GET, POST, PUT, DELETE, OPTIONS'
>     )
>
> if __name__ == '__main__':
>     """Starts a cherryPy server and listens for requests
>     """
>
>     userController = UserController()
>
>     cherrypy.tools.CORS = cherrypy.Tool('before_handler', CORS)
>
>     cherrypy.config.update({
>         'server.socket_host': '0.0.0.0',
>         'server.socket_port': 8080,
>         'tools.CORS.on': True,
>     })
>
>
>     # API method dispatcher
>     # we are defining this here because we want to map the HTTP verb to
>     # the same method on the controller class. This _api_user_conf will
>     # be used on each route we want to be RESTful
>     _api_conf = {
>         '/': {
>             'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
>         }
>     }
>
>
>     # _api_user_conf better explained
>     # The default dispatcher in CherryPy stores the HTTP method name at
>     # :attr:`cherrypy.request.method<cherrypy._cprequest.Request.method>`.
>
>
>     # Because HTTP defines these invocation methods, the most direct
>     # way to implement REST using CherryPy is to utilize the
>     # :class:`MethodDispatcher<cherrypy._cpdispatch.MethodDispatcher>`
>     # instead of the default dispatcher. To enable
>     # the method dispatcher, add the
>     # following to your configuration for the root URI ("/")::
>
>
>     #     '/': {
>     #         'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
>     #     }
>
>
>     # Now, the REST methods will map directly to the same method names on
>     # your resources. That is, a GET method on a CherryPy class implements
>     # the HTTP GET on the resource represented by that class.
>
>
>     # http://cherrypy.readthedocs.org/en/3.2.6/_sources/progguide/REST.txt
>
>
>     cherrypy.tree.mount(userController, '/api/users', _api_conf)
>
>
>
>     cherrypy.engine.start()
>     cherrypy.engine.block()
>
>
>
> Here's the user controller (controllers/userController.py) (*NOTE: be
> sure the file __init__.py is in the controllers directory and is blank)*
>
> import cherrypy
>
>
> # from services.userServiceProvider import UserServiceProvider
>
>
> from typing import Dict, List
>
>
> '''
> NOTES
>  + @cherrypy.tools.json_out() - automatically outputs response in JSON
>  + @cherrypy.tools.json_in()  - automatically parses JSON body
> '''
> class UserController():
>
>
>     # expose all the class methods at once
>     exposed = True
>
>     def __init__(self):
>         # create an instance of the service provider
>         # self.userService = UserServiceProvider()
>         pass
>
>
>     '''
>     This code allows for our routes to look like
> http://example.com/api/users/uuid
>     and the uuid will be made available to the routes like the user input
>     http://example.com/api/users?uuid=uuid
>     '''
>     def _cp_dispatch(self, vpath: List[str]):
>
>         # since our routes will only contain the GUID, we'll only have 1
>         # path. If we have more, just ignore it
>         if len(vpath) == 1:
>             cherrypy.request.params['uuid'] = vpath.pop()
>
>         return self
>
>
>     @cherrypy.tools.json_out()
>     def GET(self, **kwargs: Dict[str, str]) -> str:
>         """
>         Either gets all the users or a particular user if ID was passed in.
>         By using the cherrypy tools decorator we can automagically output
> JSON
>         without having to using json.dumps()
>         """
>
>
>         # our URI should be /api/users/{GUID}, by using _cp_dispatch,
> this
>         # changes the URI to look like /api/users?uuid={GUID}
>
>         if 'uuid' not in kwargs:
>             # if no GUID was passed in the URI, we should get all users'
> info
>             # from the database
>             # results =  self.userService.getAllUsers()
>             results = {
>                 'status' : 'getting all users'
>             }
>         else:
>             # results = self.userService.getUser(kwargs['uuid'])
>             results = {
>                 'status' : 'searching for user ' + kwargs['uuid']
>             }
>
>
>         return results
>
>     @cherrypy.tools.json_in()
>     @cherrypy.tools.json_out()
>     def POST(self):
>         """Creates a new user
>         """
>         input = cherrypy.request.json
>         inputParams = {}
>
>         # convert the keys from unicode to regular strings
>         for key, value in input.items():
>            inputParams[key] = str(value)
>
>         try:
>             # result = self.userService.addUser(inputParams)
>             result = {
>                 'status' : 'inserting new record'
>             }
>
>
>             if len(inputParams) == 0:
>                 raise Exception('no body')
>         except Exception as err:
>             result = {'error' : 'Failed to create user. ' + err.__str__()}
>
>
>         return result
>
>     @cherrypy.tools.json_out()
>     def DELETE(self, **kwargs: Dict[str, str]):
>         # convert the keys from unicode to regular strings
>         uuid = ''
>         if 'uuid' not in kwargs:
>             result = {
>                 'success' : False,
>                 'message' : 'You must specfy a user.'
>             }
>
>
>             return result
>
>
>         uuid = kwargs['uuid']
>
>
>         try:
>             if len(uuid) == 0:
>                 raise Exception('must pass in user ID')
>
>             # result = self.userService.deleteUser(inputParams)
>             result = {
>                 'status' : 'deleting user with ID: ' + uuid
>             }
>         except Exception as err:
>             result = {'error' : 'could not delete. ' + err.__str__()}
>
>
>         return result
>
>
>     @cherrypy
>
>

-- 
You received this message because you are subscribed to the Google Groups "cherrypy-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cherrypy-users+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/[email protected]
To post to this group, send email to cherrypy-users-/JYPxA39Uh5TLH3MbocFF+G/[email protected]
Visit this group at https://groups.google.com/group/cherrypy-users.
For more options, visit https://groups.google.com/d/optout.