zope 3应用程序的rest框架
z3c.rest的Python项目详细描述
详细文档
在zope 3中构建restive服务的框架
这个包实现了几个与构建restive web相关的组件。 使用zope发布服务器的服务。每一组组件都记录在 相应的文本文件。
client.txt [必须读取]
这个包还提供了一个rest web客户端,可以用来测试 或者用于访问应用程序中的restive api。
null.txt [高级用户]
为了创建新资源,发布服务器必须能够遍历到 尚未存在的资源/对象。这个文件解释了那些空的 资源工作。
traverser.txt [高级用户]
遍历器模块包含几个遍历助手组件 常见的遍历场景,suhc作为容器和空资源。
rest.txt [信息]
本文介绍了在 出版商。它还讨论了 出版商。
rest客户端
rest客户端提供了一个简单的python api,可以轻松地与restive交互。 网络服务。它的设计与zope的测试有相似的api 浏览器,
让我们从实例化客户机开始。当然我们有一个版本 直接与zope发行商对话的客户:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()
为了进行测试,我们为文件夹定义了一个简单的rest api。这个 最简单的调用是检索根文件夹的内容:
< Buff行情>>>> client.open('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>
您还可以实例化提供url的客户机:
< Buff行情>>>> client = testing.RESTClient('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>
还支持https url
< Buff行情>>>> client = testing.RESTClient('https://localhost/') Using SSL >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>
获取资源
open() 方法隐式地使用"get"http方法。另一种选择 将使用这个:
< Buff行情>>>> client.get('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>
还有其他几条回复信息是 可用:
< Buff行情>>>> client.url 'http://localhost/' >>> client.status 200 >>> client.reason 'Ok' >>> client.fullStatus '200 Ok' >>> client.headers [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'), ('Content-Length', '204'), ('Content-Type', 'text/xml;charset=utf-8')]
如果尝试访问不存在的资源,则不会引发异常,但 状态为"404"(未找到)当然:
< Buff行情>>>> client.get('http://localhost/unknown') >>> client.fullStatus '404 Not Found' >>> client.contents '' >>> client.headers [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'), ('Content-Length', '0')]
与原始测试浏览器一样,我可以关闭zope错误处理和 python异常将通过发布服务器传播:
< Buff行情>>>> client.handleErrors = False >>> client.get('http://localhost/unknown') Traceback (most recent call last): ... NotFound: Object: <zope.site.folder.Folder ...>, name: u'unknown'
>>> client.handleErrors = True
因为restiveapi经常使用查询字符串键值对来参数化 请求,这个rest客户端对它有很强的支持。例如,您可以 只需在url中指定参数即可:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()0
也可以通过参数指定参数:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()1
您甚至可以将两种指定参数的方法结合起来:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()2
但是我们的小演示api可以做更多的事情。参数也可以指定为 带有特殊前缀的头。可以全局指定头,然后 用于每个请求:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()3
"open"方法还有一个headers参数,用于指定头 一次:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()4
>>> from z3c.rest import testing >>> client = testing.RESTClient()5
最后,在处理实际站点时,可能会发生套接字错误。误差 传播,但会记录错误号和消息:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()6
>>> from z3c.rest import testing >>> client = testing.RESTClient()7
创建新资源
现在让我们在服务器根目录中创建一个新资源。我们的小样品 应用程序只需创建另一个收藏:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()8
>>> from z3c.rest import testing >>> client = testing.RESTClient()9
每个人都可以访问文件夹资源。但我如果你想 修改任何资源,您必须登录:
< Buff行情>>>> client.open('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>0
所以让我们再试一次:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()8
>>> client.open('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>2
我们现在可以查看根容器并在其中查看项目:
< Buff行情>>>> client.open('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>3
顺便说一下,您现在可以使用相对url访问 folder1 资源:
< Buff行情>>>> client.open('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>4
>>> client.open('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>5
>>> client.open('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>6
当我们试图在不存在的资源上创建一个资源时,会得到一个 404错误:
< Buff行情>>>> client.open('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>7
>>> client.open('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>8
修改资源
修改给定的资源可以通过post或put完成,但是它们有不同的 语义学。让我们先看看帖子。我们现在想改变 文件夹的标题;可以按如下方式完成:
< Buff行情>>>> client.open('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>9
>>> client = testing.RESTClient('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>0
>>> client = testing.RESTClient('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>1
如上所述,它还必须适用于PUT:
< Buff行情>>>> client = testing.RESTClient('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>2
>>> client = testing.RESTClient('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>0
>>> client = testing.RESTClient('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>4
删除资源
删除资源和所有其他方法一样简单。让我们删除我们的 文件夹1 < Buff行情>
>>> client = testing.RESTClient('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>5
>>> client = testing.RESTClient('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>0
所以资源真的没有了:
< Buff行情>>>> client = testing.RESTClient('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>7
不应删除不存在的资源:
< Buff行情>>>> client = testing.RESTClient('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>8
此外,我们不能删除根文件夹:
< Buff行情>>>> client = testing.RESTClient('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>9
搜索响应数据
虽然不是必需的,但大多数rest服务都是基于xml的。因此,客户 支持使用xpath检查结果xml。让我们创造一些 文件夹使其更有趣:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()8
>>> client = testing.RESTClient('https://localhost/') Using SSL >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>1
接下来我们得到根文件夹资源:
< Buff行情>>>> client = testing.RESTClient('https://localhost/') Using SSL >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>2
但一般来说,在字符串级别检查xml输出是乏味的。所以 让我们编写一个很酷的xpath表达式来提取所有 项目:
< Buff行情>>>> client = testing.RESTClient('https://localhost/') Using SSL >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>3
然而,我们常常特别查询一个结果。在这种情况下,我们 不想收到列表:
< Buff行情>>>> client = testing.RESTClient('https://localhost/') Using SSL >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>4
现在,如果检测到多个匹配,即使我们只期望一个匹配,那么 出现值错误 :
< Buff行情>>>> client = testing.RESTClient('https://localhost/') Using SSL >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>5
访问链接
因为我们希望rest客户端的行为像浏览器一样-至少有一点 bit–我们还可以使用 getlink() 方法访问链接:
< Buff行情>>>> client = testing.RESTClient('https://localhost/') Using SSL >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>6
默认情况下,按标题查找链接。但你也可以通过 URL:
< Buff行情>>>> client = testing.RESTClient('https://localhost/') Using SSL >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>7
如果忘记指定标题或url,则会收到一个 valueerror :
< Buff行情>>>> client = testing.RESTClient('https://localhost/') Using SSL >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>8
链接也可以是相对的,例如acl的链接:
< Buff行情>>>> client = testing.RESTClient('https://localhost/') Using SSL >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>9
>>> client.get('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>0
链接最酷的部分是您可以单击它:
< Buff行情>>>> client.get('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>1
>>> client.get('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>2
>>> client.open('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>5
穿越时间
就像在真正的浏览器中一样,您可以返回到以前的状态。例如, 目前我们正在查看文件夹1,…
< Buff行情>>>> client.open('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>5
但如果我后退一步,我就回到根文件夹:
< Buff行情>>>> client.get('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>5
>>> client.get('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>6
>>> client.get('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>7
但如果你也能重新加载,回到历史上就很酷了。所以让我们 删除文件夹2 < Buff行情>
>>> client.get('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>8
现在我们返回两个步骤:
< Buff行情>>>> client.get('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>9
>>> client.get('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>6
>>> client.get('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>7
如所料,内容尚未改变。所以让我们重新加载:
< Buff行情>>>> client.url 'http://localhost/' >>> client.status 200 >>> client.reason 'Ok' >>> client.fullStatus '200 Ok' >>> client.headers [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'), ('Content-Length', '204'), ('Content-Type', 'text/xml;charset=utf-8')]2
>>> client.get('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>6
>>> client.url 'http://localhost/' >>> client.status 200 >>> client.reason 'Ok' >>> client.fullStatus '200 Ok' >>> client.headers [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'), ('Content-Length', '204'), ('Content-Type', 'text/xml;charset=utf-8')]4
请注意,返回零步没有任何作用:
< Buff行情>>>> client.get('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>6
>>> client.url 'http://localhost/' >>> client.status 200 >>> client.reason 'Ok' >>> client.fullStatus '200 Ok' >>> client.headers [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'), ('Content-Length', '204'), ('Content-Type', 'text/xml;charset=utf-8')]6
>>> client.open('http://localhost/') >>> print client.contents <?xml version="1.0" ?> <folder xmlns:xlink="http://www.w3.org/1999/xlink"> <name></name> <title></title> <items> </items> <acl xlink:type="simple" xlink:href="acl" xlink:title="ACL"/> </folder>5
另外,如果您试图回到时间开始之后,则值错误为 提升D:
< Buff行情>>>> client.url 'http://localhost/' >>> client.status 200 >>> client.reason 'Ok' >>> client.fullStatus '200 Ok' >>> client.headers [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'), ('Content-Length', '204'), ('Content-Type', 'text/xml;charset=utf-8')]8
绝对URL
如上所述,我们允许指定相对url,一个带有 已创建URL。一个名为 absoluteUrl() 的函数用于计算 新的绝对URL。
< Buff行情>>>> client.url 'http://localhost/' >>> client.status 200 >>> client.reason 'Ok' >>> client.fullStatus '200 Ok' >>> client.headers [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'), ('Content-Length', '204'), ('Content-Type', 'text/xml;charset=utf-8')]9
基本功能很简单:
< Buff行情>>>> client.get('http://localhost/unknown') >>> client.fullStatus '404 Not Found' >>> client.contents '' >>> client.headers [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'), ('Content-Length', '0')]0
如果url的新部分是绝对的,它还会检测到 替换原始基URL:
< Buff行情>>>> client.get('http://localhost/unknown') >>> client.fullStatus '404 Not Found' >>> client.contents '' >>> client.headers [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'), ('Content-Length', '0')]1
如果基URL没有尾随斜杠,则会自动添加:
< Buff行情>>>> client.get('http://localhost/unknown') >>> client.fullStatus '404 Not Found' >>> client.contents '' >>> client.headers [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'), ('Content-Length', '0')]2
新url结尾的斜杠将被保留:
< Buff行情>>>> client.get('http://localhost/unknown') >>> client.fullStatus '404 Not Found' >>> client.contents '' >>> client.headers [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'), ('Content-Length', '0')]3
>>> client.get('http://localhost/unknown') >>> client.fullStatus '404 Not Found' >>> client.contents '' >>> client.headers [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'), ('Content-Length', '0')]4
该函数还处理包含查询字符串的更复杂的url 正确:
< Buff行情>>>> client.get('http://localhost/unknown') >>> client.fullStatus '404 Not Found' >>> client.contents '' >>> client.headers [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'), ('Content-Length', '0')]5
>>> client.get('http://localhost/unknown') >>> client.fullStatus '404 Not Found' >>> client.contents '' >>> client.headers [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'), ('Content-Length', '0')]6
如果基url包含查询字符串,则生成的url也将:
< Buff行情>>>> client.get('http://localhost/unknown') >>> client.fullStatus '404 Not Found' >>> client.contents '' >>> client.headers [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'), ('Content-Length', '0')]7
>>> client.get('http://localhost/unknown') >>> client.fullStatus '404 Not Found' >>> client.contents '' >>> client.headers [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'), ('Content-Length', '0')]8
>>> client.get('http://localhost/unknown') >>> client.fullStatus '404 Not Found' >>> client.contents '' >>> client.headers [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'), ('Content-Length', '0')]9
>>> client.handleErrors = False >>> client.get('http://localhost/unknown') Traceback (most recent call last): ... NotFound: Object: <zope.site.folder.Folder ...>, name: u'unknown'0
如果基URL和相对URL都提供查询字符串,则它们将被合并:
< Buff行情>>>> client.handleErrors = False >>> client.get('http://localhost/unknown') Traceback (most recent call last): ... NotFound: Object: <zope.site.folder.Folder ...>, name: u'unknown'1
>>> client.handleErrors = False >>> client.get('http://localhost/unknown') Traceback (most recent call last): ... NotFound: Object: <zope.site.folder.Folder ...>, name: u'unknown'2
>>> client.handleErrors = False >>> client.get('http://localhost/unknown') Traceback (most recent call last): ... NotFound: Object: <zope.site.folder.Folder ...>, name: u'unknown'3
空资源
有时有必要遍历到尚不存在的资源。在 特别是,当使用"put"或"post"创建资源时,这是必需的。它 导线工有责任正确处理这些情况 生成空资源。本文档仅描述他们的行为。
空资源很容易使用容器和 资源:
< Buff行情>>>> client.handleErrors = False >>> client.get('http://localhost/unknown') Traceback (most recent call last): ... NotFound: Object: <zope.site.folder.Folder ...>, name: u'unknown'4
>>> client.handleErrors = False >>> client.get('http://localhost/unknown') Traceback (most recent call last): ... NotFound: Object: <zope.site.folder.Folder ...>, name: u'unknown'5
>>> client.handleErrors = False >>> client.get('http://localhost/unknown') Traceback (most recent call last): ... NotFound: Object: <zope.site.folder.Folder ...>, name: u'unknown'6
空资源是位置,因此安全性可用:
< Buff行情>>>> client.handleErrors = False >>> client.get('http://localhost/unknown') Traceback (most recent call last): ... NotFound: Object: <zope.site.folder.Folder ...>, name: u'unknown'7
容器也是父容器:
< Buff行情>>>> client.handleErrors = False >>> client.get('http://localhost/unknown') Traceback (most recent call last): ... NotFound: Object: <zope.site.folder.Folder ...>, name: u'unknown'8
资源名称位于:
< Buff行情>>>> client.handleErrors = False >>> client.get('http://localhost/unknown') Traceback (most recent call last): ... NotFound: Object: <zope.site.folder.Folder ...>, name: u'unknown'9
对于空资源有一个特殊的"put"实现。它通过 为容器查找名为"nullput"的视图。这边,一个空的 资源实现可用于所有容器实现。
< Buff行情>>>> client.handleErrors = True0
>>> client.handleErrors = True1
由于我们的 文件夹 类不存在名为"nullput"的视图,因此我们得到501 返回状态:
< Buff行情>>>> client.handleErrors = True2
现在让我们注册一个简单的nullput视图:
< Buff行情>>>> client.handleErrors = True3
>>> client.handleErrors = True4
让我们确保我们的位置结构设置正确,这样 url将起作用:
< Buff行情>>>> client.handleErrors = True5
现在我们准备好放置新资源:
< Buff行情>>>> client.handleErrors = True6
>>> client.handleErrors = True1
>>> client.handleErrors = True8
>>> client.handleErrors = True9
静止快进器部件
能够控制和扩展遍历对于任何不稳定的 应用程序编程接口。这个包使用 z3c.traverser 包提供灵活的遍历机制。
rest可插入遍历器
rest可插入遍历器是为所有类型的组件注册的。其 在 z3c.traverser 包中对实现进行了全面测试。
< Buff行情> α>>> from z3c.rest import testing >>> client = testing.RESTClient()00
>>> client.handleErrors = True0
>>> from z3c.rest import testing >>> client = testing.RESTClient()02
项目容器遍历器插件
项容器继承的项映射接口是 python中最简单的映射接口。因此,一旦穿过这个 已实现项容器,它可以被所有其他容器使用 接口和实现。
让我们从创建一个非常简单的项目容器实现开始:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()03
>>> from z3c.rest import testing >>> client = testing.RESTClient()04
>>> from z3c.rest import testing >>> client = testing.RESTClient()05
>>> from z3c.rest import testing >>> client = testing.RESTClient()06
创建遍历器插件实例之后,
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()07
>>> from z3c.rest import testing >>> client = testing.RESTClient()08
我们可以遍历到该容器的子对象:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()09
如果没有财产可以找到r子项,可以发生一些有趣的事情。在正常情况下 案例, 未找到 被引发:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()10
但是,如果请求是PUT请求,则必须生成空资源:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()11
但是,只有当当前资源是最后一个资源时,才会创建空资源 遍历堆栈中的一个:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()12
就这样。
发布者挂接rest请求
阅读本文档在某种程度上要求读者 熟悉出版过程的基本步骤。
发布请求工厂
当wsgi服务器发送请求时,zope发布过程开始。 可对zope wsgi发布服务器调用的环境和响应初始化 应用程序[1]。然后,wsgi发布者应用程序负责 在发布服务器中处理请求并输出结果。
为了在发布服务器中处理请求,我们必须创建一个有效的 发布服务器请求对象。wsgi发布服务器应用程序使用一个请求 为此目的而制造。此包实现此工厂以确保 始终会创建一个特殊的rest请求(基于http请求)。
使用zodb数据库对象实例化请求工厂:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()13
现在创建工厂:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()14
当请求从服务器传入时,将按如下方式创建该请求:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()15
>>> from z3c.rest import testing >>> client = testing.RESTClient()16
>>> from z3c.rest import testing >>> client = testing.RESTClient()17
我们现在有一个有效的请求,可以通过发布服务器发送:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()18
但是,请求只负责表示网络请求 在发布者中,对应用程序没有直接的了解。但是 请求连接到特定的应用程序(在本例中为zope 3) 称为出版物的组件。
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()19
因为我们不需要特殊的rest发布,所以我们只是重用 更通用的http版本。出版物对所有人都是一样的 请求。它还包含对数据库的引用:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()20
不幸的是,通过 发布服务器成功。该出版物还需要 发布可用,包括遍历、安全性和 构建数据库。但是,我们仍然可以看到一个失败:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()21
让我们放松一下。最初,我们从创造一个 内部使用rest请求的发布者wsgi应用程序实例。所有 您需要做的是:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()22
当wsgi服务器向wsgi应用程序发送请求时,如下所示 发生:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()23
>>> from z3c.rest import testing >>> client = testing.RESTClient()24
>>> from z3c.rest import testing >>> client = testing.RESTClient()25
其余请求
在大多数情况下,rest请求与http请求相同,因此我不会 详细介绍http请求api。
rest请求主要扩展http请求,因为它解析查询 一组参数中的URL字符串。这发生在 processinputs()
如果没有查询字符串,则参数映射为空:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()26
现在让我们传递几个参数:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()27
我们还重写了一些请求的映射方法,以便 和环境值可作为请求的一部分:
< Buff行情>>>> from z3c.rest import testing >>> client = testing.RESTClient()28
>>> from z3c.rest import testing >>> client = testing.RESTClient()29
其余响应
rest响应与http响应几乎相同,只是 它的异常处理程序返回XML而不是HTML。然而,这种方法是 仅用F或经典和字符串异常。
从响应开始,
<阻塞率> 啊!…我们现在可以调用处理程序:
<阻塞率> AAAAAAAA 131号 AAAAAAA 132让我们也尝试一个字符串异常:
<阻塞率> AAAAAAA 133重定向异常是特殊的。它实际上导致请求 已重定向。
<阻塞率> AAAAAAAA 134号 aaaaaaaaa135号休息视图
与浏览器视图不同,rest视图并不代表它自己的子资源。 (找到index.html)。相反,它仅仅定义了http的行为 特定内容组件的方法。
下面是一个示例:
<阻塞率> AAAAAAA 136restview基类提供了一个合适的构造函数:
<阻塞率> 啊! AAAAAAA 138 AAAAAAA 139当发布者遍历到myobj时,它将根据 http方法,搜索为get。然后它还希望找到一种同样的方法 命名并将其命名为@u[2]。
<阻塞率> AAAAA H140与所有其他视图一样,rest视图公开其上下文和请求:
<阻塞率> AAAAA H141因此,必须找到一个视图,这样它也有一个父视图:
<阻塞率> AAAAA H142当然,您可以将其设置为其他值:
<阻塞率> AAAAA H143更改
0.4.0(2010-10-05)
- 在zope.app.http://cite> 上添加了未声明但必需的安装依赖项
0.3.0(2010-10-05)
- 添加了未声明的测试依赖项。
- 更新了测试设置并修复了使用ZTK 1.0运行的测试。
- 使用python的 doctest 模块而不是不赞成 zope.testing.doctest
0.2.5(2008-09-16)
- bug/misfeature:最终按照需要处理url合并。所以 添加了大量测试来记录行为。
0.2.4(2008-09-04)
- restclient()现在可以正确地解释 https:// url。
0.2.3(2008-03-20)
- 错误/错误特征:叹气,正确转动尾部斜线 我觉得很痛苦。我真的希望我能让它正常工作 现在是rest客户机。
0.2.2(2008年3月19日)
- bug/misfeature:客户端总是在url的末尾添加斜线。但是 一些restapi对此非常敏感。现在斜线只保留了 如果有的话,但不会有其他的添加。
0.2.1(2008-03-06)
- 错误:有时没有读取响应体和客户端的内容 是空的。不幸的是,这个问题不能可靠地再现,但是 调试表明连接已提前关闭。(罗伊·马修)
- 功能:使软件包python 2.4和2.5兼容。
- 特点:z3c.rest需要lxml 2.0。
0.2.0(2008-03-03)
- 特性:使http调用者可以为rest客户机插入,允许 除restriquest之外的请求类型
0.1.0(2008-03-03)
-
初始释放
- publisher挂钩以构建专用rest服务器
- 错误视图支持
- 基于z3c.traverser的可插拔rest traverser
- rest客户端
- 最小示例应用程序