AttributeError: 'Request' object has no attribute 'json'
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()
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.tools.json_in()
@cherrypy.tools.json_out()
def PUT(self):
# get the 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]):
# the _cp_dispatch() method
if 'uuid' not in kwargs:
result = {
'success' : False,
'message' : 'You must specfy a user.'
}
return result
else:
print('found uuid: ' + kwargs['uuid'])
# get the 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, POST, PUT'
def HEAD(self):
return ''
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'
cherrypy.response.headers["Access-Control-Allow-Methods"] = (
'GET, POST, PUT, DELETE, OPTIONS'
)
def OPTIONS(self):
return 'Allow: DELETE, GET, HEAD,
OPTIONS, POST, PUT'
-- Tim Roberts, ti...@probo.com Providenza & Boekelheide, Inc.
line 143, in PATCHdata = cherrypy.request.json
PATCH /api/users/123-123-123 HTTP/1.1
Content-Type: application/json; charset=utf-8
Host: localhost:8080
Connection: close
User-Agent: Paw/3.0.12 (Macintosh; OS X/10.12.1) GCDHTTPRequest
Content-Length: 21
{"last_name":"Jones"}
@cherrypy.tools.json_in()
@cherrypy.tools.json_out()
def PATCH(self, **kwargs: Dict[str, str]):
# the _cp_dispatch() method
if 'uuid' not in kwargs:
result = {
'success' : False,
'message' : 'You must specfy a user.'
}
return result
else:
print('found uuid: ' + kwargs['uuid'])
# get the request body
data = cherrypy.request.
json
print('HTTP BODY: ' + str(data))
# result = self.userService.updateUser(data, kwargs['uuid'])
result = {
'status' : 'patching user ({})'.format(kwargs['uuid'])
}
return result
methods_with_bodies = ('POST', 'PUT')
methods_with_bodies = ('POST', 'PUT', 'PATCH')
--
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-user...@googlegroups.com.
To post to this group, send email to cherryp...@googlegroups.com.
Visit this group at https://groups.google.com/group/cherrypy-users.
For more options, visit https://groups.google.com/d/optout.
To unsubscribe from this group and stop receiving emails from it, send an email to cherrypy-users+unsubscribe@googlegroups.com.
To post to this group, send email to cherrypy-users@googlegroups.com.
Visit this group at https://groups.google.com/group/cherrypy-users.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to a topic in the Google Groups "cherrypy-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/cherrypy-users/-HvSQC0Lmas/unsubscribe.
To unsubscribe from this group and all its topics, send an email to cherrypy-users+unsubscribe@googlegroups.com.
To post to this group, send email to cherrypy-users@googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to cherrypy-user...@googlegroups.com.
To post to this group, send email to cherryp...@googlegroups.com.
Visit this group at https://groups.google.com/group/cherrypy-users.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to a topic in the Google Groups "cherrypy-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/cherrypy-users/-HvSQC0Lmas/unsubscribe.
To unsubscribe from this group and all its topics, send an email to cherrypy-user...@googlegroups.com.
To post to this group, send email to cherryp...@googlegroups.com.
Visit this group at https://groups.google.com/group/cherrypy-users.
For more options, visit https://groups.google.com/d/optout.
--
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-user...@googlegroups.com.
To post to this group, send email to cherryp...@googlegroups.com.
Man, I feel stupid. I work with Git at work, but, all we do is just branch and merge.
appconf = {
'/method': {
'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
'request.methods_with_bodies': ('POST', 'PUT', 'PATCH')
},
}
cherrypy.tree.mount(root, config=appconf)