我正处于开发一些REST API的十字路口,我没有发现关于这个主题的真正讨论,更不用说对这两者的坚定辩护了。
据我了解,使用REST,您有/<resource>/<action>
作为您的网址
因此,要禁用用户,您需要:
PUT /user/disable
似乎合理。但是,我们正在讨论更基本的方法:
应该是:
POST /user (creates a user *implicitly*)
POST /user/create (creates a user *explicitly*)
DELETE /user/:id
DELETE /user/:id/delete
第一个似乎被认为是“标准”,第二个显然更明确的意图并且与/ user / disable
等方法一致也许这场辩论在其他地方肆虐,但我还没有看到。如果你对此有“宗教信仰”,那么现在就是你的教诲机会
答案 0 :(得分:4)
将/<resource>/<action>
作为您的网址不是REST。 REST使用HTTP谓词来确定要对给定资源或资源集合执行的操作。这意味着:
POST /users
GET /users/<id>
PUT /users/<id>
DELETE /users/<id>
那是REST。
对于所有其他方法,您可以使用其他动词,例如PATCH
。禁用用户可能是:
PATCH /users/<id>/disable
这不是纯粹的REST,但没关系。
编辑:如果您希望与REST兼容,则禁用用户意味着您要更改其状态。换句话说,您希望更改其中一个属性,如state
标志。您可以“修补”您的资源:
PATCH /users/<id>?state=disabled
这是REST。您也可以使用PUT
替换资源,如评论中所述。
答案 1 :(得分:2)
@Christian Bongiorno
您在URI中编码与REST无关的操作。它是最清晰的RPC形式。
您需要使用您使用的基础协议中定义的方法(即您的情况下为HTTP)来识别资源并对这些资源执行操作。 HTTP规范定义了这些方法的语义,因此您必须执行以下操作,而不是直接在URI中编码操作:
这就是你应该如何思考行动。但是这还不够,你需要使用媒体格式来支持这种超媒体控制作为链接(至少),以便能够描述这些动作,例如见:
一些快速互动示例:
***Request***
GET /users HTTP/1.1
Host: service.org
Accept: application/x+json
***Response***
HTTP/1.1 200 OK
Content-Type: application/x+json
Content-Length: ...
[{
"name": "john",
"links": {
"self": "/users/1",
"edit": "/users/1"
}
}, {
"name": "jane",
"links": {
"self": "/users/2",
"edit": "/users/2"
}
}]
***Request***
GET /users/2 HTTP/1.1
Host: service.org
Accept: application/x+json
***Response***
HTTP/1.1 200 OK
Content-Type: application/x+json
Content-Length: ...
{
"name": "jane",
"links": {
"self": "/users/2",
"edit": "/users/2"
}
}
***Request***
DELETE /users/2 HTTP/1.1
Host: service.org
***Response***
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: ...
Resource was destroyed...
***Request***
POST /users/2 HTTP/1.1
Host: service.org
Content-Type: application/x+json
Content-Lenght: ...
{"status": "disabled"}
***Response***
HTTP/1.1 303 See Other
Location: /users/2
答案 2 :(得分:0)
在您的网址中执行操作不是REST。
我解决此问题的方法是定义一个动作子资源。
你可以这样做:
POST /users/123/actions
并以json请求正文:
{
"type": "reset_password",
"current_password": "mypassword",
"new_password": "$myNewPass2#"
}