roy fielding 创建了 rest 作为他的博士论文。
读完后,我会将其归结为三个基本要素:
描述对象状态的文档
在系统之间来回传输对象状态的传输机制
对状态执行的一组操作
虽然 Roy 只专注于 HTTP,但我不明白为什么不能使用其他传输方式。以下是一些示例:
安装 WebDAV 共享(WebDAV 是 HTTP 扩展,因此仍使用 HTTP)。将电子表格(.xls、.xlsx、.csv、.ods)复制到已安装的文件夹中,其中每一行都是新的/更新的状态。复制到共享的行为表示更新插入操作,文件名表示数据类型,列是字段。服务器以(文档名称)-status.(文档后缀)进行响应,它提供每行的键、状态以及可能的错误消息。在这种情况下,请求数据并没有多大意义。
使用 gRPC。传输的对象是文档,HTTP 是传输,远程方法的名称是操作。数据可以提供和请求。
使用 FTP。 与 WebDAV 类似,它是基于文件的。 PUT 命令是更新插入,GET 命令是请求。 GET 仅提供文件名,因此它通常提供指定类型的所有数据。可以允许使用特殊文件名来指示硬编码过滤器以获取数据子集。
每当我在野外看到 REST 实现时,它们通常不遵循基本的 HTTP语义学,我从未见过对此给出任何解释,只是一堆不同的意见。我发现这些都没有引用 RFC。大多数人似乎认为:
POST = 创建
PUT = 更新整个文档
PATCH = 更新文档的一部分
GET = 检索整个文档
这与 HTTP 关于 POST 和 PUT 的规定相反:
PUT 是“创建”或“更新”。 GET 通常会返回上次 PUT 的内容。如果 PUT 创建,它必须返回 201 Created。如果 PUT 更新,它必须返回 200 OK 或 204 No Content。 RFC 建议 PUT 的 200 OK 内容应该是操作的状态。我认为就 SQL 而言,从 select 语句返回新行是可以的。这样做的优点是,任何生成的列都会返回给调用者,而无需执行单独的 GET。
POST 根据资源自身的语义处理资源。较旧的 RFC 表示 POST 适用于资源的下属。所有版本都给出了将文章发布到邮件列表的示例;所有版本都说,如果创建了资源,则应返回 201 Created。
我认为 POST 的真正含义是:
除创建、全部/部分更新或删除之外的任何数据操作
任何非数据操作的操作,例如:
执行全文搜索与短语匹配的行。
生成要在地图上显示的 GIS 对象。
该词必须表示您的仅当您按照规定执行时,实现才符合 HTTP。仅使用 PUT 进行更新显然不会破坏任何内容,只是因为它不符合 RFC 标准。如果您提供处理发送/接收数据的所有细节的客户端,那么使用什么动词对于客户端的用户来说并不重要。
我是那种想要一个理由的人不遵循 RFC。我从来不理解在 REST API 中将创建与更新分开的重要性,就像在 Web 应用程序中一样。想想日历约会、笔记、联系人等手机应用程序:
“创建”点击加号图标,它会显示一个带有空值或默认值的新表单。
“更新”正在选择一个对象并点击铅笔图标,这将显示包含当前值的条目表单。
一旦条目表单出现,它就会显示在字段验证方面的工作方式完全相同。
那么为什么 REST API 和 Web 前端与手机应用程序有任何不同呢?如果电话用户获得用于“创建”和“更新”的相同数据输入表单有帮助,那么它对 API 和网络用户是否也同样有帮助?
如果您决定使用 PUT 作为“创建”或“更新”,并且您使用 SQL 作为存储,大多数供应商都有某种类型的更新插入查询。不幸的是,这无助于决定何时返回 200 OK 或 201 Created。您必须查看驱动程序在执行 DML 查询时提供的信息,以找到区分更新插入的插入和更新的方法,或使用其他查询策略。
一个简单的示例是执行更新集...其中 pk 列 = pk 值。如果一行受到影响,则该行存在并已更新;否则,该行不存在,需要插入。在 Postgres 上,您可以利用 RETURNING 子句,它实际上可以返回任何内容,而不仅仅是行数据,如下所示:
SQL VALUES (...) ON CONFLICT( ) DO UPDATE SET ( ...) 返回 (SELECT COUNT( ) FROMWHERE = ) 存在" data-lang="text/x-sql" style="box-sizing: border-box;">1
INSERT INTO <table> VALUES (...) ON CONFLICT(<pk column>) DO UPDATE SET (...) RETURNING (SELECT COUNT(<pk column>) FROM <table> WHERE <pk column> = <pk value>) exists登录后复制
这样做的天才在于:
RETURNING 子句中的子查询首先执行,因此它会在执行 INSERT ON CONFLICT UPDATE 查询之前确定该行是否存在。查询的结果是名为“exists”的列,如果该行在查询之前存在,则该列为 1。执行,如果没有执行,则返回 0。
RETURNING 子句还可以返回行的列,包括未提供的任何生成内容。
您只需弄清楚如何处理是否需要插入或更新,并进行一个简单的抽象,您的所有 PUT 都可以调用它来处理 200 OK 或 201 Created。
使用的一个很好的好处PUT 的目的是,一旦您看到 POST,您就确定它不是检索或持久性,相反,您知道搜索 POST 来查找任何不是检索或持久性操作的代码。
我认为按照 RFC 中的描述使用 PUT 和 POST 的好处超过了人们以不符合 RFC 的方式使用它们的任何原因。
以上就是REST 和 HTTP 语义的详细内容,更多请关注本网内其它相关文章!