首页 文章

资源已存在时POST的HTTP响应代码

提问于
浏览
605

我正在构建一个允许客户端存储对象的服务器 . 这些对象在客户端完全构造,完整的对象ID对于对象的整个生命周期是永久的 .

我已经定义了API,以便客户端可以使用PUT创建或修改对象:

PUT /objects/{id} HTTP/1.1
...

{json representation of the object}

是对象ID,因此它是Request-URI的一部分 .

现在,我也在考虑允许客户端使用POST创建对象:

POST /objects/ HTTP/1.1
...

{json representation of the object, including ID}

由于POST意味着“追加”操作,我不知道如果对象已经存在该怎么办 . 我应该将请求视为修改请求还是应该返回一些错误代码(哪个)?

15 回答

  • 7

    208 - http://httpstatusdogs.com/208-already-reported怎么样?这是一个选择吗?

    在我看来,如果唯一的东西是重复资源,则不应该引发错误 . 毕竟,客户端或服务器端都没有错误 .

  • 1

    另一种可能的治疗方法是使用PATCH . PATCH定义为改变内部状态的东西,不限于追加 .

    PATCH允许您更新现有项目,从而解决问题 . 见:RFC 5789: PATCH

  • 9

    在检查重复记录的正确代码时偶然发现了这个问题 .

    请原谅我的无知,但我不明白为什么每个人都忽略了代码“300”,它清楚地说“多选”或“暧昧”

    在我看来,这将是构建非标准或特定系统供您自己使用的完美代码 . 我也错了!

    https://tools.ietf.org/html/rfc7231#section-6.4.1

  • 1

    返回418怎么样?

    因为客户端要求保留已经存在于服务器上的实体,服务器最终会生气并认为他是一个茶壶并返回: 418 I'm a teapot .

    参考文献:

  • 13

    我的感觉是 409 Conflict 是最合适的,然而,当然在野外很少见到:

    由于与资源的当前状态发生冲突,无法完成请求 . 只有在预期用户可能能够解决冲突并重新提交请求的情况下,才允许使用此代码 . 响应主体应该包含足够的信息供用户识别冲突的来源 . 理想情况下,响应实体将包含足够的信息供用户或用户代理解决问题;但是,这可能是不可能的,也不是必需的 . 冲突最有可能发生在响应PUT请求时 . 例如,如果正在使用版本控制并且包含PUT的实体更改为与早期(第三方)请求所产生的资源冲突的资源,则服务器可能会使用409响应来指示它无法完成请求 . 在这种情况下,响应实体可能包含由响应Content-Type定义的格式的两个版本之间的差异列表 .

  • 4

    可能在游戏后期,但我在尝试制作REST API时偶然发现了这个语义问题 .

    为了扩展Wrikken的答案,我认为你可以使用 409 Conflict403 Forbidden ,具体取决于具体情况 - 简而言之,当用户无法解决冲突并完成请求时,使用403错误(例如,他们不能发送 DELETE 请求以显式删除资源),或者如果可能的话可以使用409 .

    10.4.4 403 Forbidden服务器理解请求,但拒绝履行请求 . 授权无效,请求不应重复 . 如果请求方法不是HEAD并且服务器希望公开为什么请求没有得到满足,那么它应该描述实体中拒绝的原因 . 如果服务器不希望将此信息提供给客户端,则可以使用状态代码404(未找到) .

    如今,有人说“403”和权限或身份验证问题浮现在脑海中,但规范说它基本上是服务器告诉客户端它不会这样做,不要再问它,这就是为什么客户端不应该“T .

    至于 PUTPOST ... POST 应该用于在用户无法或不应该为资源创建标识符时创建资源的新实例 . 资源的标识已知时使用 PUT .

    9.6 PUT ... POST和PUT请求之间的根本区别体现在Request-URI的不同含义上 . POST请求中的URI标识将处理所包含实体的资源 . 该资源可能是数据接受过程,某些其他协议的网关或接受注释的单独实体 . 相反,PUT请求中的URI标识请求附带的实体 - 用户代理知道URI的用途,并且服务器不得尝试将请求应用于其他资源 . 如果服务器希望将请求应用于不同的URI,它必须发送301(永久移动)响应;然后,用户代理可以自己决定是否重定向请求 .

  • 2

    我认为对于REST,你只需要对该特定系统的行为做出决定,在这种情况下,我认为“正确”的答案将是这里给出的几个答案之一 . 如果您希望请求停止并且行为就好像客户端在继续之前犯了一个需要修复的错误,那么使用409.如果冲突真的不那么重要并且想要保持请求继续,那么通过重定向来响应客户端到找到的实体 . 我认为正确的REST API应该在POST之后重定向(或至少提供位置头)到该资源的GET endpoints ,因此这种行为将提供一致的体验 .

    编辑:值得注意的是,你应该考虑一个PUT,因为你提供了ID . 然后行为很简单:“我现在不关心那里有什么,把这件事放在那里 . ”意思是,如果没有任何东西,它就会被创造出来;如果有东西它会被替换 . 我认为POST是当服务器管理该ID时更合适 . 分离这两个概念基本上告诉你如何处理它(即PUT是幂等的,所以只要有效载荷有效,它总是有效,POST总是创建,所以如果有ID冲突,那么409会描述这个冲突) .

  • 744

    这都是关于 context ,还有谁负责重复(服务器或客户端或两者)

    如果服务器只是 point the duplicate ,请查看4xx:

    • 400 Bad Request - 当服务器不处理请求时,因为它显然是客户端故障

    • 409冲突 - 如果服务器不处理请求,但原因不是客户端的错误

    对于 implicit 处理重复项,请查看2XX:

    • 200好的

    • 201创建

    如果服务器是 expected to return something ,请查看3XX:

    发现

    • 302

    • 303见其他

    当服务器能够指向现有资源时,意味着重定向 .

    如果以上是不够的,那么在响应主体中准备一些错误消息总是一个好习惯 .

  • 6

    为什么不 202 Accepted ?这是一个OK请求(200s),本身没有客户端错误(400s) .

    来自10 Status Code Definitions

    “202 Accepted . 请求已被接受处理,但处理尚未完成 . ”

    ...因为它不需要完成,因为它已经存在 . 客户不知道它已经存在,他们没有做错任何事 .

    我倾向于投掷一个202,并返回类似的内容到GET /{resource}/{id} 将返回的内容 .

  • 59

    "302 Found"听起来合情合理 . 并且RFC 2616表示可以回答除GET和HEAD之外的其他请求(这肯定包括POST)

    但它仍然让访问者通过这个URL来获取RFC的“Found”资源 . 为了使它直接进入真正的“找到”URL,应该使用“303 See Other”,这是有道理的,但强制另一个调用GET以下的URL . 好的方面,这个GET是可缓存的 .

    我认为 I would use "303 See Other" . 我不知道我是否可以回复身体中的"thing",但我想这样做是为了将一次往返保存到服务器 .

    UPDATE: 重新阅读RFC后,我仍然认为 inexistent "4XX+303 Found"代码应该是正确的 . 但是, "409 Conflict" is the best existing answer code (由@ Wrikken指出),可能包括指向现有资源的Location头 .

  • 3

    我认为你不应该这样做 .

    如您所知,POST是修改集合的,它用于创建新项目 . 所以,如果你发送id(我认为这不是一个好主意),你应该修改集合,即修改项目,但这是令人困惑的 .

    用它来添加一个没有id的项目 . 这是最好的做法 .

    如果要捕获UNIQUE约束(而不是id),则可以响应409,就像在PUT请求中一样 . 但不是身份证 .

  • 2

    更有可能是 400 Bad Request

    6.5.1 . 400错误请求400(错误请求)状态代码表示服务器由于被认为是客户端错误(例如,格式错误的请求语法,无效请求消息框架或欺骗性请求路由)而无法或不会处理请求 .

    由于请求包含重复值(已存在的值),因此可将其视为客户端错误 . 需要在下次尝试之前更改请求 .
    通过考虑这些事实,我们可以得出结论为HTTP STATUS 400 Bad Request .

  • 63

    我个人使用WebDAV扩展 422 Unprocessable Entity .

    REST Patterns describes it as

    422 Unprocessable Entity状态代码表示服务器理解请求实体的内容类型(因此415不支持的媒体类型状态代码是不合适的),并且请求实体的语法是正确的(因此400 Bad Request状态代码是不合适的) )但无法处理所包含的指令 .

  • 12

    我会使用 422 Unprocessable Entity ,当请求无效但问题不在语法或身份验证中时使用 .

    作为反对其他答案的论据,使用任何非 4xx 错误代码意味着它不是客户端错误,显然是 . 使用非 4xx 错误代码来表示客户端错误根本没有任何意义 .

    似乎 409 Conflict 是这里最常见的答案,但是,根据规范,这意味着资源已经存在,并且您应用于它的新数据与其当前状态不兼容 . 如果您要发送 POST 请求,例如,已使用的用户名,则当存储的资源版本与请求的资源版本之间存在冲突时,'s not actually conflicting with the target resource, as the target resource has not yet been posted to. It'是专门针对版本控制的错误 . 它对于此目的非常有用,例如,当客户端缓存旧版本的资源并根据不再有条件有效的不正确版本发送请求时 . "In this case, the response representation would likely contain information useful for merging the differences based on the revision history."使用该用户名创建另一个用户的请求是无法处理的,与版本控制无关 .

    对于记录,422也是当您尝试使用已在使用的名称创建存储库时GitHub使用的状态代码 .

  • 17

    根据RFC 7231,可以使用 303 See Other 如果处理POST的结果等同于现有资源的表示 .

相关问题