Skip to content

Conversation

@csarven
Copy link
Member

@csarven csarven commented Oct 9, 2020

There is a slight discrepancy in the spec where it recommends:

Clients who want the server to assign a URI of a resource, MUST use the POST request.

and

Servers MUST create intermediate containers and include corresponding containment triples in container representations derived from the URI path component of PUT, POST and PATCH requests.

For example, say /foo/ exists, it is not entirely clear what happens with:

POST /foo/bar/baz/
Link: rel=type LDPC

The expectation would've been along the lines of creating a new container with a server determined name eg. /foo/bar/baz/qux/.

However, that raises a bit of a question as to why bar/baz/ are created where client determines the name.

In order to minimise confusion and to keep things consistent, the PR restricts POST to target only existing resources.

Copy link
Member

@acoburn acoburn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Big 👍 on this. With this change, the difference between creating resources with POST on the one hand and PUT and PATCH on the other becomes much more clear.

@Vinnl
Copy link

Vinnl commented Oct 12, 2020

We've seen confusion the other way around: a developer using solid-client was confused that POST did not create intermediate Containers (in NSS, I think), whereas PUT did.

That does mostly make sense to me. What would the expected course of action when a POST fails because the Container does not exist yet? Is there a situation imaginable in which the failure mode would not immediately be handled by creating the intermediate Containers first? And if so, would that situation occur more often than the one in which you want to create the intermediate Containers anyway?

Anecdotally, I'd expect developers to want the intermediate Containers to usually be created. That use case would be more difficult with the current proposal: they will have to inspect failed requests, PUT the intermediate Containers on fail, and then retry the POST. Alternatively, if intermediate Containers would be created automatically, then developers who would not want that would have to do a HEAD in advance, and not do the POST if the Container does not exist or is not readable.

@bourgeoa
Copy link
Member

I thought that POST was limiting it scope to container creation (folder) for which the server did not choose a name and on the resource (files) side where the server could not create intermediate containers and could choose a resource name.

@RubenVerborgh
Copy link
Contributor

the PR restricts POST to target only existing resources.

👍 for me based on RFC 7231:

4.3.3. POST

The POST method requests that the target resource process the
representation enclosed in the request according to the resource's
own specific semantics.

and

6.5.4. 404 Not Found

The 404 (Not Found) status code indicates that the origin server did
not find a current representation for the target resource or is not
willing to disclose that one exists.

So a 404 means there is no representation, so no "target resource" to perform the processing.

Also, given the second part of the 404 definition, there might be security considerations as well.

Copy link
Member

@justinwb justinwb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 I agree with the other reviewers that this is sensible and clears up some expected behavior between POST and PUT/PATCH

@csarven
Copy link
Member Author

csarven commented Oct 12, 2020

Vincent, Alain:

Note key proposed functional requirements in #160 (comment) which is what some of this stems from:

F2.1: The system shall provide the ability to use client's preferred naming.
F2.2: The system shall provide the ability to use server's preferred naming.

Server and client need to agree on who allocates a URI to a resource:

In RFC 7231:

4.3.3. POST
o Creating a new resource that has yet to be identified by the
origin server; and

Proper interpretation of a PUT request presumes that the user agent
knows which target resource is desired. A service that selects a
proper URI on behalf of the client, after receiving a state-changing
request, SHOULD be implemented using the POST method rather than PUT.

In Solid spec:

Clients who want to assign a URI to a resource, MUST use PUT and PATCH requests.

Clients who want the server to assign a URI of a resource, MUST use the POST request.

When the client believes that a resource with a particular URI does not have a representation, it can use PUT or PATCH to allocate the URI of a resource. POST is an append operation on an existing resource.

In the context of WAC, Write access is required to assign client-specified URI which is typically done with PUT or PATCH. Append access is required for POST. If the container of the target resource of a POST request does not exist, Write access would be required to fulfil the request. POST is not particularly suitable if client wants to specify any part of the URI - but it could try its luck with Slug for the last URI segment.

So then an application should not make requests like POST /foo/bar/baz/ with the intention of creating a resource where 1) client assigns /foo/bar/baz/, and 2) server assigns the last segment eg. qux or qux/.

PUT and PATCH can be used to meet the requirement on client assigning a URI (F2.1), however they can't be used towards server assigning a URI (F2.2). POST is fundamental to having server assign a URI (F2.2).

Note: I did not investigate a hybrid functional requirement like:
F2.3: The system shall provide the ability to use client's and server's preferred naming for different URI segments.

Are there significant use cases?

Which HTTP method to use becomes a simpler question to address once client knows its intentions for URI allocation.

Edit: Does that clarify or address your concerns?

@Vinnl
Copy link

Vinnl commented Oct 13, 2020

@csarven

Are there significant use cases?

I'm merely relaying the confusion we saw with a developer, and which I think served as the trigger for you creating this PR?

The confusion stems, I think, from seeing a POST request not just as a request to create a single Resource, but as a request on a Container to create a Resource. So while they're using POST as a way to indicate that they want the server to create the Resource itself (and to determine the slug it will have inside the given Container), they're also thinking of it as analogous to a PUT on the Container in the sense that they're updating that. (But again, this is my interpretation.)

@csarven
Copy link
Member Author

csarven commented Oct 13, 2020

I've outlined the rationale behind the design so that it can be inspected further. The PR aims to clarify what method to use for different intentions. Systems can only reliably fulfill F2.1 and F2.2, but not something like F2.3. This is arguably a simple and consistent design. The recommendation to developers is that they should keep their implementations within that (until of course F2.3 is acknowledged and spec'd).

@nicolasmondada
Copy link

This addresses the discrepancy and that's great. We should update Inrupt's docs to make sure the behaviour is clear.

In terms of developer experience I agree with @Vinnl that some developers might expect a "Create" function to handle intermediate containers as well, which might not be addressed in the spec given #160 (comment).

In that case we might look into adding a way to do this in the SDK itself.

@RubenVerborgh
Copy link
Contributor

RubenVerborgh commented Oct 14, 2020

In terms of developer experience I agree with @Vinnl that some developers might expect a "Create" function

That's all fine; but that's a client thing then.

Recall that the majority of developer (including myself) will access Solid pods via libraries.

@nicolasmondada
Copy link

Yes, based on @csarven comment it seems like this is not a change that is going to happen on the spec any time soon. If that's the case, we should look into what can be changed on the libraries to make a better developer experience.

@csarven
Copy link
Member Author

csarven commented Oct 14, 2020

Thanks all. I think we are good to go. Here is a bit more info/support on not requiring POST to create nested containers. #160 (comment) concluded that it would require Slug with shared slash semantics in order to create nested containers with POST - it was deemed that system should do either client or server naming in a reliable way. That was also in context of target container existing. Whereas the central example of this PR is about target a resource which wouldn't necessarily have all of the required containers - targeting an non-existent resource. Just to say that these decisions are consistent.

@csarven csarven closed this Oct 14, 2020
@csarven csarven reopened this Oct 14, 2020
@csarven csarven merged commit 4dbfa82 into master Oct 14, 2020
@csarven csarven deleted the edit/post-targets-existing branch December 4, 2020 11:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

8 participants