diff --git a/docs/reference/command-line-interface.ttl b/docs/reference/command-line-interface.ttl index a493a1a..e50f844 100644 --- a/docs/reference/command-line-interface.ttl +++ b/docs/reference/command-line-interface.ttl @@ -403,6 +403,9 @@ ldh add file \\

See also the data import user guides.

Request bodies

ldh put and ldh post read RDF from an optional FILE argument, recognizing the syntax from its extension (ldh put "$LDH_BASE" root.ttl), or from standard input, where -t/--content-type is required since a stream carries no name. Either way relative URIs resolve against the target URI. ldh patch reads a SPARQL 1.1 update from standard input, validates it and sends it verbatim.

+

Creating, not replacing

+

ldh create container and ldh create item only create: the PUT carries If-None-Match: *, so a document already at the URI is refused 412 Precondition Failed and left as it is, and the command exits 1 with nothing on standard output. --if-absent accepts that document instead, as mkdir -p does a directory: the command exits 0 and prints its URL, so a setup script can run again. To replace a document, ldh put it.

+
container=$(ldh create container --parent "$LDH_BASE" --title "Categories" --slug categories --if-absent)

What a document is about

ldh create item and ldh create container take --primary-topic, the resource the document is about, resolved against the created document's URI: '#this' names a fragment of the document itself, an absolute URI a resource described somewhere else. It writes the foaf:primaryTopic link only — the topic's own type and properties are the constructor's business, and a vocabulary may refuse a topic without them.

ldh create item \\
diff --git a/docs/reference/http-api.ttl b/docs/reference/http-api.ttl
index 5b429be..76b1626 100644
--- a/docs/reference/http-api.ttl
+++ b/docs/reference/http-api.ttl
@@ -83,6 +83,9 @@
                 
             
         
+        

The accept query parameter stands in for the Accept header where a link cannot set one, as in + ?accept=text%2Fturtle. Its value is a media type and has to be URL-encoded: a malformed one, such as an unencoded + ?accept=application/rdf+xml whose + decodes to a space, is answered 400 Bad Request.

The same document, negotiated as N-Triples:

GET /products/1/ HTTP/1.1
 Host: localhost:4443
diff --git a/docs/reference/http-api/documents.ttl b/docs/reference/http-api/documents.ttl
index 089d439..ceb5080 100644
--- a/docs/reference/http-api/documents.ttl
+++ b/docs/reference/http-api/documents.ttl
@@ -48,9 +48,9 @@
                     Media type not supported
                 
                 
-                    POST
-                    Appends data to a document
-                    204 No Content
+                    POST
+                    Appends data to a document
+                    204 No Content
                     400 Bad Request
                     RDF syntax error
                 
@@ -67,19 +67,22 @@
                     Media type not supported
                 
                 
-                    422 Unprocessable Entity
+                    422 Unprocessable Entity
                     Constraint violation in the resulting document
                 
                 
                     Body states the sioc:has_parent/sioc:has_container of a resource other than the document
                 
+                
+                    Body types the document with a class other than def:Root, dh:Container and dh:Item, or leaves the root without one of them
+                
                 
                     Malformed IRI in the body (see below)
                 
                 
-                    PUT
-                    Upserts a document
-                    204 No Content (replaced)

201 Created (created)

308 Permanent Redirect + PUT + Upserts a document + 204 No Content (replaced)

201 Created (created)

308 Permanent Redirect 400 Bad Request RDF syntax error @@ -99,12 +102,15 @@ Media type not supported - 422 Unprocessable Entity + 422 Unprocessable Entity Constraint violation in the resulting document Body states the sioc:has_parent/sioc:has_container of a resource other than the document + + Body types the document with a class other than def:Root, dh:Container and dh:Item, or leaves the root without one of them + Malformed IRI in the body (see below) @@ -124,11 +130,14 @@ The container still has documents: delete them first - PATCH - Modifies a document using SPARQL Update - 204 No Content - 422 Unprocessable Entity - SPARQL update is not a single DELETE/INSERT … WHERE or DELETE WHERE operation, uses GRAPH, WITH, USING or USING NAMED, or removes an rdf:type + PATCH + Modifies a document using SPARQL Update + 204 No Content + 422 Unprocessable Entity + SPARQL update has an operation other than DELETE/INSERT … WHERE, DELETE WHERE, INSERT DATA and DELETE DATA, uses GRAPH, WITH, USING or USING NAMED, or removes an rdf:type + + + Update types the document with a class other than def:Root, dh:Container and dh:Item, or leaves it without one of them Constraint violation in the updated document @@ -152,6 +161,8 @@

Containment is server-managed: a POST drops the document's sioc:has_parent/sioc:has_container from its body, a PATCH cannot change them, and no write may state the containment of another resource. acl:default grants rely on it.

+

A document is typed with the hierarchy classes only — def:Root, dh:Container or dh:Item — and a write that gives it any other type is refused with 422 Unprocessable Entity, as is a PUT of the root or a + PATCH that leaves the document with none of them. Other classes belong on the resources the document describes, such as its foaf:primaryTopic.

LinkedDataHub will also manage additional document metadata, such as its owner and creation/modification timestamps.

For example, this HTTP request creating the Northwind regions container (Turtle syntax):

PUT /regions/ HTTP/1.1
@@ -199,7 +210,7 @@ If-None-Match: *

Graph-scoped updates

-

A PATCH applies a SPARQL update scoped to the requested document's graph. The request body must contain a single update operation, in one of two forms: DELETE/INSERT with a WHERE clause (either template can be omitted, giving plain INSERT { } WHERE { } or DELETE { } WHERE { }), or the DELETE WHERE shorthand. Every other form is rejected with 422 Unprocessable Entity, as is a body with more than one operation. Like any write to an existing document, it quotes the document's entity tag (see Conditional writes). Appending a description to the Chai product:

+

A PATCH applies a SPARQL update scoped to the requested document's graph. The request body contains one or more update operations, separated by ;, in any of these forms: DELETE/INSERT with a WHERE clause (either template can be omitted, giving plain INSERT { } WHERE { } or DELETE { } WHERE { }), the DELETE WHERE shorthand, INSERT DATA and DELETE DATA. Every other form is rejected with 422 Unprocessable Entity. The operations run in order, and the document is validated once they all have: they change it together or not at all. Like any write to an existing document, it quotes the document's entity tag (see Conditional writes). Appending a description to the Chai product:

PATCH /products/1/ HTTP/1.1
 Host: localhost:4443
 Accept: application/n-triples
@@ -213,6 +224,23 @@ INSERT
     <https://localhost:4443/products/1/#this> schema:description "A delicate black tea blend" .
 }
 WHERE {}
+

Replacing the product's name, as two operations applied together:

+
PATCH /products/1/ HTTP/1.1
+Host: localhost:4443
+Accept: application/n-triples
+Content-Type: application/sparql-update
+If-Match: "1e635b4-ntriples"
+
+PREFIX schema: <https://schema.org/>
+
+DELETE DATA
+{
+    <https://localhost:4443/products/1/#this> schema:name "Chai" .
+} ;
+INSERT DATA
+{
+    <https://localhost:4443/products/1/#this> schema:name "Masala Chai" .
+}

The update executes against that one graph, so it cannot name another: GRAPH is not allowed in a template, in the WHERE pattern (including EXISTS and sub-queries) or in a DELETE WHERE, and neither are WITH, USING and USING NAMED. This request is rejected with 422 Unprocessable Entity:

PATCH /products/1/ HTTP/1.1
diff --git a/docs/reference/http-api/linked-data-proxy.ttl b/docs/reference/http-api/linked-data-proxy.ttl
index ff3384b..3079750 100644
--- a/docs/reference/http-api/linked-data-proxy.ttl
+++ b/docs/reference/http-api/linked-data-proxy.ttl
@@ -36,6 +36,8 @@
     schema:telephone "(171) 555-2222" .

An HTML page with no JSON-LD has no RDF representation, so the proxy answers 406 Not Acceptable. The user interface then opens the page in a new browser tab, as an ordinary external link would.

+

Any other non-RDF body, such as an image, is passed through when its media type matches the request's Accept, and answered + 406 Not Acceptable otherwise. An object block whose value is an external image requests RDF, gets the 406 and shows the image.

The proxy only accepts external (non-relative to the current dataspace's base URI) URLs; local URLs have to be dereferenced directly.

The proxy forwards the origin's ETag and Last-Modified validators and passes conditional request headers (If-Match, If-None-Match, If-Modified-Since, If-Unmodified-Since) through. Preconditioned diff --git a/docs/reference/versioning.ttl b/docs/reference/versioning.ttl index 5350d00..3402544 100644 --- a/docs/reference/versioning.ttl +++ b/docs/reference/versioning.ttl @@ -133,6 +133,16 @@ HTTP/1.1 302 Found Location: https://localhost:4443/orders/10248/?version=4d1e7aa Vary: accept-datetime Link: <https://localhost:4443/orders/10248/>; rel="original"

+

A version is committed after the write that makes it. While the document's latest change is still being committed, the most + recent version would be the one before it, so the TimeGate answers 503 Service Unavailable with Retry-After instead: + a second per commit queued on the dataspace's branch, at most 60. After a commit that failed, it answers 500 Internal Server Error + until the next write is committed.

+
GET /orders/10248/?timegate HTTP/1.1
+Host: localhost:4443
+
+HTTP/1.1 503 Service Unavailable
+Retry-After: 3
+Cache-Control: no-store

Restore and diff

@@ -163,7 +173,7 @@ Link: <https://localhost:4443/orders/10248/>; rel="original"
--timemap - The version history (PROV-O in RDF formats, or application/link-format via --accept) + The version history (PROV-O in RDF formats, or application/link-format via --accept), from the timemap the document links to --version <sha> @@ -171,7 +181,7 @@ Link: <https://localhost:4443/orders/10248/>; rel="original" --timegate - Datetime negotiation; the optional --datetime takes an RFC 1123 or ISO 8601 datetime. Prints the negotiated version's URI as the only line on stdout, so it pipes into another ldh get + Datetime negotiation with the timegate the document links to; the optional --datetime takes an RFC 1123 or ISO 8601 datetime. Waits as a 503's Retry-After asks, then prints the negotiated version's URI as the only line on stdout, so it pipes into another ldh get