solid / specification

Solid Technical Reports
https://solidproject.org/TR/
MIT License
471 stars 42 forks source link

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

Closed csarven closed 4 weeks ago

csarven commented 1 month ago

Preview | Diff


Summary:

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 https://github.com/solid/specification/issues/70#issuecomment-536684883 :

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 ( https://github.com/solid/specification/issues/70#issuecomment-547924171 ) 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 https://github.com/solid/specification/pull/160#issuecomment-635932724 , 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 ( https://github.com/solid/specification/pull/621 ).

CxRes commented 1 month ago

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 commented 1 month ago

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 https://github.com/solid/specification/commit/93901540e7efd22ce48692deb4298df30ea4c2a7 and it is integrated in this PR.