Skip to content
This repository has been archived by the owner on Apr 13, 2022. It is now read-only.

Is PUT a standard? #198

Open
Otto-AA opened this issue Jul 1, 2019 · 5 comments
Open

Is PUT a standard? #198

Otto-AA opened this issue Jul 1, 2019 · 5 comments

Comments

@Otto-AA
Copy link
Contributor

Otto-AA commented Jul 1, 2019

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
Copy link
Contributor

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
Copy link
Member

acoburn commented Jul 1, 2019

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:

  • What container (if any) will now include the ldp:contains triples pointing to this new resource?
  • Given a PUT to /foo/bar/baz in the absence of /foo and /foo/bar, are those intermediate containers created?
  • If the containers are created, what type of container is created? (ldp:BasicContainer would make sense, but there is no text clarifying that point)
  • If those intermediate resources already exist, what happens if they are not containers?
  • 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?
  • How does Create-on-PUT square with the requirement to use If-Match (or similar) conditional headers with PUT?

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
Copy link
Contributor Author

Otto-AA commented Jul 1, 2019

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

@michielbdejong
Copy link
Contributor

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
Copy link
Member

acoburn commented Jul 2, 2019

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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants