solid / solid-spec

Solid specification draft 0.7.0
Creative Commons Zero v1.0 Universal
1.13k stars 103 forks source link

Is PUT a standard? #198

Open Otto-AA opened 5 years ago

Otto-AA commented 5 years ago

The spec currently states:

An alternative (though not standard) way of creating new resources is to use HTTP PUT.

I am not sure how we should interpret this statement: Does it (1) mean that it is not part of the api standard yet, or (2) that it is not usual to use it but it's part of the standard?

I think this description is a bit ambiguous, so from my point of view it would make sense to rephrase it to (1) "An alternative (though currently not part of the solid-spec) way of creating new resources is to use HTTP PUT." or (2) "An alternative (though not usual) way of creating new resources is to use HTTP PUT."

michielbdejong commented 5 years ago

yeah, PUT and POST are definitely both supported, and POST /foo/ with a slug header of 'bar' should have the same effect as PUT /foo/bar.

Server implementers should be careful that they don't allow POST if PUT is not allowed or vice versa, so basically both should require permissions on both the container and the resulting resource, see https://github.com/michielbdejong/web-access-control-spec/blob/verbs-modes-table/README.md#relation-between-http-verbs-and-modes-of-access

acoburn commented 5 years ago

From the perspective of LDP, servers may allow creation of resources via POST or PUT (or some other method):

4.2.3 Clients can create LDPRs via POST (section 5.2.3 HTTP POST) to a LDPC, via PUT (section 4.2.4 HTTP PUT), or any other methods allowed for HTTP resources.

LDP, however, does not specify the exact behaviors of Create-on-PUT, for example:

IMO, these behaviors (if Create-on-PUT is to be supported at all) would be helpful to clarify at the level of the Solid specification, because a server implementation will need to make decisions on these sorts of issues. The role of the specification, here, is to make sure that all implementations make the same (or at least not incompatible) decisions in such cases. That way clients will have a consistent interface on which to operate.

The simplest option is to disallow Create-on-PUT, stating that creation happens only with POST, but the simplest option is not necessarily the best option: that is a discussion to be had among the specification editors.

Otto-AA commented 5 years ago

Ok thanks for your answers. I've created a PR to make it more clear which of these two interpretations is meant.

michielbdejong commented 5 years ago

Great points @acoburn, indeed those things are all defined at the Solid level and not at the LDP level:

What container (if any) will now include the ldp:contains triples pointing to this new resource?

After a PUT to https://example.com/some/path/to/a/resource, the newly created resource will be at that URL, and will be ldp-contained by https://example.com/some/path/to/a/, in general, remove the longest /-less suffix. Note that PUT to a URI that ends in a / makes no sense (maybe we should also add that in #201).

Given a PUT to /foo/bar/baz in the absence of /foo and /foo/bar, are those intermediate containers created?

yes (see rest-api.md, section about mkdir -p)

If the containers are created, what type of container is created? (ldp:BasicContainer would make sense, but there is no text clarifying that point)

Indeed not clarified at the LDP level, but at the Solid level it is: "Resources are grouped in directory-like Containers (currently conforming to the LDP Basic Container spec)"

If those intermediate resources already exist, what happens if they are not containers?

That's a conflict error (although I think you're right that that's not explicitly documented!) Created #201 about this.

If intermediate containers are created, what happens in the case of conflict in an eventually consistent back-end store with a high level of concurrency?

Now that I think about that, I don't think I understand how you could ever implement Solid on top of an eventually consistent backend-store. But specifically about the comparison between POST and PUT, you could copy the trick that POST uses, and PUT to a URL that ends in a long random string. That way it becomes astronomically unlikely that two concurrent PUTs would result in a network split.

How does Create-on-PUT square with the requirement to use If-Match (or similar) conditional headers with PUT?

You would use If-None-Match: *, meaning only create the resources if no ETags match, i.e. if the resource does not exist. The remoteStorage spec does this too. It's a MAY there because we don't want to tell clients what to do, if they mess up then it's their own problem. Is it a requirement on clients in LDP or in Solid to use If-Match (or similar) conditional headers with PUT?

acoburn commented 5 years ago

Thanks @michielbdejong

Is it a requirement on clients in LDP or in Solid to use If-Match (or similar) conditional headers with PUT

In LDP (section 4.2.4.5), If-Match on PUT is listed at the SHOULD level

LDP servers should require the HTTP If-Match header and HTTP ETags to detect collisions.

In Trellis, I have a configuration setting that can be turned on to enforce this or not (enforcing it is great in theory but not very practical for many general use cases). By default, this is not enforced.