在CherryPy中创建RESTful Web API的最佳方法是什么?我一直在寻找几天,似乎没什么好看的。对于Django来说,似乎有很多工具可以做到这一点,但不适用于CherryPy,或者我不了解它们。
稍后编辑:我应该如何使用Cherrypy将/ getOrders?account = X& type = Y等请求转换为/ orders / account / type之类的内容?
答案 0 :(得分:11)
我不知道这是否是“最佳”方式,但我的方法就是这样:
import cherrypy
class RESTResource(object):
"""
Base class for providing a RESTful interface to a resource.
To use this class, simply derive a class from it and implement the methods
you want to support. The list of possible methods are:
handle_GET
handle_PUT
handle_POST
handle_DELETE
"""
@cherrypy.expose
def default(self, *vpath, **params):
method = getattr(self, "handle_" + cherrypy.request.method, None)
if not method:
methods = [x.replace("handle_", "")
for x in dir(self) if x.startswith("handle_")]
cherrypy.response.headers["Allow"] = ",".join(methods)
raise cherrypy.HTTPError(405, "Method not implemented.")
return method(*vpath, **params);
class FooResource(RESTResource):
def handle_GET(self, *vpath, **params):
retval = "Path Elements:<br/>" + '<br/>'.join(vpath)
query = ['%s=>%s' % (k,v) for k,v in params.items()]
retval += "<br/>Query String Elements:<br/>" + \
'<br/>'.join(query)
return retval
class Root(object):
foo = FooResource()
@cherrypy.expose
def index(self):
return "REST example."
cherrypy.quickstart(Root())
您只需从RESTResource
类派生,并使用前缀为handle_
的同名方法处理您想要的任何RESTful动词(GET,PUT,POST,DELETE)。如果您不处理特定动词(例如POST),基类将为您引发405 Method Not Implemented
错误。
路径项在vpaths
中传递,任何查询字符串都在params
中传入。使用上面的示例代码,如果您要求/foo/bar?woo=hoo
,vpath[0]
将是bar
,params
将是{'woo': 'hoo'}
。
答案 1 :(得分:7)
因为HTTP定义了这些调用方法,所以使用CherryPy实现REST的最直接方法是使用MethodDispatcher而不是默认调度程序。
在CherryPy文档中可以找到更多内容: http://cherrypy.readthedocs.io/en/latest/tutorials.html#tutorial-7-give-us-a-rest
以下是有关如何使用CherryPy Tools发送和接收JSON的详细说明: http://tools.cherrypy.org/wiki/JSON
答案 2 :(得分:2)
所以你想使用Cherrypy将/ getOrders?account = X&amp; type = Y转换成类似/ orders / account / type的东西。
我会尝试@Tomasz Blachowicz提到的http://cherrypy.readthedocs.org/en/latest/tutorial/REST.html中使用的方法,并进行一些修改。
请记住,您可以使用
处理/ order / account / type之类的内容@cherrypy.expose
def order(account=None, type=None):
print account, type
class Root(object):
pass
root = Root()
root.orders = orders
cherrypy.quickstart(root, '/')
因此,如果您采用http://cherrypy.readthedocs.org/en/latest/tutorial/REST.html中给出的示例,则可以对其进行修改以处理该类型的URL。
class Orders(object):
exposed = True
def __init__(self):
pass
def GET(self, account=None, type=None):
#return the order list for this account type
return getOrders(account, type)
def PUT(self, account=None, type=None, orders=None):
#Set the orders associated with account or something
setOrders(account, type, orders)
class Root(object):
pass
root = Root()
root.orders = Orders()
conf = {
'global': {
'server.socket_host': '0.0.0.0',
'server.socket_port': 8000,
},
'/': {
'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
},
}
cherrypy.quickstart(root, '/', conf)
为什么你想要使用我不知道的put方法设置订单,但它确实提供了另一个如何做PUT方法的例子。您所要做的就是用PUT替换请求使用的方法,它将使用Orders的PUT()方法并在Orders上使用常规GET,它将使用GET()方法。由于未定义POST()方法,因此POST不能与此示例一起使用。如果您尝试POST或DELETE,您将获得“405 Method Not Allowed”。
我喜欢这种方法,因为很容易看出发生了什么,我相信它会回答你的问题。
答案 3 :(得分:1)
我假设您已经尝试了部分匹配,如教程中所述。我发现虽然不是很好,但它确实可以在大多数时间完成工作。
除此之外,尽管我还没有尝试过,但Cherrypy显然支持Routes(参见http://www.cherrypy.org/wiki/PageHandlers),它为您提供了各种RESTful选项。
答案 4 :(得分:1)
要回答第二个问题,您需要定义并公开默认方法:
class getOrders(Object):
def default(account, type):
...
default.exposed = True
使用此方法,getOrders / x / y将映射到default(account='x', type='y')
。就像其他人说的那样,它并不好,但是它完成了工作。
就RESTful应用程序而言,我非常确定默认页面处理程序适用于这样的应用程序。