Specification: Specify POST

Created on 4 Nov 2019  路  44Comments  路  Source: solid/specification

In context of LDP, POST is used to add resources to containers ie. POST to LDPC resource optionally using the Slug header and Link for interaction model(s).

What should be the POST behaviour to target resources that are not LDPCs?

```
POST /foo/bar
````

If the target resource exist, what should happen?

If the target resource doesn't exist, what should happen?

What are the effects of interaction model(s) (LDPR and/or LDPC) used in request's Link header?

How should requests to create a resource with the LDP-NR interaction model get handled?

What are the effects without an interaction model?

Ecosystem resource access

Most helpful comment

If we just have the container URL, and all manipulations are on that, it is much easier, you know exactly what rules apply.

So we agree. Shouldn't design to have representations with different access modes.

The key difference is that PUT expects to replace everything, whereas POST doesn't.

I meant beyond the literal difference between POST and PUT. If POST HTML is spec'd to act like a write/replace operation, it will generally have the same affect as PUT anything to write/replace. And so they both have to deal with not touching the RDF/server-managed triples.

All 44 comments

I am happy to adjust the Trellis behavior to whatever gets specified here, but I will describe the current behavior in the context of your questions.

What should be the POST behaviour to target resources that are not LDPCs?

If the target resource exist, what should happen?

Respond with 405 Method Not Allowed

What should be the POST behaviour to target resources that are not LDPCs?

If the target resource doesn't exist, what should happen?

Respond with 404 Not Found

What are the effects of interaction model(s) (LDPR and/or LDPC) used in request's Link header?

For a successful request (i.e. /foo/bar is an LDP-C) the link header would define the interaction model for the newly created resource. A successful response will echo that interaction model back to a client in a Link header.

How should requests to create a resource with the LDP-NR interaction model get handled?

The body of the request (the raw byte stream) is used to create the new resource at the location hinted at with a Slug header (or at a server-generated location in the absence of a Slug header). A successful request will respond with the following:

  • A Location header pointing to the new resource's URL
  • A Link header with the interaction model of the new resource (i.e. LDP-NR)
  • A Link header pointing to the location of the corresponding LDP-RS description of this LDP-NR (every LDP-NR has an LDP-RS description)

What are the effects without an interaction model?

The server uses implementation-specific heuristics to assign an interaction model. I.e. if the Content-Type request header is an RDF serialization that is parseable by the server as RDF, the new resource is assigned an LDP-RS interaction model; otherwise, the resource is assigned an LDP-NR interaction model.

Raised by @ericprud ( https://gitter.im/solid/specification?at=5dcd102092a84f79fe6477bb ):

Should a 201 response payload include statements related to adding a new resource to a container eg. mention other created resources (nested containers) and the relations between them, metadata, associated shapes..

Indeed, LDP defines POST only for creation, which has always baffled me, since "Annotation existing documents; [...] Extending a document during authorship." has been part of POST semantics since the dawn of ages. Especially with RDF, where append is clearly defined in terms of RDF Merge (which is basically just a union where you relabel blank nodes so that they don't crash). I think it is important that we do better than LDP in this area, because POST-to-append is very common practice (though, I might have lost touch with devs). Moreover, it seems to me that POST operations will only need acl:Append privileges (with minor exceptions), as they all append operations, right?

So, my proposal follows somewhat like the setup of #40 :

  • Container

    • Creation: MUST be supported with Slug as defined elsewhere, with If-None-Match: * also supported.

    • Update: MUST be supported, where the payload is appended to the container representation using RDF Merge but ignores server managed triples. For a HTML representation (#69), it will replace the HTML, but not the RDF, in which case acl:Write is required.

    • SPARQL Support: Currently discussed in #125 .

  • RDF source

    • Creation: MUST be supported with Slug as defined elsewhere, with If-None-Match: * also supported.

    • Update: MUST be supported, where the payload is appended to the representation using RDF Merge.

    • SPARQL Support: Currently discussed in #125 .

  • Non-RDF Source:

    • Creation: MUST be supported with Slug as defined elsewhere, with If-None-Match: * also supported.

    • Update: MAY be supported if the server is able to support an append operation on the media type.

  • ACL resources

    • Like RDF sources, but with acl:Control required instead of acl:Append.

For a HTML representation (#69), it will replace the HTML, but not the RDF, in which case acl:Write is required.

By "RDF", are you referring to server-managed triples or the other representations of the same resource?

Why [POST] "replace" exactly? RDF Source or Non-RDF Source Update cases use append.

Requiring different access modes, depending on Content-Type and optionally Link headers, seems awkward. Is there even a way to set a policy like that in ACL? Otherwise, setting acl:Write on the container (and by default its members) just so that it can be updated in HTML seems problematic.

Besides those concerns, I agree with the setup.

For a HTML representation (#69), it will replace the HTML, but not the RDF, in which case acl:Write is required.

By "RDF", are you referring to server-managed triples or the other representations of the same resource?

I was thinking the entire RDF representation, to easily distinguish in a non-LDPy way...

Why [POST] "replace" exactly?

Simply because POST is fluffily enough defined to be used this way without breaking a spec... :-)

RDF Source or Non-RDF Source Update cases use append.

Requiring different access modes, depending on Content-Type and optionally Link headers, seems awkward. Is there even a way to set a policy like that in ACL? Otherwise, setting acl:Write on the container (and by default its members) just so that it can be updated in HTML seems problematic.

Yeah, I agree, it is awkward. My thinking is that you would most probably usually replace the HTML representation (#69 ), editions is managed client side, so you GET the resource, make your edits and replace the resource... So, you'd want PUT really, but since you can never replace the whole representation because of the server-managed triples, you can't have PUT, so I gave POST this role instead...

If we resolve that you can replace an HTML representation through PUT (#40) without touching the RDF or at least the server managed triples, then this can go. I'm not sure which is the lesser of evils.

I was thinking the entire RDF representation, to easily distinguish in a non-LDPy way...

I don't understand. Can you please clarify?

Yeah, I agree, it is awkward.

If representations have their URLs, it would be possible to set different access modes. However, the direction we are taking sets the policy on the effective request URI which applies to all representation URLs.

Simpler to keep all POST updates to append.

I'm not sure which is the lesser of evils.

I don't see the key difference. Both approaches essentially attempt to replace a container that way. Looking at it from the other direction, if so desired, the same rule can be applied to POST, PUT, PATCH ie. don't allow server-managed triples to be altered, irrespective of the mediatype. Possible to just ignore or fail universally.

I was thinking the entire RDF representation, to easily distinguish in a non-LDPy way...

I don't understand. Can you please clarify?

OK. If we say "server-managed triples" that references the LDP specification, an implementation has to understand what is meant by that, if we say "entire RDF representation", that's just a media type, much less to understand. However, I suppose what makes the actual complexity is something we will find out when we write the spec, it is thus something we can defer until the drafting phase.

Yeah, I agree, it is awkward.

If representations have their URLs, it would be possible to set different access modes. However, the direction we are taking sets the policy on the effective request URI which applies to all representation URLs.

My main concern is that the security usability around access modes for different representation URLs is going to be really bad unless we put a lot of effort into it. We then have to make sure the end result when managing authz isn't confusing. That's not to say that we shouldn't resolve #109 , it is just that it is a much bigger topic when authz is involved. If we just have the container URL, and all manipulations are on that, it is much easier, you know exactly what rules apply.

Simpler to keep all POST updates to append.

I'm not sure which is the lesser of evils.

I don't see the key difference. Both approaches essentially attempt to replace a container that way. Looking at it from the other direction, if so desired, the same rule can be applied to POST, PUT, PATCH ie. don't allow server-managed triples to be altered, irrespective of the mediatype. Possible to just ignore or fail universally.

The key difference is that PUT expects to replace everything, whereas POST doesn't.

If we just have the container URL, and all manipulations are on that, it is much easier, you know exactly what rules apply.

So we agree. Shouldn't design to have representations with different access modes.

The key difference is that PUT expects to replace everything, whereas POST doesn't.

I meant beyond the literal difference between POST and PUT. If POST HTML is spec'd to act like a write/replace operation, it will generally have the same affect as PUT anything to write/replace. And so they both have to deal with not touching the RDF/server-managed triples.

Create a new resource in / (root container):

POST /

<> rdfs:label "foo".

201
Location: /foo

It is not possible to append information to / with POST. Must use PUT or PATCH to change the state of /.

Create /foo/ or append to /foo/ if exists:

POST /
Slug foo/

<> rdfs:label "foo".

Slug is required in order to append information to container with POST.

Is this in a current implementation, or do you intend it as a normative statement?

It is what I've inferred from the foundations.

POST to target resource that's a container will add a new resource to a container. So, how can the root container be targeted for the purpose of update (append)?

I'm not aware of a server allowing a root container update (append) with POST, so that's within normal behaviour. To close any potential gaps, the question would be if updating the root container should be prohibited with POST. If PUT and PATCH can and allowed, it is probably fine with POST as well. We can devise a way of course but it doesn't seem to be possible at the moment.

For non-root containers, it would be possible to update the container via Slug as the constructed effective request URI would be the desired container, although not necessarily guaranteed if for instance the server doesn't implement Slug or ignores it (aside: we can come back to that exact requirement). I'm not aware of a server capable of updating a non-root container with POST+Slug.

Oh, I can see it now, you're right... I was confused, because I didn't understand what was appending to a resource and what was creating a resource (which is also appending a container).

I my proposal, your first example would append that triple to the root container RDF representation. And that is, I acknowledge, inconsistent with what I said, that a POST without a Slug would leave the server to determine the URL of the resource it created...

I don't think we should prohibit POST on any container, the question is really whether the behaviour should be

POST /

<> rdfs:label "foo".

201 Created
Location /some-server-generated-url/

or to append <> rdfs:label "foo". to the container RDF representation. I think this would be valid for all containers, irrespective of whether it is a root container or not.

The former is a practice that has been common for a very long time on the Web but doesn't have a spec behind it AFAIK, the latter is a relatively novel interpretation of an old non-normative spec statement.

I suspect the former is already implemented, I'll write a test for it...

whether the behaviour should be
POST /
Location /some-server-generated-url/

That's it. What I'm saying is that - based on agreed foundations - I don't see "append [payload] to the container RDF representation" possible unless Slug is purposed to target the desired effective request URI. Obviously that's not possible for the root container case as it stands. Either the request needs to pass additional information about the intention or we acknowledge that it is not possible to update root container with POST.

The former is a practice

I'm not certain but that practice probably didn't permit more than one operation on the same effective request URI.

How about using POST with Slug: . (dot segment) to suggest that the payload should be appended to the target container:

POST /
Slug: .

<> rdfs:label "foo".


GET /

<> rdfs:label "foo".
...

That is for any container.

Interesting idea! Just one thing: Currently, Slug is used when creating new resources, not when appending to an existing resource.

So, how about using Slug: * when the server is asked to create the identifier?

Downside of that would be if the feature is already implemented, it would be a breaking change.

I agree that the RFC wording emphasises create but append is not particularly prohibited.

Server is already expected to create the identifier without Slug.

Right. OK, so we have a couple of possibilities. Those are things that shouldn't block us from advancing to rought consensus, I think. Any other things that block us from that?

No blockers. Some aspects will be worked out in drafting.


By the way, appending with POST text/html is possible and generally useful with RDFa but not so with non-RDFa. POST text/html to an existing container should be interpreted as an append operation based on request's payload in RDFa - effectively allowing RDF Merge. If the payload doesn't encode an RDF graph, there is nothing to append.

Tested, and found that

solid:handlers POST -- On parent: / +0ms
solid:handlers POST -- Will create at: https://robin.kjernsmo.net:8446/2d4a6a90-33aa-11ea-bd8c-eb7f2690efb0 +0ms

i.e., NSS creates a resource with a server-assigned identifier if no Slug is set. This is as expected, and that would influence the design as we should probably not break this behaviour. I'll update #128 too.

[@csarven] POST text/html to an existing container should be interpreted as an append operation based on request's payload in RDFa - effectively allowing RDF Merge

I do not understand the consistant effort to treat anything-but-RDF as trash.

RDFa must not be treated as RDF-plus-HTML, nor otherwise be handled as if the HTML is valueless. RDFa is HTML-plus-RDF, and the primary value of the resource is in the HTML, which value is increased by the inclusion of the RDF.

RDF Merge is not appropriate for POST of any HTML, including HTML-plus-RDF.

POST text/html to an existing container should generally be treated as a request to create a text/html resource within that container -- or maybe as a request for that payload to be handled according to that container's rules, which might include loading RDF found within RDFa markup within that HTML into a triple/quad store -- but should absolutely not include discarding the HTML markup containing the RDFa markup unless that discard follows an explicit confirmation with the user.

POST text/html to an existing container should be interpreted as an append operation based on request's payload in RDFa - effectively allowing RDF Merge

I do not understand the consistant effort to treat anything-but-RDF as trash.

I do not understand how anything that we've said can be interpreted as that. To the contrary, this effort is motivated by a "homepage" use case, where a user wants to write a homepage in HTML.

RDFa _must not_ be treated as RDF-plus-HTML, nor otherwise be handled as if the HTML is valueless. RDFa is HTML-plus-RDF, and the primary value of the resource is in the HTML, which value is increased by the inclusion of the RDF.

Of course.

RDF Merge is not appropriate for POST of any HTML, including HTML-plus-RDF.

Why do you say that?

POST text/html to an existing container should generally be treated as a request to create a text/html resource within that container

Of course, just as we've specified.

-- or _maybe_ as a request for that payload to be handled according to that container's rules, which _might_ include loading RDF found within RDFa markup within that HTML into a triple/quad store --

Yes, that's what we've been saying. What algorithm do you want to use for that if you do not want to use RDF Merge?

but should absolutely not include discarding the HTML markup containing the RDFa markup _unless_ that discard follows an explicit confirmation with the user.

Of course.

@kjetilk -

My last comment was in response to @csarven's last comment, of which I quoted the most relevant sentence. I should perhaps have also included the next sentence, to wit --

[@csarven] If the payload doesn't encode an RDF graph, there is nothing to append.

There is something to append to the container -- which is the text/html payload -- because an LDP Container is not limited to containing RDF!

If RDF within the payload is going to be applied to an RDF triple/quad store, then RDF Merge is fine -- within the context of that RDF store.

RDF Merge is not fine as the complete treatment of a POST text/html request, because that payload is not just RDF.

The use of "append" was in context of updating a container as opposed to creating a resource as a member of a container. Like giving the container a label (as in the Slug example from earlier) or the homepage case.

I don't quite see how HTML without non-RDFa can be appended per se. Hence, RDF Merge doesn't apply any way. We may need to be more precise about append. It would be feasible to append in the sense that the delta between the current representation and the new representation would be the data intended to be appended. It is not strictly about "add this to that" but more so about ensuring the continuity of the resource state. So, perhaps POST text/html would simply mean that the payload needs to be consistent for it to be considered a successful append operation. From the outset, it may appear to be similar to PUT to container. Where applicable1, the requirement to persist containment triples would remain.

  1. I think this may serve as the wiggle room for the index.html case (69) actually in that is not forced to include containment triples.

I'm not convinced that even HTML with RDFa can be meaningfully appended in the general case. There are lots of specific cases where it can, e.g. formulaic records whose order is temporal. For example, a diary or blog could be usefully treated as a linear document. In those cases, the presence of RDFa doesn't affect whether it's linear. If the document is supposed to have some sort of narrative flow (a book, a spec, a single-record document), we're looking at PATCH rather than POST.

I propose the spec follow the definition of POSTing RDF to RDF docs with:

POSTing an HTML payload P to an HTML resource R appends P's html/body/* elements to the end of R'shtml/body.

That would provide a predictable behavior to HTML POSTs that clients can work with. It may be worth having a header which controls prepend vs. append or default to prepend so new "records" appear at the top. We could invent behaviors for other linear formats, typically dialects of XML, but I don't think it's worth doing that now. It also may be worth allowing P to elide its <html><body> wrapper.

This creates two distinct merge semantics, one for linear documents and one for RDF graphs. I think it would be contrived to allow for mixing them (Franken-merge) and that clients would be better served by getting an error when appending HTML to RDF and visa versa.

(Alternative proposal: only specify POST to RDF payloads on RDF Resources and see in a few years if folks have invented the linear document semantics or something else that may be more useful.)

Just so that we don't get ahead of ourselves, I suggest that we agree on how to target the container for the purpose of updating (appending) its state. Two Slug based approaches are pitched above (Slug: . as the latest). If that's sensible, simple, useful.. Hint: throw stones at it or propose something else. If we don't get the targeting working, I'm not convinced that append to an existing container's state with POST is possible to begin with (regardless of message media type).


I generally like this idea as a possibility but concerned about what it entails:

POSTing an HTML payload P to an HTML resource R appends P's html/body/* elements to the end of R's html/body.

Although I can see the practicality, appending to an HTML document is not confined to adding nodes into body nor should be. Client should be able to append to any part of the document eg. any node type and value, regardless of the document structure and intended semantics.

RDF Merge makes it possible for any part of the resource description - RDF graph - to be extended (including any existing units of information). However, with the approach above for HTML, it is limited to prepend and append, and so eg. adding a paragraph to an existing section is not possible. Hence, the request semantics while intended or perceived to be the same have fundamentally different outcomes for append.

The following is a valid HTML5 document:

<!DOCTYPE html>
<title>foo<title>

Whether that's the payload P or the target resource R, you can see that it wouldn't be a straightforward append ie. without expecting the server to do some normalisation by updating the tree perhaps eg. include head, body.

For the homepage or other cases, I'm not sure about the utility of only being able to prepend/append.

So, those are some of my concerns, and generally think that the Solid spec needs to have a careful cut off point and not over specify or something very new. Don't get me wrong, I'm fine with some practicality as opposed to nothing.


Note: I'm only exploring not advocating the following:

What may be sufficiently well-defined and that can be borrowed is the add patch operation from XML Patch operations + XPath: https://tools.ietf.org/html/rfc5261#section-4.3 .

As a bonus, the same approach can potentially be used for the PATCH case ( mentioned in https://github.com/solid/specification/issues/85#issuecomment-554733574 )

Payload examples:

<add sel="/path/to/node">
 <p>foo</p>
</add>

<add sel="/path/to/node" type="@property">schema:abstract</add>

It is a matter of wrapping the intended node to be appended to specified location.


Edit: One requirement that's the same in the approaches that @ericprud and I mentioned is that the Content-Type needs to properly indicate the payload, along with what's expected of POST as opposed to for example PATCH, which expects the payload to be an instruction describing what the server should do. So, while we could get away with the payload as if it is not an instruction, but it actually is implied at the very least.


Alternatively, we only specify appends to existing containers if server can eventually perform RDF Merge, and that they should reject the other cases?

@csarven in any proposal, it would be helpful to consider how a client would discover what the semantics of POST are for a particular server. That is, for a given Solid server implementation, how does a client know what a POST operation implies before actually issuing the request and inspecting the response?

Given that Slug is just a hint to the server (and can therefore be ignored), I would be a little wary of seeing these two requests as so structurally different (provided that I am understanding the proposal correctly):

# Append triples to the container itself
POST /container/
Slug: .

and

# Create a new resource inside the container
POST /container/
Slug: resource

If there was another header involved, that might make the semantics more clear or even a particular Content-Type. But generally, why wouldn't you just use PATCH to append triples? application/sparql-update doesn't need to be the only content-type accepted for PATCH.

@acoburn The request semantics of POST is for the most part what RFC 7231 says. Anything beyond that is the criteria that the Solid spec sets. For instance, we are defining what "append" and "write" operations imply ( https://github.com/solid/specification/issues/118 , https://github.com/solid/specification/issues/126 ) by clarifying the relationship between HTTP and WAC.

I agree that Slug at the moment, and probably for all time, is only a client suggestion and that it can't necessarily be relied upon. However, if a server allows container updates with POST, then they can accept requests including Slug to actually have it work. Clients intending to update a container, will have to use it of course. This is similar to for example LDP specifying an interaction model, and servers and clients adhering to it. Without the spec, no client can really be expected to know what an interaction model is that's passed through the Link header. (Okay, potentially possible if all pointers are self-describing for machines to grok.)

I thought Slug would be needed to "append triples to the container itself" (https://github.com/solid/specification/issues/108#issuecomment-572317243 , https://github.com/solid/specification/issues/108#issuecomment-572645113 ). I am not certain if the request is meaningful - that's why I'm asking for feedback. I'm on the fence because the dot segment is expected to be "removed as part of the resolution process" at least in URIs (RFC 3986), and what remains is the same target resource for updating. We may only need to specify it along with slash semantics in Slug ( https://github.com/solid/specification/issues/96#issuecomment-570086753 ). If there is something else more appropriate, fine by me.

Note that both of those POST /container/ examples are considered to be append ( https://github.com/solid/specification/issues/118#issuecomment-569648485 ) even meanwhile a resource is getting created, but only acl:Append is required. Yea, I know..

[Aside: Let me just say that this is the kind of language/semantics exercise that I tried to push back on. I'm open to considering POST to container as a write or whatever operation, if that's more meaningful and useful in the end, but let's resolve that in 118 and 126 instead of here.]

As mentioned earlier, I'd be content to not specify POST to container for the purpose of appending triples to it. Not thrilled about the idea of introducing a particular Content-Type. It may help with the payload for appending but we still need to resolve targeting. Yes, PATCH would be just fine to append triples. Agree also with PATCH handling different Content-Types but I think we only have application/sparql-update on the table at the moment (fundamentally required?) ... there may be some hints and nudges about using others like application/xml-patch+xml ?

I think we got on some tangents too many now.

In the case of RDF, the append operation is obvious, it is the RDF Merge defined in rdf-mt, for HTML I imagine there could be something similar that defines it in terms of the tree structure, but in general it is far from that obvious and I think we should resist any temptation to define what an append operation means generically, that has to be an orthogonal issue, IMHO outside the scope of Solid. If we start to get too deeply into that, it will slow our progress dramatically.

We have encountered many tensions in #69 , and some of that carries over here, especially since an update of a resource with an HTML+RDFa representation have both types of data. We could trivially append RDF to the resource, but not to HTML. Pragmatically, it seems like something that could be handled as an implementation detail, as the server would always have a way to serialize the RDF regardless of how it has been has added, it could at the very least add it to the /html/head of the document.

I think the critical question is whether POST should tie very strongly to acl:Append. Doing so, would certainly make it easier to secure the server. However, it might be that people use POST to update e.g. HTML files. If so, it is possible to define that when a POST brings a clearly defined append operation and where the server is able to verify that indeed only append is done, like it is for RDF, then it will execute, otherwise it will require acl:Write. It seems like this complexity is unnecessary though: We should insist that POST is used for appends, and only for media types that has a clear append definition. This makes extending the server with further append operations on other media types an orthogonal issue.

In the HTML+RDFa case, it means that changes using RDF only media types will be accepted since they can be dealt with by an RDF Merge, whereas changes in the HTML media types will be rejected.

I believe that we should take the view that POST implies acl:Append is required, and that no operations that require other permissions should be permitted to use POST (ignoring SPARQL for the moment).

@acoburn :

But generally, why wouldn't you just use PATCH to append triples? application/sparql-update doesn't need to be the only content-type accepted for PATCH.

As mentioned above, POST-to-append has been the intuition since the first HTTP draft. Anecdotally, I have always used it. It maps very clearly to the RDF Merge, which is also how SPARQL defines it. Arguably, INSERT DATA is syntactic sugar around the RDF Merge. I fear, however, that if we give developers another thing to learn beyond RDF to do something as simple as this, it will hinder Solid adoption.

There's nothing wrong with PATCH, but if you only need append, it will always be extra complexity. For example, what access mode is required by a PATCH can only be found from the request body, whereas for POST, it can be found from the media type itself.

So, in the interest of keeping simple things simple and hard things possible, I really think we need to have POST-to-append.

But yeah, I see that Slug: . is less than ideal. I would prefer to not have that design, but I can't come up with a better alternative. That said, since a Container expects much less interaction than other resources, I can certainly live with that we don't define how to add triples to them in this round.

Then, understanding the implications of a POST becomes a matter of inspecting the request URI and applying the heuristics of #128 , which I think is becoming pretty clear, and should improve in the drafting phase.

I think we got on some tangents too many now.

What followed from the point of agreement at https://github.com/solid/specification/issues/108#issuecomment-572804436 was about container updates.. because it wasn't addressed. That's why I raised and the discussion moved. Whether it is possible to target a container for update with POST:

Just so that we don't get ahead of ourselves, I suggest that we agree on how to target the container for the purpose of updating (appending) its state.

Re:

we should resist any temptation to define what an append operation means generically

RFC doesn't restrict POST append to a Content-Type. So, if anything that's going on is Solid constraining the append to only RDF formats. But even for Solid, I was under the impression that append is not limited to RDF.. I see no reason provided that each use their own request semantics/algo. If we acknowledge that a container may not necessarily be an RDF Source, then we have to consider whether append is supposed to be about RDF or not. Having said that, if POST to append is only for RDF:

Alternatively, we only specify appends to existing containers if server can eventually perform RDF Merge, and that they should reject the other cases?

What do you think about https://github.com/solid/specification/issues/40#issuecomment-573358652 ?

whether POST should tie very strongly to acl:Append

Yes.

I believe that we should take the view that POST implies acl:Append is required, and that no operations that require other permissions should be permitted to use POST (ignoring SPARQL for the moment).

I thought we agreed on that already. Provided that update to container (to create a new resource) can be covered by append: https://github.com/solid/specification/issues/118#issuecomment-569648485 .

But yeah, I see that Slug: . is less than ideal. I would prefer to not have that design, but I can't come up with a better alternative. That said, since a Container expects much less interaction than other resources, I can certainly live with that we don't define how to add triples to them in this round.

I don't have anything better at the moment either.. and yes, I can live with no container updates as well. It is still though important... giving a container a human-readable label is a natural expectation.

--

Can we wrap this up? We have enough material here for draft criteria. We can resolve the finer details there.

I think we got on some tangents too many now.

What followed from the point of agreement at #108 (comment) was about container updates.. because it wasn't addressed. That's why I raised and the discussion moved. Whether it is possible to target a container for update with POST:

Just so that we don't get ahead of ourselves, I suggest that we agree on how to target the container for the purpose of updating (appending) its state.

Right, but I took the conversation here as a broader discussion, one that is about what append operations imply on generic resources, not specifically containers.

Re:

we should resist any temptation to define what an append operation means generically

RFC doesn't restrict POST append to a Content-Type.

No, but the RFC doesn't need a strict interpretation, as it doesn't have a concept of access control, so it can afford to be generic, we cannot, because we have to make sure that the acl:Append authorization is respected.

So, if anything that's going on is Solid constraining the append to only RDF formats. But even for Solid, I was under the impression that append is not limited to RDF.. I see no reason provided that each use their own request semantics/algo.

Hmmmm, append is certainly a useful operation on all kinds of resources, but surely, what an append implies certainly comes down to the semantics of the media type, or even the individual representation?

For RDF, we have the luxury of the RDF merge, which is great. For HTML and JSON, you could envision that an append operation implies that the existing representation R is appended to by a payload R' iff R is a strict subtree of R', but what would it mean to append something to an image, and how could you find out?

That's why I say that each media type needs its own append definition. For RDF we have one, lets go for that.

If we acknowledge that a container may not necessarily be an RDF Source, then we have to consider whether append is supposed to be about RDF or not. Having said that, if POST to append is only for RDF:

Alternatively, we only specify appends to existing containers if server can eventually perform RDF Merge, and that they should reject the other cases?

If we restrict ourselves to containers, then yes. For generic resources, I think the definition could be something like "if representation has a clear algorithm for append" or something.

But yeah, I see that Slug: . is less than ideal. I would prefer to not have that design, but I can't come up with a better alternative. That said, since a Container expects much less interaction than other resources, I can certainly live with that we don't define how to add triples to them in this round.

I don't have anything better at the moment either.. and yes, I can live with no container updates as well. It is still though important... giving a container a human-readable label is a natural expectation.

Yeah... it could still be updated by PUT though, first doing a GET, get the Etag, make that change, and PUT it back with If-Matches...

--

Can we wrap this up? We have enough material here for draft criteria. We can resolve the finer details there.

I agree. We will probably better advance with it more concrete now, and I think it is appropriate to put it down in draft text.

[@ericprud] I propose the spec follow the definition of POSTing RDF to RDF docs with:

POSTing an HTML payload P to an HTML resource R appends P's html/body/* elements to the end of R'shtml/body.

I haven't digested everything subsequent to this yet, but this is important --

html/body/* is not all that may be important in an HTML payload. That html/body/* may well depend on things in the html/head/* of P which are not in the original R -- and this would lose those things.

@ericprud's formulation must not be put in the spec, as written here.

@TallTed , we can't have a generic server do everything that custom POST handler might do. Normally, I'd not want to bother handling POST on HTML at all, but folks seemed motivated to handle POSTs to index files. Given that, I don't see how we can do any more than provide a simple and predictable rule that clients can count on. So sure, clients might want POST to do arbitrarily complex operations; but I don't know how to specify a generic POST operation to do that. Got any ideas?

Not sure it is POST on HTML that is the central issue, rather handle the RDFa that might be embedded in it, which should be handled like other RDF would.

I agree that RDFa is our primary use case, but I don't think the presence or absence of RDFa affects the treatment of HTML. RDFa's value comes in it being interspersed in the HTML (otherwise, you may as well use a script with type=turlte or JSON). Suppose we have an index file:

<html><head><title>My Stuff</title><style></style></head>
  <body>
  <h2 property="http://purl.org/dc/terms/title">Resource 1</h2>
  <p>Date: <span property="http://purl.org/dc/terms/created">2011-09-10</span></p>
</body> </html>

If we want to add Resource 2 and preserve the RDF, we can (in order of increasing effort and controversy):

  • script-only -- not handle RDFa but instead specify merging POSTed script data into a pre-existing script element in the head.
  • strip-RDFa -- like script-only, but promise to extract any RDFa in POSTed HTML. (-.8 'cause it throws away the value of the RDFa.)
  • append-body -- stuff POSTed RDFa somewhere in the body (top, bottom)
  • markup-target -- have a processing instruction specify where to inject the POSTed RDFa.

And of course there's no-HTML-POST -- reject any POSTs with HTML target or body.

Yes, indeed, the question is not whether it can be done, the question is whether we should, and if we should, then the question is when. My answer is "definitly not now" :-)

To expand on the append-body, this suggest that there is a lot of freedom that servers could have in determining what an append would be, just like shapes for RDF. For example, one resource could determine that an append it its context would be to add another pair of h2 and p in your example, in another, it could be to add another row of data to a table.

I would question if this is a valid use of Solid, since Solid is mostly about manipulating RDF, and have apps that use RDF on the client side. In this case, we add to much smart to the server side.

I don't see markup-target as a major undertaking, but I don't think we should define it, it should be up ot the server to template where they want to inject the RDFa data. They would probably have to do that anyway, but I believe the only normative thing we should say about it, is that the RDF representation has to be there for the #69 case.

[Just laying out some things to consider.. and also for drafting, so bear with me.]

I'd like to clarify some behaviours and variability related to Slug because it seems important.

Assuming container create and/or update are desired with POST. Without the other headers (eg. Link) influencing the identifier, we have:

  • Slug is required to create and update a container.

  • Slug: . is required to update the root container.

A server accepting Slug and keeping the value as is, the response of the following requests should be equivalent:

POST /
Slug: foo/

POST /foo/
Slug: .

That is, /foo/ will be created or updated.

There is however a variability issue (or consideration) in the responses pertaining to effective request URIs where server ignores Slug. Hence, the above example may result in the creation of /foo and /foo/bar respectively. To take another example:

POST /
Slug: .

Client's request may either result in update / or create /foo if Slug is ignored.

So, what a poor client to do? First question is whether this kind of variability should exist in the design.

Let's say it shouldn't. One way a nice server may be able to mitigate unexpected results for the client is to catch some of the cases. For instance, a server may ignore the Slug in determining an identifier, however, if detected, it can check for consistency. So:

POST /
Slug: foo/

Here the client would like to create /foo/. Compared with the earlier behaviour, the server instead of creating /foo, can return 400 (or something else?) if trailing slash in Slug is detected.

Yet another possible server behaviour is where Slug can only be used to update a container and that create will be rejected. Clients need to use PUT (simple) or PATCH (less simple) to create a container. So:

POST /
Slug: foo/

Client's request may either update /foo/ or return 400 if /foo/ exists.

So, this is a matter of client's comfort in dealing with the consequences of using a Slug. Not using it is obvious and simple but there are cases in which it is definitely a nice to have. If create or update container via POST removed, that'd is another simplification.

Almost done: alternatively, we raise the level of Slug requirement so that there is less variance in the responses.

Actually, it seems I would want to challenge the premises of that post, @csarven :

  • Slug is required to create and update a container.

  • Slug: . is required to update the root container.

My opinion is that Slug is never required, and the definition of Slug seems to imply it is only for creates. So, while I did find the Slug: . interesting, it seems like we are stretching it a bit, but I feel strongly that once a resource is created, we should manipulate it by its own URL, not use a Slug to do it.

Slug: . is an interesting special case, because it says "this resource", but as you show that it brings along ambigiouties, I say we should save it for $later.

For creates, I think we exhausted the space in https://github.com/solid/specification/issues/128#issuecomment-573033297

Actually

Actually, I think you may have overlooked the premise and the statements there :)

Put differently, if you still want to be able to create and update a container using POST, Slug is (probably) required (re https://github.com/solid/specification/issues/108#issuecomment-567272797 )

I feel strongly that once a resource is created, we should manipulate it by its own URL

That'd be great. How? PUT, PATCH is a non issue obviously.

The whole point of observing variability was due to Slug being MAY. And to help figure out where to draw the lines.

I don't think whether Slug can be used for append or not is actually an issue - okay to dismiss the possibility of course. Let me put it this way, we define the append operation but in there we do have some "create" resource happening - at least the context being that a resource is created and added to container. We are using POST for the purpose of append, so whether the Slug is actually constrained to create (like stand alone resources) is a very specific view. (I'm not dismissing or disagreeing .. just saying that our definitions and reasoning is not super clear to make the call on Slug that way.)

OK, then I don't understand where you are going, but I've returned it to Under discussion to clarify.

In my head it is very simple: Slug is just for creating resources, and #128 defines that exhaustively.

When updating, you don't use a Slug, the append applies to the request-URI, and since a Slugless POST to a container already means that the server chooses the rest of the identifier (also as detailed in #128), we can't append to the container representation without doing something clever.

That Slug: . could be that clever thing to enable that, but lets not do it now to ensure that we can progress towards a draft. We can figure out that something clever later if appending to a container representation is a feature people miss.

That's my position, what's wrong with that picture?

Just to be clear, it makes sense to move to Under Discussion on the basis of us not completely clearing how to POST Container.Update and if so still desired.

As documented above, I was merely exploring the boundaries to find a way to reconcile. So, yes, I do fully understand your position and there is nothing wrong with that picture.

Hey! You scared the living daylights out of me, @csarven , I thought you were opening a much bigger can of worms!

Is that picture something we can go for as rough consensus?

Just stating my preference, not intending to reopen any discussions

  • only use POST on LDPC to create new LDPR (server may or may not honor Slug header)
  • use PATCH to update LDP-RS
  • use PUT to update LDP-NR - this leaves all the complexity of modifying HTML or SVG or ... to the client

If above doesn't address requirements motivated by some specific use case I would need to see that specific use case.

Arguably, INSERT DATA is syntactic sugar around the RDF Merge. I fear, however, that if we give developers another thing to learn beyond RDF to do something as simple as this, it will hinder Solid adoption.

I think libraries can take care of DX. I don't see adding different way to accomplish the same thing that much helpful. Especially if it would rely on nuances (eg. Slug header), add extra burden on storage server implementations, and blurry expectations client applications can make about interactions with storage servers.

Don't most of the reasons you'd want to POST and LDP-RS also apply to LDP-NRs?

  1. server manages naming.
  2. injection into a container (whether that be RDF manipulation or some other server state).
  3. (more) defined response codes for when the above works.
Was this page helpful?
0 / 5 - 0 ratings