Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarify requests including content; container creation; omit slug targetting auxiliary #660

Merged
merged 4 commits into from
Jun 3, 2024

Conversation

csarven
Copy link
Member

@csarven csarven commented May 27, 2024

Preview | Diff


Summary:

  • This PR clarifies the Solid Protocol to enhance internal consistency and avoid conflicting implementations.
  • Requests without a Content-Type header, particularly when the request message includes content, can potentially confuse servers and cause issues with existing or future implementations.
  • PUT and PATCH requests can be used to create a container if the target URI ends with a slash (/) and the message content is empty, even without the Content-Type or Link headers indicating an LDP container.
  • POST requests to create a container essentially depends on the Link header indicating an LDP container (or possible alternative considerations that were contemplated in the past).

This PR makes a correction class 3 change:


A more high level explanation of the changes:

Servers conforming to the Solid Protocol can create a container using PUT and PATCH requests without the Content-Type header, provided that the message content is empty. Similarly, LDP server conformance generally requires the use of a Content-Type header when there is message content, and the behaviour without a Content-Type header is unspecified.

Where a server accepts a POST request with a Link header indicating the LDP container type but without a Content-Type header, the server could potentially conform to the Solid Protocol (given changes to the specification) but no conformance to LDP is unspecified.

The use case for servers assigning a URI for containers (e.g., /{uuid}/) with POST requests is generally uncommon.

To avoid potential conflicting requirements across specifications, it would be preferable not to specify that POST requests can create containers, regardless of the Content-Type header being omitted when message content is empty. LDP servers are not required to create containers that way either. This can make sure that Solid servers remain compatible with LDP servers without necessarily restricting container creation.


Background drawing from HTTP specs, LDP, and Solid Protocol specs:

In https://www.rfc-editor.org/rfc/rfc9110#section-9.3.3-1 :

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

The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message content.

Server's expectation is that Content-Type is included in the request (irrespective to resource semantics).

In https://www.rfc-editor.org/rfc/rfc9110#section-8.3-5 :

A sender that generates a message containing content SHOULD generate a Content-Type header field in that message unless the intended media type of the enclosed representation is unknown to the sender. If a Content-Type header field is not present, the recipient MAY either assume a media type of "application/octet-stream" ([RFC2046], Section 4.5.1) or examine the data to determine its type.

At the moment, the Solid Protocol tries to be strict on this point https://solidproject.org/ED/protocol#server-content-type-missing by requiring Content-Type, and generally on the basis of discouraging heuristics to figuring out representation's type ( https://www.rfc-editor.org/rfc/rfc9110#section-8.3-6 ). LDP is however more relaxed on this (see below)

While LDP does not generally describe or prohibit an interaction model to create a container ( https://www.w3.org/TR/ldp/#ldpc-post-createrdf ) with POST without Content-Type:

5.2.3.4 LDP servers that successfully create a resource from a RDF representation in the request entity body MUST honor the client's requested interaction model(s). If any requested interaction model cannot be honored, the server MUST fail the request.

If the request header specifies a LDPC interaction model, then the server MUST handle subsequent requests to the newly created resource's URI as if it is a LDPC.
This specification does not constrain the server's behavior in other cases.

it does explain the process to create LDP-RSs where it also includes the Content-Type header, emphasis on "creation of LDP-RS", which includes all LDP container types ( https://www.w3.org/TR/ldp/#ldpc-isldpr ):

https://www.w3.org/TR/ldp/#ldpc-post-turtle :

5.2.3.5 LDP servers that allow creation of LDP-RSs via POST MUST allow clients to create new members by enclosing a request entity body with a Content-Type request header whose value is text/turtle [turtle].

https://www.w3.org/TR/ldp/#ldpc-post-jsonld :

5.2.3.14 LDP servers that allow creation of LDP-RSs via POST MUST allow clients to create new members by enclosing a request entity body with a Content-Type request header whose value is application/ld+json [JSON-LD].

Essentially LDP does not specify conformance for POST requests without Content-Type and without message content. No interoperability between servers and clients specified. It doesn't even specify for PUT.

LDP also notes the possibility that servers might infer the content type (when the Content-Type header is missing) by sniffing ( https://www.w3.org/TR/ldp/#ldp-http-content-sniffing ), which is also summarised in #70 (comment) :

6.2.6 When the Content-Type request header is absent from a request, LDP servers might infer the content type by inspecting the entity body contents ([RFC7231] section 3.1.1.5).

While content type sniffing is discouraged in Solid Protocol ( #70 (comment) ) the context of the discussion and the requirements that lead to it in the Solid Protocol was for requests including a message. It is important to maintain that case. However, when the request does not include content, and the request semantics does not require the Content-Type header, then it is possible to have a valid request without the Content-Type header.


Solid Protocol defines a container as a hierarchical collection of resources ( https://solidproject.org/ED/protocol#container-resource ) - not limited to LDP:

A container resource is a hierarchical collection of resources that contains other resources, including containers.

but the described normative behaviours correspond to LDP Basic Container ( https://solidproject.org/ED/protocol#server-basic-container ):

The representation and behaviour of containers in Solid corresponds to LDP Basic Container and MUST be supported by server.

With resource type heuristics ( https://solidproject.org/ED/protocol#resource-type-heuristics ) in Solid Protocol, it is possible to create a container without a Content-Type header if the request's target URI ends with a slash (/):

When creating new resources, servers can determine a target URI’s type by examining the URI path ending (URI Slash Semantics).

https://solidproject.org/ED/protocol#uri-slashes-hierarchical-identifier :

The slash (/) character in the URI path indicates hierarchical relationship segments, and enables relative referencing [RFC3986]. The semantics of the slash character is shared by servers and clients. Paths ending with a slash denote a container resource.

The ways in which PUT, PATCH, and POST can be used to create containers and URI assignment are based on determining the request semantics from HTTP request method ( https://www.rfc-editor.org/rfc/rfc9110#section-9 ). Summarised in:

https://solidproject.org/uri-allocation-put-patch :

Clients can use PUT and PATCH requests to assign a URI to a resource.

https://solidproject.org/uri-allocation-put-patch :

Clients can use POST requests to have the server assign a URI to a resource.

https://solidproject.org/ED/protocol#server-post-target-not-found

When a POST method request targets a resource without an existing representation, the server MUST respond with the 404 status code.

Essentially only PUT and PATCH can be used to create a container in such requests.


Additional background on determining resource type was outlined here #160 (comment) , based on use cases borrowed from LDP where 1) the requirements building on from HTTP (as opposed to LDP), and 2) aiming to not conflict with LDP and be compatible as needed.

As it currently stands in the Solid Protocol, the only interoperable way for Solid Protocol to create a container with POST is by:

C3.1: request including Link header with rel="type" targeting a valid LDP container type [F1.2].

where it only meets the functional requirement:

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

The Slug header is not required in Solid Protocol or LDP, and it is deemed to be unreliable or problematic ( #621 ).

Copy link
Member

@CxRes CxRes left a comment

Choose a reason for hiding this comment

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

I would have ideally preferred two commits for this, but it is not a big deal.

I have suggested changes where the requirement on the client is stricter than the server wrt content-type field (thereby server need not be obligated to match content-type with content), in keeping with Postel's law.

ED/protocol.html Outdated Show resolved Hide resolved
ED/protocol.html Outdated Show resolved Hide resolved
@CxRes
Copy link
Member

CxRes commented May 27, 2024

PS: the HTTP Police aka HTTPWG has ruled that it is not header but field or header field. I guess we'll need a separate PR for that!

@csarven csarven force-pushed the fix/messages-with-content-container-creation branch from c093c7a to 0e820c8 Compare May 28, 2024 08:13
@csarven
Copy link
Member Author

csarven commented May 28, 2024

Thanks for the heads up. The specification already uses "header field" (as well as "field value") in some parts so I guess some instances were missed. I went ahead and made that change to clarify in 9390154 and it is integrated in this PR.

@csarven csarven added this to the Release 0.11.0 milestone May 28, 2024
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.

Overall, this is a good clarification.

Also +1 on removing the link header requirement on POST-to-create-container operations.

Copy link
Contributor

@TallTed TallTed left a comment

Choose a reason for hiding this comment

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

Editorial tweaks for clarity and consistency

ED/protocol.html Outdated Show resolved Hide resolved
ED/protocol.html Outdated Show resolved Hide resolved
ED/protocol.html Outdated Show resolved Hide resolved
ED/protocol.html Outdated Show resolved Hide resolved
csarven and others added 2 commits May 30, 2024 22:37
Co-authored-by: Ted Thibodeau Jr <tthibodeau@openlinksw.com>
csarven added a commit that referenced this pull request Jun 1, 2024
Part of missed #660 (comment)

Co-authored-by: Rahul Gupta <CxRes@users.noreply.github.com>
@csarven csarven merged commit e4fdfe7 into main Jun 3, 2024
@csarven csarven deleted the fix/messages-with-content-container-creation branch June 3, 2024 10:30
csarven added a commit that referenced this pull request Jun 3, 2024
csarven added a commit that referenced this pull request Jun 3, 2024
Part of missed #660 (comment) in commit 9390154

Co-authored-by: Rahul Gupta <CxRes@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Relax mandatory content-type header field requirement for PUT, POST with no content body.
6 participants