关于正确的 REST api 设计的问题,特别是更新资源时的 PUT 操作

Questions on proper REST api design specifically on the PUT action when updating a resource

我正在创建一个 REST 接口(我们不是都这样),我想更新一个资源。

所以,我想使用 PUT。

所以,我读了this

我的收获是我 PUT 到 URL 这样的

/hc/api/v1/organizer/event/762d36c2-afc5-4c51-84eb-9b5b0ef2990c

带有有效载荷,然后永久重定向到 URL 它可以获得资源的更新版本。 在这种情况下它恰好是相同的URL,不同的动作。

所以我的问题是:

  1. 我对使用 PUT 更新资源的理解是否正确,我对 PUT 使用的理解是否正确。
  2. 当客户端获得重定向时,它是否对重定向的 URL 执行与对原始 URL 相同的操作?如果它 "depends" 是否有大多数客户遵循的标准?

我问第 2 个问题,因为 POSTMAN 和我的 JQuery AJAX 通话令人窒息。 JQuery 因为 net::ERR_TOO_MANY_REDIRECTS。那么它是否重定向并再次尝试 PUT,它会得到另一个重定向?

curl 也爆炸了,但即使它说如果它获得 301 它将切换到 GET,但当我查看输出时(如下),它似乎并没有真正做到这一点。

当 curl 遵循重定向且请求不是普通 GET(例如 POST 或 PUT)时,如果 HTTP 响应为 301,它将使用 GET 执行以下请求、302 或 303。如果响应代码是任何其他 3xx 代码,curl 将使用相同的未修改方法重新发送以下请求。

CURL OUTPUT(为简洁起见进行了编辑)(另请注意它是如何说它要切换到 GET [从 POST 错误地切换到 GET],但它似乎还是执行了 PUT ):

curl -X PUT -H "Authorization: Basic AUTHZ==" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -H "Postman-Token: e80657f0-a8f5-af77-1d9d-d7bc22ed0b30" -d '{ JSONDATA"}' http://localhost:8080/hc/api/v1/organizer/event/762d36c2-afc5-4c51-84eb-9b5b0ef2990c -v -L
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> PUT /hc/api/v1/organizer/event/762d36c2-afc5-4c51-84eb-9b5b0ef2990c HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:8080
> Accept: */*
> Authorization: Basic AUTHZ==
> Content-Type: application/json
> Cache-Control: no-cache
> Postman-Token: e80657f0-a8f5-af77-1d9d-d7bc22ed0b30
> Content-Length: 203
>
* upload completely sent off: 203 out of 203 bytes
< HTTP/1.1 301 Moved Permanently
< Connection: keep-alive
< X-Powered-By: Undertow/1
< Set-Cookie: rememberMe=deleteMe; Path=/hc; Max-Age=0; Expires=Fri, 20-Feb-2015 03:53:28 GMT
< Set-Cookie: JSESSIONID=uwI3_41LAa7vlvapTsrZdw10.macbook-air; path=/hc
* Server WildFly/8 is not blacklisted
< Server: WildFly/8
< Location: /hc/api/v1/organizer/event/762d36c2-afc5-4c51-84eb-9b5b0ef2990c
< Content-Length: 0
< Date: Sat, 21 Feb 2015 03:53:28 GMT
<
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost:8080/hc/api/v1/organizer/event/762d36c2-afc5-4c51-84eb-9b5b0ef2990c'
* Switch from POST to GET
* Found bundle for host localhost: 0x7f9e4b415430
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (127.0.0.1) port 8080 (#0)
> PUT /hc/api/v1/organizer/event/762d36c2-afc5-4c51-84eb-9b5b0ef2990c HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:8080
> Accept: */*
> Authorization: Basic dGVzdHVzZXIxOlBhc3N3b3JkMQ==
> Content-Type: application/json
> Cache-Control: no-cache
> Postman-Token: e80657f0-a8f5-af77-1d9d-d7bc22ed0b30
>
< HTTP/1.1 500 Internal Server Error
< Connection: keep-alive
< Set-Cookie: JSESSIONID=fDXxlH2xI-0-DEaC6Dj5EhD9.macbook-air; path=/hc
< Content-Type: text/html; charset=UTF-8
< Content-Length: 8593
< Date: Sat, 21 Feb 2015 03:53:28 GMT
<

...失败随之而来...它实际上做了一个 PUT

提前致谢。

我认为您对 301 重定向部分的解读过多。

如果您想使用 PUT 更新资源,return:

  • 201: 如果资源已创建
  • 200: 更新后的资源

问题中的 301 仅在实际存在问题重定向时适用 - 例如,如果可以通过名称识别某些内容,并且您需要将其重定向到具有 id 或其他内容的 url。 (也许你重构了,人们仍在使用旧端点)。

那么,您真的需要重定向您的 PUT 请求吗?因为你应该在同一个循环中使用 200 发回更新的资源,如上所述,而不是 "redirecting to GET".

编辑:修复一些拼写问题。