让我们假设您有一个REST资源Restriction
(认为是一个路障),其中包含一些过滤器(例如街道,方向等)。限制中有一个expiry
,它是一个日期时间。仅在应用程序逻辑中考虑它是在到期日或未设置/为空(没有到期日)时。
现在有了程序样式,我可以对expire()
进行限制,该方法将到期时间设置为当前时间。
借助REST,我们改为修改资源的状态。我在这些或多或少的功能上等效的API定义之间感到困惑:
PATCH /restrictions/{id}
data = {
"expiry": 1558654742
}
客户端显式设置到期时间。这会带来用户时区错误,主机时钟错误等风险。此外,客户端除了当前时间外别无选择。
PATCH /restrictions/{id}
data = {
"expired": true
}
expired
字段是一个临时虚拟属性,在后端将其转换为expiry = now
。这可能会使客户感到困惑。另外,expired
的值只能是true
,因此这里有些冗余。
DELETE /restrictions/{id}
资源保持持久状态(软删除),但是GET对集合不返回,后者仅返回未过期的限制。个体限制没有GET。
PUT /restrictions/{id}/expiry
data = {}
创建一个新的虚拟资源(此路径上没有其他方法),该资源表示有效期。不确定没有任何数据的PUT是否惯用。
目前,我不打算返回单个限制,默认情况下,所有限制的列表将仅返回未过期的限制。
对于RESTful Web服务,您认为哪种方法最惯用和最明显?
答案 0 :(得分:0)
如果资源在过期后将返回404,则DELETE
是一个很好的方法。
答案 1 :(得分:0)
对于RESTful Web服务,您认为哪种方法最惯用和最明显?
如果您想要惯用的REST,请考虑如何使用网站。
您可能会以GET /restrictions/{id}
开头,除了有关限制的数据外,还有一种形式-可能嵌入在表示形式中,也许在另一个资源的表示形式中,但可以通过链接使用。然后,您将提交该表单,该表单会将字段捆绑成application/x-www-form-urlencoded
请求中包含的POST
文档。您可以将任何URI用作表单的操作(并因此使用POST请求的target-uri),但是最有用的可能是POST /restrictions/{id}
,因为与HTTP兼容的客户端会知道invalidate先前缓存的/restrictions/{id}
表示形式。
目前,我不打算返回单个限制,默认情况下,所有限制的列表将仅返回未过期的限制。
相同的游戏,但是您可以将uri用作未过期限制列表,而不是将单个限制用于标识符。您的资源模型不必与数据模型匹配。
没有规则说POST
的内容类型必须为application/x-www-form-urlencoded
。您可以发布其他表示形式,包括自己的自定义类型(如果这样会使事情变得更容易)(当然,您必须记录该类型,并且唯一要发送该类型的客户端是已实现该类型的客户端;这样做的最大好处是)标准媒体类型是“免费”获得大量客户。)
PUT
和PATCH
是可以接受的选择。 PUT
(根据推断,可能是PATCH
)实际上并不要求服务器按原样接受请求:
对给定表示形式的成功PUT建议,在同一目标资源上进行后续GET将导致在200(OK)响应中发送等效表示形式。
但是,不能保证这种状态变化是可观察到的,因为目标资源可能在其他后续GET被执行之前由其他用户代理并行作用,或者可能由源服务器进行动态处理。收到。成功的响应仅表示用户代理的意图已在原始服务器处理时达到。
在响应中应遵循一些约定,以区分“我接受了您的陈述”与其他响应。
答案 2 :(得分:0)
REST的少数约束之一是cacheability之一。顾名思义,not an option认为顾名思义,这些限制是,尽管他在这种情况下谈论的是超媒体。尽管一般规则也适用于此。
高速缓存允许本地或中间应用程序(即所谓的高速缓存)在一定时间内存储特定URI的响应,并且如果对同一URI的进一步安全请求命中高速缓存,则高速缓存将为其客户端提供服务存储的响应,而不是将请求路由到服务器。
万一到期,您还需要考虑此类缓存值的到期时间,否则缓存可能仍会为客户提供不应再存在的数据。
HTTP详细讨论了在RFC 7234中进行缓存的问题,响应可能会通过Cache-Control头或Expires头告诉缓存将资源视为新鲜的时间。如果两者都存在,则前者获胜。在示例中,响应标头,例如Cache-Control: max-age=3600
定义了应将响应视为新鲜的最长3600秒,而Expires
应该使用RFC 7231中指定的日期时间格式,例如{{1 }}。
但是,不幸的是,RFC 7234没有讨论客户端如何主动设置这样的指令,因为这被认为是服务器任务。 Expires: Fri, 24 May 2019 05:20:00 CET
确实提供了一些request headers,尽管这些更多地表明客户端将接受或不接受过时的数据,但没有指示服务器设置相应的到期日期。通常,如果客户端不希望某个资源进一步可用,则应Cache-Control
使用该资源。但是,如果您阅读DELETE,您可能会惊讶于它实际上并不保证该资源将被删除。它所说明的是,在成功处理这样的请求之后,将URI到资源的映射删除。是否可以通过不同的URI访问相同的资源不是另一回事。使用某种类型的参数“自定义” DELETE
以在一定时间后删除资源可能适用于您的API,尽管对于其他类型的API可能无法理解,因此通常不建议这样做。>
通过使用DELETE
,有关过期时间戳的信息需要成为资源本身的一部分。通常,此类信息被视为资源的元数据,而不是实际数据的一部分或一部分。因此,尽管这显然是自以为是的做法,但我也不赞成PATCH
。
如果所有other HTTP methods都不符合要求,则应采用POST,因为服务器将根据其自身的语义处理请求。当在同一端点上接收到不同的有效负载时,它可能也会应用不同的启发式方法。如果必须在Web上设计这样的功能,则可以在条目的编辑页面上选择设置到期日期。单击表单的“提交”按钮后,您的浏览器正在执行PATCH
请求,包括到期日期,服务器将根据服务器上可用的某些启发式方法来知道要做什么。即请求中的到期日期字段的可用性可能会指示服务器实际将条目的删除排队,更新目标资源的到期日期元数据,并返回更新的POST
或Cache-Control: max-age=...
标头传入的请求还可以通知缓存有关该时间点之后不传送该资源的缓存响应的信息。
通常,默认情况下,unsafe operations, like POST
, PUT
or DELETE
invalidate cached responses of a target resource是在两个用户对服务器执行可缓存的Expires: ...
请求的情况下,两者之间的中间缓存均不同于另一个用户的中间缓存,并且现在,用户1使原始资源到期,即使在原始服务器上已删除资源的情况下,用户2仍将由目标资源的“他的”中间高速缓存提供服务,因为他的中间高速缓存仍然看到响应足够新鲜,因此可以与存储的响应一起使用2。用户1的缓存中目标URI的缓存响应应该已经被初始GET
请求删除,但是任何最终可缓存的响应也可能已返回更新的缓存头,因此导致在指定时间点到期。因此,重要的是,将缓存的时间值设置为不高到将来,也不要设置得太短,以使缓存变得无用。
对于可能被删除并不能由高速缓存提供服务的关键资源,为了防止上述情况,通常最好指定POST
,这样此类条目就不会被高速缓存进一步存储,并且请求由API /服务器本身直接处理。
总而言之,应该将过期时间点之类的东西视为资源的元数据,而不是主数据。尽管Cache-Control: no-cache
一开始听起来不错,但一段时间后它不支持删除,而另一个API可能会立即执行这样的请求,除了不保证完全删除该资源。 DELETE
作为HTTP的通用工具集,也可以在这里使用其他HTTP操作,例如POST
或PUT
,即使后者“工作”的前提是请求的主体属于资源的实际数据。如果资源不是关键资源,则还应该考虑缓存到设计中,并使用PATCH
或Cache-Control: max-age=...
,或者在资源永远(无论出于何种原因)绝不会过时的情况下使用Expires: ...
给客户的信息。无论使用哪种HTTP方法,您都应该考虑服务器通常如何允许客户端设置此选项。与Web相似,基于表单的解决方案避免了带外信息,因此通常简化了与API的交互,因为所有信息都已经提供或可以通过其他链接获得。