HTTP PUT 中的幂等性是什么?我可以禁止覆盖资源吗?

2024-01-21

我正在编写一个 REST API,我希望允许具有适当权限的经过身份验证的用户通过此 API 上传文件。我想我会用一个PUT端点来处理这个问题。我想包括一个故障保护,其中请求将被拒绝400-如果资源已经存在并且用户没有通过查询指定应该覆盖该资源(即,家庭错误)PUT https://my.server.com/api/files/path/to/file.txt?overwrite=1).

PUT 的 HTTP/1.1 RFC 文档 https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6建议允许这种情况:

如果现有资源被修改,则应发送 200(OK)或 204(无内容)响应代码以指示请求成功完成。如果无法使用 Request-URI 创建或修改资源,则应给出反映问题性质的适当错误响应。

但我对幂等性的概念很着迷。规范说 https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.2:

方法还可以具有“幂等性”属性,因为(除了错误或过期问题)N > 0 个相同请求的副作用与单个请求的副作用相同。方法 GET、HEAD、PUT 和 DELETE 共享此属性。此外,方法 OPTIONS 和 TRACE 不应该有副作用,因此本质上是幂等的。

然而,多个请求的序列也可能是非幂等的,即使按该序列执行的所有方法都是幂等的。 (如果整个序列的单次执行始终产生不会因重新执行该序列的全部或部分而更改的结果,则序列是幂等的。)例如,如果序列的结果依赖于某个序列,则该序列是非幂等的。稍后以相同顺序修改的值。

根据定义,从不产生副作用的序列是幂等的(前提是没有在同一组资源上执行并发操作)。

我无法理解这一点,因为它适用于我的场景。如果PUT https://my.server.com/myfile.txt返回一个201 Created第一次运行,然后403 Forbidden or 409 Conflict仅仅因为文件已经存在而在后续请求中不执行任何其他操作就出现错误,这是否违反了幂等性的概念?必须将查询附加到 URI 上以绕过故障保护是否会违反幂等性?


这是关于幂等性的常见思维错误。

该规则的要点不是多个相同的请求得到相同的响应。

该规则的要点是,如果多次发送相同的请求,则服务器的状态与仅发送一次相同。

因此,如果您发送相同的请求两次,第二个请求将出错并被忽略,但服务器上的状态仍然与仅发送第一个请求相同。

更新后的 HTTP 标准有一个有趣的笔记 https://www.rfc-editor.org/rfc/rfc7232#section-3.1 though:

源服务器不得执行请求的方法,如果接收到 If-Match 条件评估结果为 false;相反,源服务器 必须以 a) 412(前提条件失败)状态代码进行响应 或 b) 2xx(成功)状态代码之一(如果源服务器 已验证正在请求状态更改并且最终 状态已经反映在目标的当前状态中 资源(即用户代理请求的更改已经 成功了,但用户代理可能不知道它,也许 因为先前的响应丢失或进行了兼容的更改 由其他一些用户代理)。在后一种情况下,源服务器 不得在响应中发送验证器标头字段,除非可以 验证该请求是否与之前的更改重复 由同一用户代理创建。

即使该段落特定于使用If-Match标题,它也可能适用于这里。也许你只想回来201 Created如果您可以检测到发送了完全相同的请求。不过,这对你的问题来说有点题外话。

顺便说一句,你should使用条件标头而不是?overwrite=1。如果你明确地don't如果想要允许客户端更新已创建的资源,客户端可以简单地包括:

If-None-Match: *

然后你的服务器就可以返回412 Precondition Failed,向客户端表明该资源是之前创建的。此外,如果您想强制客户端始终包含此标头,您可以使用428 Precondition Required告诉客户。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

HTTP PUT 中的幂等性是什么?我可以禁止覆盖资源吗? 的相关文章

  • put方法中的Angularjs文件上传不起作用

    我有一个简单的待办事项应用程序 我试图在其中上传照片和单个待办事项 现在我已经创建了这个工厂函数来负责待办事项的创建 todosFactory insertTodo function todo return http post baseUr
  • 是否可以将请求标头添加到 CORS 预检请求中?

    我有一个从外部服务器 不是服务器 访问 API 的网站 为网站提供服务 通过简单的XmlHttpRequest 见下文 那个API 需要将用于访问服务的 API 密钥添加为请求标头 然而 正如这些CORS https developer m
  • Java:使用 HttpURLConnection 的 HTTP PUT

    如何执行 HTTP PUT 我正在使用的类似乎认为它正在执行 PUT 但端点将其视为我执行了 GET 我做错了什么吗 URL url new URL https HttpURLConnection conn HttpURLConnectio
  • 如何从 Retrofit2 获取字符串响应?

    我正在做 android 正在寻找一种方法来执行超级基本的 http GET POST 请求 我不断收到错误 java lang IllegalArgumentException Unable to create converter for
  • 我可以从 HTTP 请求中找到无线接入点的 BSSID(MAC 地址)吗?

    假设有人在咖啡店里无线连接到互联网 并向 johnsveryownserver com 发送 HTTP 请求 服务器端 有什么方法可以确定我的MAC地址吗 无线接入点他们连接到什么 请注意 我对他们机器的 MAC 地址不感兴趣 如果我无法使
  • Android httpclient文件上传数据损坏和超时问题

    我在 Android 中上传图像时遇到问题 我正在使用 apache httpmime 4 1 lib 代码是这样的 MultipartEntity reqEntity new MultipartEntity HttpMultipartMo
  • 如何在java中以编程方式访问网页

    有一个网页 我想从中检索某个字符串 为此 我需要登录 单击一些按钮 填充文本框 单击另一个按钮 然后就会出现字符串 我怎样才能编写一个java程序来自动执行此操作 是否有任何有用的库用于此目的 Thanks Try HtmlUnit htt
  • 如何将所有GET请求查询参数放入Go中的结构体中?

    你好 我想将 get 查询参数转换为 Go 中的结构 例如我有这样的结构 type Filter struct Offset int64 json offset Limit int64 json limit SortBy string js
  • 使用 JSON 的 Pentaho HTTP Post

    我是 Pentaho 的新手 我正在尝试执行以下工作流程 从数据库中读取一堆行 做一些转换 将它们以 JSON 格式发布到 REST Web 服务 我已经使用输入步骤和 Json 输出步骤解决了前两个问题 但是 我在执行最后一步时遇到两个问
  • 以 REST 方式更新整个资源集合

    我有一个资源列表的 REST URI 例如 http foo com group users 这些用户中的每一个都有一个序列号 我想公开一种方法来为集合中的所有用户重新编号这些值 并使访问该列表的每个人都可以使用此更改 由于这是对整个集合的
  • cookie 在会话结束时或在特定时间过期?

    cookie 是否可以在会话结束时或在特定时间过期 是的 这很简单 HttpCookie newCookie new HttpCookie myCookie newCookie Expires DateTime Today AddDays
  • Node.js:在检索 http 请求正文之前断开 http 请求连接

    我正在用 Node js 编写一个 http 服务器 我有一个客户端通过 HTTP POST 多部分 数据 将大文件上传到该服务器 我想接受唯一使用有效文件名上传文件的连接 我有一些条件 在服务器检索数据之前应断开无效文件名连接 我不知道如
  • 如何找出数据包的HTTP头长度?

    我知道如何手动执行此操作 通过查看十六进制转储 我怎样才能自动获得相同的信息 我必须使用 API 吗 我有wireshark 和Microsoft 网络监视器 这可以通过简单地实现Lua解析器 http wiki wireshark org
  • 为什么http使用CRLF作为行分隔符?

    据我所知 使用LF因为行分隔符非常流行 但我想知道为什么许多文本协议 如 HTTP FTP 使用CRLF作为它的行分隔符 我不认为这些协议是为旧打字机发明的 那么这有什么历史原因吗 我尝试通过谷歌 stackoverflow 和维基百科搜索
  • AngularJS 1.X 中的异步调用是如何工作的? $Http 调用没有返回值

    我有以下名为的函数getvalue 它与控制器一起位于 AngularJS 模块内 我试图在单击事件上调用此函数 调用控制器中的另一个函数 我希望我很清楚 功能 function getvalue Data http var value u
  • Android 套接字和 HTTP 响应标头

    有趣的是 我可能无意中找到了解决方案是否可以使用普通套接字连接发送 HTTP 请求并接收没有标头的响应 https stackoverflow com questions 8320574 我希望我忽略了一些东西 无论如何 我正在连接到 We
  • 对于较大的请求正文,Nginx proxy_cache_key $request_body 将被忽略

    我使用 nginx 作为反向代理 我希望它能够缓存 POST 请求 我的后端已正确配置为为 POST 请求返回适当的缓存控制标头 在 nginx 中我配置了 proxy cache methods POST proxy cache key
  • 当查看 X-Auth-Token 与 Authorization 标头之间的差异时,哪个是首选?

    下面两个标题有什么区别 哪一个是首选 X Auth Token dadas123sad12 Authorization Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ Authorization是客户端使用的主要标头认证如
  • Chrome 问题 - 视频流和会话冲突

    我在使用 javascript 和 PHP 实现视频时遇到问题 索引 php session start do other stuff include video php 视频 php
  • Java 中的下载管理器 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我需要通过 FTP HTTP 从 Java 获取几个大文件 几个演出 有现成的库 java 命令行工具

随机推荐