REST 问题:PUT 一种表示形式,GET 一种不同的表示形式?

发布于 2024-08-15 05:09:02 字数 1801 浏览 5 评论 0原文

问题的简短版本:
特定 URI 处的“GET”是否需要与该 URI 的“PUT”内容相匹配?

我认为不需要。原因如下:

鉴于资源是理论上客户端不可知的抽象事物,因此当我们执行 PUT 时,我们必须仅发送表示形式。基于对 RFC2616 的梳理,似乎并没有完全指定这对于具有许多(可能是无限的?)表示的资源意味着什么,但这是我的想法;如果您同意,请告诉我:

我的期望是,如果我将表示形式放入资源,则该 URI 处的资源的所有其他表示形式应根据需要保持一致(可能会更新)。换句话说,您告诉资源“使用此表示来重新定义自己”。

因此,我应该能够这样做:

PUT /resources/foo/myvacation
内容类型:image/jpg
...

并跟进:

GET /resources/foo/myvacation
接受:图片/png
...

并以不同的格式获取 myvacation 的更新版本(假设服务器知道如何执行此操作)。由此推断,这个复合原子“图像+元数据”PUT 也应该是合法的:

PUT /resources/foo/myvacation
内容类型:多部分/表单数据

内容处置:表单数据;名称=“文档”
内容类型:image/jpg
[..]
内容配置:表单数据;名称=“iptc”
内容类型:应用程序/iptc
[..]
内容配置:表单数据;名称=“exif”
内容类型:应用程序/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
内容类型:应用程序/exif
[..]

PUT 的描述如下:

PUT 方法请求将所包含的实体存储在提供的 Request-URI 下。

对我来说,这相当反 REST,除非您以非常自由的方式。我的解释是“PUT 方法请求根据所包含实体的表示在提供的请求 URI 处创建或更新资源。”

后来,我们得到:

POST 和 PUT 请求的根本区别体现在 Request-URI 的不同含义上。 POST 请求中的 URI 标识将处理所包含实体的资源。该资源可能是数据接受进程、某些其他协议的网关或接受注释的单独实体。相反,PUT 请求中的 URI 标识请求中包含的实体——用户代理知道 URI 的用途,并且服务器不得尝试将请求应用于其他资源。

我们需要类似地创造性地阅读它,但这里的关键位是“知道 URI 的意图”和“应用请求”。

因此,对我来说,在给定 URI 上 GET 返回的表示不一定必须与 PUT 到给定 URI 的表示相同,它只需保持一致即可。

是真是假?

Short version of the question:
Does "GET" at a particular URI need to match what was "PUT" to that URI?

I think not. Here's why:

Given that a resource is an abstract thing that is theoretically unknowable by the client, when we do a PUT, we must be only sending a representation. Based on combing over RFC2616, it doesn't seem entirely specified as to what that means for a resource that has many (potentially infinite?) representations, but here are my thoughts; please tell me if you agree:

My expectation is that if I PUT a representation to a resource, all other representations of the resource at that URI should be kept consistent (potentially updated) as necessary. In other words, you're telling the resource "use this representation to redefine yourself".

Thus, I should be able to do this:

PUT /resources/foo/myvacation
Content-type: image/jpg
...

And follow up with this:

GET /resources/foo/myvacation
Accept: image/png
...

and get the updated version of myvacation in a different format (assuming the server knows how to do that). Extrapolating from that, this composite atomic "image + metadata" PUT should also be legal:

PUT /resources/foo/myvacation
Content-type: multipart/form-data

Content-disposition: form-data; name="document"
Content-type: image/jpg
[..]
Content-disposition: form-data; name="iptc"
Content-type: application/iptc
[..]
Content-disposition: form-data; name="exif"
Content-type: application/exif
[..]

And then, because server-side content negotiation (RFC2616 section 12.1) can take place based on just about anything, we can default to the "document" content for this:

GET /resources/foo/myvacation
Content-type: image/jpg
[..]

or if you believe as I do that RFC 2396 section 3.4 "The query component is a string of information to be interpreted by the resource." means that a URI with a query string refers to the same resource as a URI without a query string (and is isomorphic with just sending application/x-form-urlencoded data to the resource), then this should also be legal:

GET /resources/foo/myvacation?content=exif
Content-type: application/exif
[..]

The description of PUT says:

The PUT method requests that the enclosed entity be stored under the supplied Request-URI.

To me, this is fairly anti-REST, unless you read it in a very liberal manner. My interpretation is "The PUT method requests that a resource be created or updated at the supplied Request-URI based on the representation of the enclosed entity."

Later on, we get:

The fundamental difference between the POST and PUT requests is reflected in the different meaning of the Request-URI. The URI in a POST request identifies the resource that will handle the enclosed entity. That resource might be a data-accepting process, a gateway to some other protocol, or a separate entity that accepts annotations. In contrast, the URI in a PUT request identifies the entity enclosed with the request -- the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource.

We need to similarly read this creatively, but the key bits here are "knows what URI is intended" and "apply the request".

So, to me the representation returned by GET at a given URI does not necessarily have to be the same representation that was PUT to the given URI, it just has to be consistent.

True or false?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦幻的味道 2024-08-22 05:09:02

基于内容协商可以从同一 URI 返回不同表示的事实,我非常确定您 PUT 的内容不必与您检索的内容相同。

Based on the fact that content negotiation can return different representations from the same URI, I am quite sure that what you PUT does not have to be the same as what you retrieve.

云柯 2024-08-22 05:09:02

你的假设是正确的。 GET 不一定要返回与 PUT 相同的表示,但它必须是相同的资源

我目前正在开发一个 Web 应用程序,它将以 XHTML、JSON 或自定义 XML 方言的形式返回任何资源,具体取决于您在内容协商标头中要求的内容。因此浏览器默认会看到 HTML。其他HTTP客户端,包括XMLHttpRequest,可以获取JSON等。它们都是同一 URI 上同一资源的表示。

同样,我们的应用程序将接受任何受支持格式的 PUT 或 POST(取决于相关特定资源或集合的语义。)

Your assumptions are correct. The GET doesn't necessarily have to return the same representation as what you PUT, but it does have to be the same resource.

I'm currently working on a web application that will return any resource as XHTML, JSON, or a custom XML dialect, depending on what you ask for in the content negotiation headers. So a browser will see the HTML by default. Other HTTP clients, including XMLHttpRequest, can get the JSON, and so on. They are all representations of the same resource at the same URI.

Likewise, our application will accept a PUT or POST in any of the supported formats (subject to the semantics of the particular resource or collection in question.)

若无相欠,怎会相见 2024-08-22 05:09:02

我同意其他答案,即您放置的资源不需要与您稍后获取的资源相同。我想围绕这个领域向这个问题添加一些我的经验。

依赖内容协商时您需要非常小心。要做到正确是非常棘手的,如果不正确会导致严重的用户问题。让我们做一个基于图像的例子...

如果Alice以原始格式放置图像,那么鲍勃可以获取jpeg格式的图像(通过服务器端raw->jpeg转换),而Alice可以以jpeg格式获取图像原始格式;没问题。但是,如果 Bob PUT 是 jpeg,则无法恢复到 Alice 的原始格式。对于度假照片来说,缺乏对称变换可能不是什么大问题,但对于医学图像来说,那就是大问题了。

缺乏对称变换的另一个问题是在一个有模式而另一个没有模式的表示中。在这种情况下,在服务器端,您最终会制定如何在它们之间进行转换的约定。但是,当您处理的文档的模式会随着时间的推移而变化并且超出您的控制时,您就会遇到大问题。每次架构更改时,您都必须更新新架构形状的所有转换,同时仍然支持使用旧架构的资源。除了少数有限的情况外,内容谈判很快就会变得比其价值更麻烦。可以管理的领域之一是您是否完全控制资源表示及其底层架构。另一个问题是资源格式是否是标准的,以及是否可以在不同格式之间进行对称转换。

I agree with the other answers that resource that you PUT is not required to be the same as the one that you later GET. I wanted to add some of my experience to this question around this area.

You need to be very careful when relying on content-negotiation. It is very tricky to get right and if you don't get it right leads to nasty user problems. Let's do an example based on images...

If Alice PUTs an image in a raw format, then Bob can GET the image as a jpeg(through a server side raw->jpeg transform), and Alice can GET the image in a raw format; No problems. However, if Bob PUTs a jpeg, then there is no way to get back to the raw format for Alice. In the case of vacation photos the lack of symmetric transforms may not be a big deal, but in medical images it would be.

Another area where the lack of symmetric transforms bites you is in representations where one has a schema and the other does not. In this case, on the server side you end up making conventions for how to transform between them. But you get into big problems when you are dealing with documents with schemas that change over time and are out of your control. Everytime the schema changes you have to update all of your transforms for the new schema shape, while still supporting resources using the old schema. Content negotiation quickly becomes more trouble than its worth except for a few limited circumstances. One of the areas where it can be manageable is if you fully control the resource representation and its underlying schema. Another area is if the resource formats are standards and its possible to make symmetric transformations between the different formats.

北渚 2024-08-22 05:09:02

如果您正在进行转换,那么您的 PUT 不是您的 GET 是有道理的,所以我不明白为什么这是一个问题。

但是,如果您 PUT 具有某些信息的用户,那么当您使用 GET 时,它应该检索该人,就像当我放置第四张度假照片时,当我调用 GET 我期望这张照片,但它可能会通过转换为不同的格式进行转换,或者进行其他一些转换,但是,如果我得到第五张照片,那就是一个问题。

If you are transforming then it would make sense that what you PUT is not what you GET, so I don't see why it is a problem.

But, if you PUT a user with certain information, then when you use GET then it should retrieve that person, just as, when I put my 4th vacation photo, when I call GET I expect that photo, but it may be transformed by converting to a different format, or have some other transforms, but, if I get the 5th photo instead, then that is a problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文