此包与zope发布服务器集成,根据“if none match”、“if match”和“if modified since”、“if unmodified since”协议验证条件请求。

z3c.conditionalviews的Python项目详细描述


z3c.条件视图

z3c.conditionalviews是一种基于 条件协议,如实体标记或上次修改日期。它也是 可扩展,以便像webdav这样的协议可以定义自己的条件 像if头这样的协议。

它通过将每个条件协议实现为ihttpvalidator 实用程序,请参阅etag和lastmodify模块以了解最常见的用例。 然后当发布者调用某些视图时,我们查找这些实用程序 让他们根据任何协议验证请求对象 实用工具实现。

在调用视图时,当我们验证请求时,我们 通常可以访问上下文、请求和查看自身。所以 ihttpvalidator实用程序通常会将这3个对象调整为一个对象 实现特定于所讨论协议的接口。例如 实体标记验证器查找实现ietag的适配器。

与zope的集成

>>> import zope.component
>>> import zope.interface
>>> import z3c.conditionalviews.interfaces
>>> import z3c.conditionalviews.tests

装饰工

为了集成可以缓存的常见浏览器视图,我们可以修饰 视图使用z3c.conditionalviews.conditionalview对象调用方法。 注意,此测试中使用的所有视图都在ftesting.zcml中定义 文件。

>>> response = http(r"""
... GET /@@simpleview.html HTTP/1.1
... Host: localhost
... """, handle_errors = False)
>>> response.getStatus()
200
>>> response.getHeader('content-length')
'82'
>>> response.getHeader('content-type')
'text/plain'
>>> print response.getBody()
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

因为我们还没有定义一个实现ietag的适配器,所以 不包含ETag头。

>>> response.getHeader('ETag') is None
True

定义我们的ietag实现。

>>> class SimpleEtag(object):
...    zope.interface.implements(z3c.conditionalviews.interfaces.IETag)
...    def __init__(self, context, request, view):
...        pass
...    weak = False
...    etag = "3d32b-211-bab57a40"
>>> zope.component.getGlobalSiteManager().registerAdapter(
...    SimpleEtag,
...    (zope.interface.Interface,
...     zope.publisher.interfaces.browser.IBrowserRequest,
...     zope.interface.Interface))
>>> response = http(r"""
... GET /@@simpleview.html HTTP/1.1
... Host: localhost
... """, handle_errors = False)
>>> response.getStatus()
200
>>> response.getHeader('content-length')
'82'
>>> response.getHeader('content-type')
'text/plain'
>>> response.getHeader('ETag')
'"3d32b-211-bab57a40"'
>>> print response.getBody()
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

现在通过设置请求头如果没有匹配:“3d32b-211-bab57a40”,我们的 视图验证失败,返回304响应。

>>> response = http(r"""
... GET /@@simpleview.html HTTP/1.1
... Host: localhost
... If-None-Match: "3d32b-211-bab57a40"
... """, handle_errors = False)
>>> response.getStatus()
304
>>> response.getHeader('ETag')
'"3d32b-211-bab57a40"'
>>> response.getBody()
''

xxx-这似乎不对不应设置内容长度和内容类型 对于这个回应。

>>> response.getHeader('content-length')
'0'
>>> response.getHeader('content-type')
'text/plain'

现在确保我们没有破坏出版商,确保我们 仍然可以将参数传递给不同的视图。

>>> response = http(r"""
... GET /@@simpleview.html?letter=y HTTP/1.1
... Host: localhost
... """, handle_errors = False)
>>> response.getStatus()
200
>>> response.getHeader('content-length')
'82'
>>> print response.getBody()
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy

我们现在正在为此请求获取一个字符集值,因为 当接收到数据时,simpleview的值不是unicode字符串 默认情况下,从请求自动转换为Unicode。

>>> response.getHeader('content-type')
'text/plain;charset=utf-8'

因为请求中有一个查询字符串,所以我们不设置etag 头球。

>>> response.getHeader('ETag') is None
True

以下请求中的查询字符串导致请求 有效,否则无效。

>>> response = http(r"""
... GET /@@simpleview.html?letter=y HTTP/1.1
... If-None-Match: "3d32b-211-bab57a40"
... Host: localhost
... """, handle_errors = False)
>>> response.getStatus()
200

通用http条件发布

我们可以将验证方法与发布调用方法集成。这个 作为尝试验证通过 出版物callobject方法。这对于验证 修改对象,以便客户端可以说如果没有修改此资源 上次下载资源后发生更改,或者如果不存在 某个位置的资源。

这有额外的好处,我们不需要指定 实现Put方法。

>>> resp = http(r"""
... PUT /testfile HTTP/1.1
... Authorization: Basic mgr:mgrpw
... Content-type: text/plain
... Content-length: 55
... aaaaaaaaaa
... aaaaaaaaaa
... aaaaaaaaaa
... aaaaaaaaaa
... aaaaaaaaaa""", handle_errors = False)
>>> resp.getStatus()
201
>>> resp.getHeader('Content-length')
'0'
>>> resp.getHeader('Location')
'http://localhost/testfile'
>>> resp.getHeader('ETag', None) is None
True

我们现在可以获取资源和实体标记。

>>> resp = http(r"""
... GET /testfile HTTP/1.1
... Authorization: Basic mgr:mgrpw
... """)
>>> resp.getStatus()
200
>>> resp.getHeader('ETag')
'"testfile:1"'
>>> print resp.getBody()
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa

我们可以使用head方法来获取实体标记。

>>> resp = http(r"""
... HEAD /testfile HTTP/1.1
... Authorization: Basic mgr:mgrpw
... """)
>>> resp.getStatus()
200
>>> resp.getHeader('ETag')
'"testfile:1"'

如果没有“if none match”头,则重写数据。

>>> resp = http(r"""
... PUT /testfile HTTP/1.1
... Authorization: Basic mgr:mgrpw
... Content-type: text/plain
... Content-length: 55
... bbbbbbbbbb
... bbbbbbbbbb
... bbbbbbbbbb
... bbbbbbbbbb
... bbbbbbbbbb""", handle_errors = False)
>>> resp.getStatus()
200
>>> resp.getHeader('Content-length')
'0'
>>> resp.getHeader('Location', None) is None
True
>>> resp.getHeader('ETag')
'"testfile:2"'
>>> resp = http(r"""
... GET /testfile HTTP/1.1
... Authorization: Basic mgr:mgrpw
... """)
>>> resp.getStatus()
200
>>> print resp.getBody()
bbbbbbbbbb
bbbbbbbbbb
bbbbbbbbbb
bbbbbbbbbb
bbbbbbbbbb

指定一个if none match:“*”头,表示仅当存在 在请求uri中指定的位置没有资源。如果有 资源,然后a412 precondition failed响应为 返回且资源未被修改'

>>> resp = http(r"""
... PUT /testfile HTTP/1.1
... Authorization: Basic mgr:mgrpw
... If-None-Match: "*"
... Content-type: text/plain
... Content-length: 55
... cccccccccc
... cccccccccc
... cccccccccc
... cccccccccc
... cccccccccc""")
>>> resp.getStatus()
412
>>> resp.getHeader('Content-length')
'0'
>>> resp.getHeader('Location', None) is None
True
>>> resp.getHeader('ETag')
'"testfile:2"'

文件不会更改。

>>> resp = http(r"""
... GET /testfile HTTP/1.1
... Authorization: Basic mgr:mgrpw
... """)
>>> resp.getStatus()
200
>>> print resp.getBody()
bbbbbbbbbb
bbbbbbbbbb
bbbbbbbbbb
bbbbbbbbbb
bbbbbbbbbb

现在既然TestFiel2确实存在,我们就满足了内容。

>>> resp = http(r"""
... PUT /testfile2 HTTP/1.1
... Authorization: Basic mgr:mgrpw
... If-None-Match: "*"
... Content-type: text/plain
... Content-length: 55
... yyyyyyyyyy
... yyyyyyyyyy
... yyyyyyyyyy
... yyyyyyyyyy
... yyyyyyyyyy""")
>>> resp.getStatus()
201
>>> resp.getHeader('Content-length')
'0'
>>> resp.getHeader('Location')
'http://localhost/testfile2'
>>> resp.getHeader('ETag', None) is None # No etag adapter is configured
True
>>> resp = http(r"""
... GET /testfile2 HTTP/1.1
... Authorization: Basic mgr:mgrpw
... """)
>>> resp.getStatus()
200
>>> print resp.getBody()
yyyyyyyyyy
yyyyyyyyyy
yyyyyyyyyy
yyyyyyyyyy
yyyyyyyyyy

我们现在可以删除资源,只要它没有改变。所以对于 “/testfile”资源我们可以使用它的第一个实体标记来确认这一点。

>>> resp = http(r"""
... DELETE /testfile HTTP/1.1
... Authorization: Basic mgr:mgrpw
... If-Match: "testfile:1"
... """)
>>> resp.getStatus()
412

文件仍然存在。

>>> resp = http(r"""
... GET /testfile HTTP/1.1
... Authorization: Basic mgr:mgrpw
... """)
>>> resp.getStatus()
200

但是使用有效的实体标记我们可以删除资源。

>>> resp = http(r"""
... DELETE /testfile HTTP/1.1
... Authorization: Basic mgr:mgrpw
... If-Match: "testfile:2"
... """)
>>> resp.getStatus()
200
>>> resp.getBody()
''
>>> resp = http(r"""
... GET /testfile HTTP/1.1
... Authorization: Basic mgr:mgrpw
... """)
>>> resp.getStatus()
404

不允许的方法

对于不允许的方法,我们仍然应该得到405 method not allowed状态 已经登记了。

我们需要记录才能遍历到文件。

>>> resp = http(r"""
... FROG /testfile2 HTTP/1.1
... Authorization: Basic mgr:mgrpw
... """)
>>> resp.getStatus()
405
>>> resp.getHeader('ETag', None) is None
True

清理

>>> zope.component.getGlobalSiteManager().unregisterAdapter(
...    SimpleEtag,
...    (zope.interface.Interface,
...     zope.publisher.interfaces.browser.IBrowserRequest,
...     zope.interface.Interface))
True

z3c.conditionalView中的更改

1.0(2008-09-27)

  • 使用idctimes而不是izopedublincore,因为idctimes是实际的 必需的接口。

1.0b

  • 修正了处理协议中的时区问题。

0.9

  • 初次发布。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java在Websphere MQ临时队列上未收到回复   泛型构造函数在Java中的作用是什么?   java在Youtube HTTP请求中指定空格字符   hashmap在Java中如何读取另一个地图中的地图?   如果有类,java将在编译时签入。类派生自另一个类。班   java在安卓 junit测试执行期间捕获logcat输出   java如何在列表中拆分不同类型的字符串   java仅从输入读取某些行?   java在执行jar后继续批处理文件   ICEPDF Java中书签的框架设置   java将文件上传到服务器根目录   java如何在Spring Boot中缓存CompletableFuture的值   java正则表达式来解析命令字符串   java Hibernate按关联属性过滤   使用Java提取HTML标记   java Hibernate配置使用JAR模块中的注释在Spring MVC EAR项目中不起作用   java为什么我在传递给freemarker的哈希映射上得到一个null值,而它不是null?