英文:
What are the disadvantages custom actions in "REST" endpoints?
问题
我必须承认,长时间以来,我一直在努力充分理解RESTful资源端点的优缺点。
我经常听说RESTful API应该将一切都视为资源,而不是发送消息或命令。
例如,假设我想要能够激活
或停用
一个像account
这样的资源。尽管大多数我所读的东西都强烈倾向于以下端点:
PUT accounts/1/activate
PUT accounts/1/deactivate
我觉得我可能误解了一些重要的东西,即使在做应用程序很长时间之后,因为RESTful的方法似乎是这样的:
POST accounts/1/activation
DELETE accounts/1/activation
或类似的。甚至有同事更喜欢这样的方式:
PUT accounts/1?activate=true
PUT accounts/1?deactivate=true
并在update
动作中,只是一个长长的if ... then
链,查找标志以确定要“做”什么。
if params[:activate]
# 进行一些激活操作
对我来说,后者的方式似乎并不有利,我真的很想了解我可能漏掉了什么。
“命令”方法在我看来更有优势,因为它清晰地表明了端点的目的,在服务器上分离了行为,并且在许多情况下消除了客户端知道要传递哪些属性以完成任务的需要。然而,我非常乐意听到这种方法的劣势和后者方法的优势。请有人给我一些启示吗?
英文:
I have to admit, I've struggled for a long time to fully grasp the advantages and disadvantages of RESTful resource endpoints.
I've often heard that RESTful APIs should consider everything as a resource, and NOT to send messages, or commands.
For example, say I wanted to be able to activate
or deactivate
a resource like account
. My strong inclination, against most of what I've read is to have endpoints that looks like:
PUT accounts/1/activate
PUT accounts/1/deactivate
I feel like I'm misunderstanding something important even after a long time making apps, because it seems the RESTful approach would be something like:
POST accounts/1/activation
DELETE accounts/1/activation
Or something similar. I've even had a colleague who preferred something like:
PUT accounts/1?activate=true
PUT accounts/1?deactivate=true
And inside the update
action, there would just be a long if ... then
chain looking for flags to figure out what to "do".
if params[:activate]
# do some activation stuff
The latter approaches just don't seem advantageous to me, and I'd really like to understand what I'm missing.
The "command" approach has more advantages to my mind, because it makes it clear what the purpose of the endpoint is, separates behavior out on the server, and in many cases obviates the need for the client to know what attributes to pass in order to get the job done. I am however very open to hearing disadvantages to this and advantages of the latter approaches.
Could someone enlighten me please?
答案1
得分: 1
I have to admit, I've struggled for a long time to fully grasp the advantages and disadvantages of RESTful resource endpoints.
不得不承认,我花了很长时间才完全理解RESTful资源端点的优缺点。
Not your fault - the literature sucks.
这不是你的错 - 文献很糟糕。
The latter approaches just don't seem advantageous to me, and I'd really like to understand what I'm missing.
后一种方法对我来说似乎没有优势,我真的想了解我漏掉了什么。
My guess: what you are missing is that HTTP is an application protocol - it transfers and manipulates "documents" (resources) over a network. See Webber 2011.
我的猜测是:你所忽视的是HTTP是一种应用协议 - 它在网络上传输和操作“文档”(资源)。请参阅Webber 2011。
Useful work is a side effect of manipulating resources.
有用的工作是操作资源的副作用。
For example:
例如:
PUT /accounts/1/activate
不意味着“激活账户1”。它的意思是“用包含的有效载荷替换/accounts/1/activate的表示” - 激活账户是副作用。
Designing a resource model is thinking about what side effects we need, and which alternative offers us the best tradeoffs.
设计资源模型是考虑我们需要什么副作用,以及哪种替代方案为我们提供最佳权衡。
Since not everybody gives the same weights to the different trade offs available, you get a lot of different ideas about which resource model is the best fit.
由于不是每个人都对不同的权衡因素给予相同的重视,所以对于哪种资源模型最适合存在很多不同的观点。
One of the tradeoffs to consider in designing your resource model: how much information are you giving to the HTTP application itself?
在设计您的资源模型时要考虑的权衡之一是:您向HTTP应用程序本身提供了多少信息?
We certainly could design a resource model where everything happens via
当然,我们可以设计一个资源模型,在其中一切都通过
POST /
POST /
or everything happens via
或者一切都通过
PUT /{someUUID}
PUT /{someUUID}
but neither of those approaches correctly identify safe requests, or help caches to understand whether to invalidate a previously stored response, or tell our operators reading the access logs anything useful about how the system is being used, they don't simplify our concerns with access control, and so on.
但这两种方法都不能正确识别安全请求,也不能帮助缓存了解是否要使先前存储的响应无效,或者告诉我们的操作员阅读访问日志有关系统使用情况的有用信息,它们不能简化我们对访问控制的担忧等等。
(I'll note in passing that while HTTP cares a lot about whether the resources in your model understand messages the same way everybody else on the internet understands them, what HTTP does not care about at all is how easy/difficult your resource model is to implement.)
(我顺便指出,虽然HTTP非常关心您的模型中的资源是否以与互联网上的其他人相同的方式理解消息,但HTTP根本不关心您的资源模型是多么容易/困难来_实施_。)
We could design our resource model such that the activate account side effect is induced by editing the /accounts/1/activate
document, OR we could instead activate that same side effect by editing the /accounts/1
document. Both choices are "fine," but they have different caching implications to consider.
我们可以设计我们的资源模型,以便通过编辑/accounts/1/activate
文档来引发激活账户的副作用,或者我们可以通过编辑/accounts/1
文档来激活相同的副作用。这两种选择都“可以”,但它们有不同的缓存影响需要考虑。
英文:
> I have to admit, I've struggled for a long time to fully grasp the advantages and disadvantages of RESTful resource endpoints.
Not your fault - the literature sucks.
> The latter approaches just don't seem advantageous to me, and I'd really like to understand what I'm missing.
My guess: what you are missing is that HTTP is an application protocol - it transfers and manipulates "documents" (resources) over a network. See Webber 2011.
Useful work is a side effect of manipulating resources.
For example:
PUT /accounts/1/activate
doesn't mean "activate account 1". What is means is "replace your representation of /accounts/1/activate with the included payload" - activating the account is the side effect.
Designing a resource model is thinking about what side effects we need, and which alternative offers us the best tradeoffs.
Since not everybody gives the same weights to the different trade offs available, you get a lot of different ideas about which resource model is the best fit.
One of the tradeoffs to consider in designing your resource model: how much information are you giving to the HTTP application itself?
We certainly could design a resource model where everything happens via
POST /
or everything happens via
PUT /{someUUID}
but neither of those approaches correctly identify safe requests, or help caches to understand whether to invalidate a previously stored response, or tell our operators reading the access logs anything useful about how the system is being used, they don't simplify our concerns with access control, and so on.
(I'll note in passing that while HTTP cares a lot about whether the resources in your model understand messages the same way everybody else on the internet understands them, what HTTP does not care about at all is how easy/difficult your resource model is to implement.)
We could design our resource model such that the activate account side effect is induced by editing the /accounts/1/activate
document, OR we could instead activate that same side effect by editing the /accounts/1
document. Both choices are "fine", but they have different caching implications to consider.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论