我正在为客户管理系统编写RESTful服务,我正在尝试找到部分更新记录的最佳实践.例如,我希望调用者能够使用GET请求读取完整记录.但是为了更新它,只允许记录上的某些操作,比如将状态从ENABLED更改为DISABLED.(我有比这更复杂的场景)
出于安全原因,我不希望调用者仅使用更新的字段提交整个记录(这也感觉有点过分).
是否有推荐的构建URI的方法?在阅读REST书籍时,RPC样式调用似乎不受欢迎.
如果以下调用返回ID为123的客户的完整客户记录
GET /customer/123
<customer>
{lots of attributes}
<status>ENABLED</status>
{even more attributes}
</customer>
Run Code Online (Sandbox Code Playgroud)
我该如何更新状态?
POST /customer/123/status
<status>DISABLED</status>
POST /customer/123/changeStatus
DISABLED
...
Run Code Online (Sandbox Code Playgroud)
更新:增加问题.如何将"业务逻辑调用"纳入REST API?这是否有商定的方式?并非所有方法都是CRUD本质上.有些更复杂,比如' sendEmailToCustomer(123) ',' mergeCustomers(123,456) ',' countCustomers() '
POST /customer/123?cmd=sendEmail
POST /cmd/sendEmail?customerId=123
GET /customer/count
Run Code Online (Sandbox Code Playgroud)
谢谢弗兰克
假设我想为人们提供RESTful资源,客户端可以在其中分配ID.
一个人看起来像这样: {"id": <UUID>, "name": "Jimmy"}
现在,客户应该如何保存(或"PUT")呢?
PUT /person/UUID {"id": <UUID>, "name": "Jimmy"} - 现在我们有这个讨厌的重复,我们必须一直验证:身体中的ID是否与路径中的ID匹配?PUT /person/UUID {"name": "Jimmy"}GET /person/UUID 回报 {"id": <UUID>, "name": "Jimmy"}PUT /person/UUID {"name": "Jimmy"}GET /person/UUID 回报 {"name": "Jimmy"}POST由于ID是由客户端生成的,因此似乎不是一个好主意.有哪些常见的模式和解决方法?仅在位置上的ID似乎是最教条正确的方式,但它也使实际实现更难.
问题的简短版本:
特定URI的"GET"是否需要匹配该URI的"PUT"?
我想不是.原因如下:
鉴于资源是客户理论上不可知的抽象事物,当我们进行PUT时,我们必须只发送一个表示.基于对RFC2616的梳理,对于具有许多(可能是无限的?)表示的资源来说,它似乎没有完全明确,但这是我的想法; 如果您同意,请告诉我:
我的期望是,如果我将表示赋予资源,那么该URI上资源的所有其他表示应该保持一致(可能更新).换句话说,您告诉资源"使用此表示来重新定义自己".
因此,我应该能够做到这一点:
PUT/resources/foo/myvacation
内容类型:image/jpg
...
并跟进这个:
GET/resources/foo/myvacation
接受:image/png
...
并以不同的格式获取myvacation的更新版本(假设服务器知道如何操作).从中推断,这个复合原子"图像+元数据"PUT也应该是合法的:
PUT/resources/foo/myvacation
内容类型:multipart/form-data内容处理:表格数据; name ="document"
Content-type:image/jpg
[..]
Content-disposition:form-data; name ="iptc"
Content-type:application/iptc
[..]
Content-disposition:form-data; name ="exif"
内容类型:application/exif
[..]
然后,因为服务器端内容协商(RFC2616第12.1节)可以基于任何事情进行,我们可以默认为"文档"内容:
GET/resources/foo/myvacation
内容类型:image/jpg
[..]
或者如果你像我那样相信RFC 2396第3.4节"查询组件是由资源解释的一串信息." 意味着带有查询字符串的URI引用与没有查询字符串的URI相同的资源(并且只是将application/x-form-urlencoded数据发送到资源时是同构的),那么这也应该是合法的:
GET/resources/foo/myvacation?content = exif
内容类型:application/exif
[..]
PUT的描述说:
PUT方法请求将所包含的实体存储在提供的Request-URI下.
对我来说,这是相当反REST的,除非你以非常自由的方式阅读它.我的解释是"PUT方法根据所包含实体的表示请求在提供的Request-URI上创建或更新资源."
后来,我们得到:
POST和PUT请求之间的根本区别体现在Request-URI的不同含义上.POST请求中的URI标识将处理所包含实体的资源.该资源可能是数据接受过程,某些其他协议的网关或接受注释的单独实体.与此相反,在URI的PUT请求识别附带请求的实体 - 用户代理知道URI打算和服务器不能尝试应用请求一些其他的资源.
我们需要同样地创造性地阅读这一点,但这里的关键点是"知道什么是URI"和"应用请求".
因此,对我来说,GET在给定URI处返回的表示不一定必须与给定URI的PUT相同,它只需要保持一致.
对或错?