跳转到主要内容

支持HTTP动词的Plone。

项目描述

Github Actions Status Coveralls github Egg Status Latest Version License

Plone REST

目的

plone.rest 允许你在 Plone 中使用 HTTP 动词,如 GET、POST、PUT、DELETE 等。

REST 代表 Representational State Transfer。它是一种创建松散耦合 Web API 的软件架构原则。

plone.rest 提供了基本的基础设施,使我们能够在 Plone 中构建 RESTful 端点。

将此基础设施与“主要”的完整 Plone REST API 分离为单独的包的原因是,你可以创建针对特定用例的替代端点。其中许多特定端点已在积极使用。

目标受众

plone.rest 是为经验丰富的 Web 开发者准备的,他们想在 Plone 上构建自己的 HTTP/REST 端点。

如果你想使用现成的完整 RESTful Plone API,你应该使用 plone.restapi。该包使用并依赖于此包。

功能

  • 注册以下 HTTP 动词的 RESTful 服务端点

    • GET

    • POST

    • PUT

    • DELETE

    • PATCH

    • OPTIONS

  • 支持基于 Dexterity 和 Archetypes 的内容对象

  • 内容协商:可以为任意媒体类型(例如‘application/json’)注册服务。

  • 命名服务允许为自定义 URL 注册服务端点

注册 RESTful 服务端点

plone.rest 允许你使用 ZCML 注册 Plone 内容的 HTTP 动词。

以下是如何在 Dexterity 内容上注册 PATCH 请求的示例

<plone:service
  method="PATCH"
  accept="application/json"
  for="plone.dexterity.interfaces.IDexterityContent"
  factory=".service.Patch"
  permission="cmf.ModifyPortalContent"
  />

你必须指定 HTTP 动词(GET、POST、PUT、DELETE、HEAD、OPTIONS),用于内容协商的媒体类型,内容对象接口,实际返回内容的工厂类以及访问服务所需的权限。

工厂类需要继承自 plone.rest 的‘Service’类,并实现一个返回响应体的 render 方法

from plone.rest import Service

class Patch(Service):

    def render(self):
        return '{"message": "PATCH: Hello World!"}'

内容协商

要访问我们创建的服务端点,我们必须向 Dexterity 对象发送 GET 请求

  1. 通过将‘Accept’头设置为‘application/json’

    PATCH /Plone/doc1 HTTP/1.1
    Host: localhost:8080
    Accept: application/json
  2. 或者通过在路径中添加显式的遍历步骤,如下所示

    PATCH /Plone/++api++/doc1 HTTP/1.1
    Host: localhost:8080

然后服务器将以‘200 OK’响应

HTTP/1.1 200 OK
Content-Type: application/json

{
  "message": "PATCH: Hello World!"
}

为什么有两种方法?使用‘Accept’头是 RESTful API 从同一 URL 获取不同响应的预期方式。然而,如果涉及到在 Varnish 或 Cloudflare 等网络加速器中缓存响应,将添加额外的挑战。将 Vary 头设置为‘Vary: Accept’在一定程度上有助于 Varnish。但是,可能会发生缓存污染,因为不同的浏览器在正常的 HTML 请求中发送不同的头。托管服务如 Cloudflare 则不支持使用‘Vary’和无法用于具有 REST 调用的网站。因此需要第二种具有不同 URL 的第二种方法。

你可以在命令行中尝试此方法

$ http --auth admin:admin PATCH localhost:8080/Plone/doc1 Accept:application/json

以下为所有受支持 HTTP 动词的示例列表

GET

$ http --auth admin:admin GET localhost:8080/Plone/doc1 Accept:application/json
$ http --auth admin:admin GET localhost:8080/Plone/++api++/doc1

POST

$ http --auth admin:admin POST localhost:8080/Plone/doc1 Accept:application/json
$ http --auth admin:admin POST localhost:8080/Plone/++api++/doc1

PUT

$ http --auth admin:admin PUT localhost:8080/Plone/doc1 Accept:application/json
$ http --auth admin:admin PUT localhost:8080/Plone/++api++/doc1

DELETE

$ http --auth admin:admin DELETE localhost:8080/Plone/doc1 Accept:application/json
$ http --auth admin:admin DELETE localhost:8080/Plone/++api++/doc1

PATCH

$ http --auth admin:admin PATCH localhost:8080/Plone/doc1 Accept:application/json
$ http --auth admin:admin PATCH localhost:8080/Plone/++api++/doc1

OPTIONS

$ http --auth admin:admin OPTIONS localhost:8080/Plone/doc1 Accept:application/json
$ http --auth admin:admin OPTIONS localhost:8080/Plone/++api++/doc1

命名服务

可以通过在服务指令中提供‘name’属性来注册命名服务

<plone:service
  method="GET"
  accept="application/json"
  for="Products.CMFPlone.interfaces.IPloneSiteRoot"
  factory=".service.Search"
  name="search"
  permission="zope2.View"
  />

这将在网站根目录中使用以下请求注册可访问的服务端点

GET /Plone/search HTTP/1.1
Host: localhost:8080
Accept: application/json

服务端点也可以使用遍历者访问

GET /Plone/++api++/search HTTP/1.1
Host: localhost:8080

额外的路径段

要处理服务 URL 后的额外路径段,如 /Plone/myservice/1/2,服务必须实现 IPublishTraverse。以下示例简单地将所有路径段存储在 self.params 中的数组中。

from plone.rest import Service
from zope.interface import implementer
from zope.publisher.interfaces import IPublishTraverse

@implementer(IPublishTraverse)
class MyService(Service):

    def __init__(self, context, request):
        super(MyService, self).__init__(context, request)
        self.params = []

    def publishTraverse(self, request, name):
        self.params.append(name)
        return self

    def render(self):
        return {'service': 'named get', 'params': self.params}

请参阅 plone.restapi 中工作流转换端点的实现,以获取其他示例。

CORS

plone.rest 允许您在 ZCML 中定义服务的 CORS(跨源资源共享)策略。以下示例定义了针对所有服务的策略。

<plone:CORSPolicy
  allow_origin="http://example.net"
  allow_methods="DELETE,GET,OPTIONS,PATCH,POST,PUT"
  allow_credentials="true"
  expose_headers="Content-Length,X-My-Header"
  allow_headers="Accept,Authorization,Content-Type,X-Custom-Header"
  max_age="3600"
  />

CORS 策略可以绑定到内容对象的特定接口和特定的浏览器层。这允许我们为不同的内容类型定义不同的策略或覆盖现有策略。以下示例定义了针对网站根的策略。

<plone:CORSPolicy
  for="Products.CMFPlone.interfaces.IPloneSiteRoot"
  layer="myproduct.interfaces.IMyBrowserLayer"
  allow_origin="*"
  allow_methods="GET"
  />

CORSPolicy 指令支持以下选项

allow_origin

允许访问资源的来源。可以是逗号分隔的来源列表,例如:“http://example.net,http://mydomain.com”或“*”。

allow_methods

逗号分隔的 HTTP 方法名称列表,此 CORS 策略允许使用,例如:“DELETE,GET,OPTIONS,PATCH,POST,PUT”。如果未指定,则允许所有已注册服务的所有方法。

allow_credentials

指示资源是否在请求中支持用户凭据。

allow_headers

逗号分隔的请求头列表,客户端可以发送这些请求头,例如:“X-My-Header”

expose_headers

逗号分隔的响应头列表,客户端可以访问这些响应头,例如:“Content-Length,X-My-Header”。

max_age

指示预检请求的结果可以缓存多长时间。

for

指定注册 CORS 策略的接口。如果没有指定此属性,则 CORS 策略应用于所有对象。

layer

注册此 CORS 策略的浏览器层。对于覆盖现有策略或仅在安装了特定插件时使其可用很有用。

安装

通过将其添加到您的 buildout 中安装 plone.rest

[buildout]

 ...

 eggs =
     plone.rest

然后运行“bin/buildout”

Plone/Python 支持

plone.rest 4.x.x 支持 Python 3.8 及更高版本上的 Plone 5.2 和 6.x。

plone.rest 3.x.x 支持 Python 2.7 和 3.6 到 3.8 上的 Plone 5.2 以及 Python 3.8 到 3.11 上的 Plone 6.0。

如果您需要使用 Python 2.7 上的 Plone 4.3、5.0 或 5.1,请查看 plone.rest 2.x.x 或 1.x.x。

重定向

plone.rest 将以与常规 Plone 相似的方式处理由 plone.app.redirector 创建的重定向。

如果给定 URL 存在重定向,则使用 GET 请求将返回 302,并在 Location 头中指示资源的新的位置。

HTTP/1.1 302 Moved Temporarily

Content-Type: application/json
Location: https://#:8080/Plone/my-folder-new-location

除 GET 之外的其他任何请求方法(POSTPATCH 等)都将返回 307 Temporary Redirect。此状态代码指示客户端不要更改方法,但可以(如果需要)在新位置使用 相同 的方法重试请求。

实际上,Python requests 库以及 Postman 似乎默认遵循此行为。

贡献

支持

此包由 Timo Stollenwerk <tisto@plone.org> 维护。

如果您遇到问题,请 告诉我们

致谢

plone.rest 由 Timo Stollenwerk (kitconcept GmbH) 和 Ramon Navarro Bosch (Iskra) 编写。

plone.rest 在 Plone 5.2 中作为核心包添加(见 https://github.com/plone/Products.CMFPlone/issues/2177)。

许可协议

该项目采用 GPLv2 许可。

变更日志

4.1.3 (2024-01-26)

内部

  • 更新配置文件。[plone 开发者] (93e1ab65)

4.1.2 (2023-10-28)

错误修复

  • 修复 Accept 头中额外斜杠解析 mimetypes 的问题。@djay (#153)

4.1.1 (2023-10-23)

内部

  • 修复测试泄露问题,在不应激活时启用发布检查。@jaroel (#168)

4.1.0 (2023-10-18)

新功能

  • 添加对 Python 3.12 的支持。@tisto (#167)

错误修复

  • 使 REST 端点检查获取的项。@jaroel (#166)

4.0.0 (2023-09-22)

破坏性变更

  • 放弃对 Python 2.7、3.6 和 3.7 的支持 @tisto (#141)

3.0.1 (2023-09-21)

错误修复

  • ++api++ 在 URL 中多次出现时,重定向到正确的 URL。当 URL 格式错误时,例如 ++api++/something/++api++,返回 404 NotFound。修复了拒绝服务问题。见 安全公告。[maurits] (#1)

3.0.0 (2023-01-29)

破坏性变更

  • 对于 GET 请求,将 HTTP 状态从 301(永久移动)更改为 302(找到),对于其他请求方法,更改为 307(临时重定向)。这修复了重新使用现有重定向时的问题。[mamico] (#135)

  • 放弃对 Plone 4.3、5.0 和 5.1 的官方支持(尽管很可能该软件包将继续工作)[tisto] (#140)

新功能

  • 添加对 Plone 6 的官方支持 [tisto] (#143)

  • 添加对 Python 3.9、3.10 和 3.11 的官方支持 [tisto] (#147)

2.0.0 (2022-10-15)

错误修复

  • 重新发布 2.0.0a6 为 2.0.0 [tisto] (#136)

2.0.0a5 (2022-04-07)

错误修复

  • 修复从父到子重定向导致的无限循环 [ericof] (#133)

2.0.0a4 (2022-03-24)

错误修复

  • ++api++ 遍历器应在 30x 重定向上保持不变 [mamico] (#132)

2.0.0a3 (2022-02-12)

错误修复

  • ++api++ 遍历器应在 30x 重定向上保持不变 [mamico] (#127)

2.0.0a2 (2022-01-25)

错误修复

  • 修复 README.rst 中的错别字 [jensens] (#123)

  • 将 document_view 作为网站根目录的默认值。[agitator] (#126)

  • 解决所有源自此包代码的弃用警告,这些警告是通过运行不支持的后向兼容性测试而暴露的。[rpatterson] (#128)

2.0.0a1 (2021-10-05)

新功能

  • 添加一个 ++api++ 遍历器作为标记 REST 请求的替代方案。[jensens] (#113)

1.6.2 (2021-02-20)

错误修复

  • 在 CORS 策略中明确使 allow_credentials 成为必需。这在此前的 Bool 字段中是默认值,直到 zope.schema 6.0.1,但在 6.1.0 中发生了变化。[maurits] (#104)

1.6.1 (2020-03-22)

错误修复

  • CORS 预检应针对所有错误代码发生,修复 #101。[sneridagh] (#101)

1.6.0 (2019-10-15)

新功能

  • 删除 CMFPlone 并将 plone.app.redirector 依赖项设置为可选 [timo] (#81)

1.5.1 (2019-10-15)

  • 棕色袋发布。

1.5.0 (2019-10-13)

  • 棕色袋发布。

1.4.0 (2018-11-08)

新功能

  • Python 3 兼容性 [tschorr,pbauer,frapell]

1.3.0 (2018-09-11)

新功能

  • 删除对 Products.CMFPlone 的不必要依赖。从 Products.CMFCore.interfaces 导入 ISiteRoot 而不是从 Products.CMFPlone.interfaces.siteroot 导入 IPloneSiteRoot。[jordic]

1.2.0 (2018-06-29)

新功能

  • 添加对 plone.app.redirector 重定向的支持。[lgraf]

1.1.1 (2018-06-22)

错误修复

  • 重新发布 1.1.0。

1.1.0 (2018-06-22)

新功能

  • 为 Zope 4 兼容性移除 Products.Five.metaclass 依赖。[timo]

1.0.0 (2018-01-17)

新功能

  • 添加对 Plone 5.1 的支持。[timo]

  • 在 setup.py 中将 Plone 4.3、5.0 和 5.1 添加到列表分类器。[timo]

  • 在 setup.py 中将开发状态设置为 production/stable。[timo]

1.0b1 (2017-05-14)

错误修复

1.0a7 (2016-11-21)

错误修复

1.0a6 (2016-05-22)

  • 添加对 CORS 策略的支持。[buchi]

  • 从服务基类中移除 JSON 渲染实现。服务必须提供自己的渲染实现。[buchi]

  • 在遍历期间回退到常规视图以确保与使用特定 Accept 头调用视图的兼容性。[buchi]

1.0a5 (2016-02-27)

  • 实现权限处理。访问服务所需的权限必须在服务指令中声明。[buchi]

  • 使用 Zope 配置系统注册服务。这提供了更好的冲突检测和解决。[buchi]

  • 改进 404 Not Found 异常的消息(不要返回 HTML)。[lgraf]

  • 添加服务分发回归测试。[lgraf]

  • 限制REST请求的遍历到内容对象。这允许我们使用命名服务(例如 /search)覆盖现有视图。[buchi]

  • 允许虚拟主机场景。这修复了#48。[tomgross]

1.0a4 (2016-02-07)

  • 重构Dexterity测试以确保服务返回正确的对象。[timo]

  • 添加对浏览器层的支持。现在可以使用“layer”属性将REST服务注册到特定的浏览器层。[buchi]

  • 删除请求方法特定的标记接口(IGET、IPOST等),因为它们对于服务查找不再需要。[buchi]

  • 添加对内容协商的支持。REST服务不再硬编码为“application/json”接受头。相反,可以使用服务指令配置媒体类型。[buchi]

  • 通过在网站根目录上使用遍历适配器而不是每个REST服务的遍历适配器来重构REST请求的遍历。这防止了REST服务被其他遍历适配器覆盖。[buchi]

1.0a3 (2015-12-16)

1.0a2 (2015-12-10)

  • 简化DynamicType预遍历钩子的补丁,并使其实际上与Archetypes一起工作。[buchi]

  • 将错误渲染为JSON。[jone]

  • 添加对命名服务的支持,允许使用“name”属性注册服务,例如 GET /Plone/searchGET /Plone/doc1/versions/1。[jone, lukasgraf, buchi]

  • 暂时从服务指令中删除“layer”,因为它尚未正确实现。[jone]

1.0a1 (2015-08-01)

  • 首次发布。[bloodbare, timo]

项目详情


下载文件

下载您平台上的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源代码分发

plone.rest-4.1.3.tar.gz (109.5 kB 查看哈希值)

上传于

构建分布

plone.rest-4.1.3-py3-none-any.whl (109.2 kB 查看哈希值)

上传于 Python 3

支持者