rest - CherryPy read PATCH body -
i'm developing api in cherrypy. i'd handle patch requests. but, following error in patch() method
line 143, in patch data = cherrypy.request.json
i'm wandering, how can body of patch request
main.py
import cherrypy controllers.usercontroller import usercontroller def cors(): """allow web apps not on same server 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, patch' ) if __name__ == '__main__': """starts cherrypy server , listens 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 # defining here because want map http verb # same method on controller class. _api_user_conf # used on each route want restful _api_conf = { '/': { 'request.dispatch': cherrypy.dispatch.methoddispatcher(), } } # _api_user_conf better explained # default dispatcher in cherrypy stores http method name @ # :attr:`cherrypy.request.method<cherrypy._cprequest.request.method>`. # because http defines these invocation methods, direct # way implement rest using cherrypy utilize # :class:`methoddispatcher<cherrypy._cpdispatch.methoddispatcher>` # instead of default dispatcher. enable # method dispatcher, add # following configuration root uri ("/"):: # '/': { # 'request.dispatch': cherrypy.dispatch.methoddispatcher(), # } # now, rest methods map directly same method names on # resources. is, method on cherrypy class implements # http on resource represented 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()
the controller resides in controllers/usercontroller.py. there init.py file located in controllers folder
controllers/usercontroller.py
import cherrypy # services.userserviceprovider import userserviceprovider 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 class methods @ once exposed = true def __init__(self): # create instance of service provider # self.userservice = userserviceprovider() pass ''' code allows our routes http://example.com/api/users/uuid , uuid made available routes user input http://example.com/api/users?uuid=uuid ''' def _cp_dispatch(self, vpath: list[str]): # since our routes contain guid, we'll have 1 # path. if have more, ignore 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 users or particular user if id passed in. using cherrypy tools decorator can automagically output json without having using json.dumps() """ # our uri should /api/users/{guid}, using _cp_dispatch, # changes uri /api/users?uuid={guid} if 'uuid' not in kwargs: # if no guid passed in uri, should users' info # database # results = self.userservice.getallusers() results = { 'status' : 'getting users' } else: # results = self.userservice.getuser(kwargs['uuid']) results = { 'status' : 'searching user ' + kwargs['uuid'] } return results @cherrypy.tools.json_in() @cherrypy.tools.json_out() def post(self): """creates new user """ input = cherrypy.request.json inputparams = {} # convert keys unicode regular strings 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 err: result = {'error' : 'failed create user. ' + err.__str__()} return result @cherrypy.tools.json_out() def delete(self, **kwargs: dict[str, str]): # convert keys unicode regular strings uuid = '' if 'uuid' not in kwargs: result = { 'success' : false, 'message' : 'you must specfy 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 id: ' + uuid } except exception err: result = {'error' : 'could not delete. ' + err.__str__()} return result @cherrypy.tools.json_in() @cherrypy.tools.json_out() def put(self): # request body data = cherrypy.request.json print('body:\n' + str(data)) # result = self.userservice.updateuser(data) result = { 'status' : 'updating user' } return result @cherrypy.tools.json_in() @cherrypy.tools.json_out() def patch(self, **kwargs: dict[str, str]): # _cp_dispatch() method if 'uuid' not in kwargs: result = { 'success' : false, 'message' : 'you must specfy user.' } return result else: print('found uuid: ' + kwargs['uuid']) # request body data = cherrypy.request.json # result = self.userservice.updateuser(data, kwargs['uuid']) result = { 'status' : 'patching user ({})'.format(kwargs['uuid']) } return result def options(self): return 'allow: delete, get, head, options, patch, post, put' def head(self): return ''
all other requests seem work, but, one. i'm thinking issue may call _cp_dispatch()
method, but, if is, how handle uri path parameter?
Comments
Post a Comment