Skip to content
This repository was archived by the owner on Apr 13, 2022. It is now read-only.

Commit 6f31735

Browse files
author
Andrei
committed
Merge pull request #87 from solid/dz_extract_component_specs
Extract the rest of the sections to component specs
2 parents 23cfda1 + c26141e commit 6f31735

11 files changed

Lines changed: 1092 additions & 870 deletions

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
##### v0.6.1
2+
3+
- Extract the rest of the sections into component specs.
4+
15
##### v0.6.0
26

37
- Move overview-type sections to `solid/solid` (see

README.md

Lines changed: 144 additions & 868 deletions
Large diffs are not rendered by default.

api-rest.md

Lines changed: 371 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,371 @@
1+
# Solid HTTPS REST API Spec
2+
3+
**Note:** This spec is a component of the parent
4+
[Solid specification](README.md); the parent spec and all its components are
5+
versioned as a whole.
6+
7+
## Reading Resources
8+
9+
Resources can be commonly accessed (i.e. read) using HTTP GET requests. Solid
10+
servers are encouraged to perform content negotiation for RDF resources,
11+
depending on the value of the `Accept` header.
12+
13+
**IMPORTANT:** a default `Content-Type: text/turtle` will be used for requests
14+
for RDF resources or views (containers) that do not have an `Accept`
15+
header.
16+
17+
### Streams
18+
19+
Being LDP (BasicContainer) compliant, Solid servers MUST return a full listing
20+
of container contents when receiving requests for containers. For every resource
21+
in a container, a Solid server may include additional metadata, such as the time
22+
the resource was modified, the size of the resource, and more importantly any
23+
other RDF type specified for the resource in its metadata. You will notice in
24+
the example below that the `<profile>` resource has the extra RDF type
25+
`<http://xmlns.com/foaf/0.1/PersonalProfileDocument>`, and also that the
26+
resource `<workspace/>` has the RDF type
27+
`<http://www.w3.org/ns/pim/space#Workspace>`.
28+
29+
Extra metadata can also be added, describing whether each resource in the
30+
container maps to a file or a directory on the server, using the [POSIX
31+
vocabulary](http://www.w3.org/ns/posix/stat#). Here is an example that reflects
32+
how our current server implementations handle such a request:
33+
34+
REQUEST:
35+
36+
```
37+
GET /
38+
Host: example.org
39+
```
40+
41+
RESPONSE:
42+
43+
```
44+
HTTP/1.1 200 OK
45+
46+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
47+
48+
<>
49+
a <http://www.w3.org/ns/ldp#BasicContainer>, <http://www.w3.org/ns/ldp#Container>, <http://www.w3.org/ns/posix/stat#Directory> ;
50+
<http://www.w3.org/ns/ldp#contains> <profile>, <data/>, <workspace/> ;
51+
<http://www.w3.org/ns/posix/stat#mtime> "1436281776" ;
52+
<http://www.w3.org/ns/posix/stat#size> "4096" .
53+
54+
<profile>
55+
a <http://xmlns.com/foaf/0.1/PersonalProfileDocument>, <http://www.w3.org/ns/posix/stat#File> ;
56+
<http://www.w3.org/ns/posix/stat#mtime> "1434583075" ;
57+
<http://www.w3.org/ns/posix/stat#size> "780" .
58+
```
59+
60+
#### Globbing (inlining on GET)
61+
62+
We have found that in some cases, using the existing LDP features was not
63+
enough. For instance, to optimize certain applications we needed to aggregate
64+
all RDF resources from a container and retrieve them with a single GET
65+
operation. We implemented this feature on the servers and decided to call it
66+
"globbing". Similar to [UNIX shell
67+
glob](https://en.wikipedia.org/wiki/Glob_(programming)), doing a GET on any URI
68+
which ends with a `*` will return an aggregate view of all the resources that
69+
match the indicated pattern.
70+
71+
For example, let's assume that `/data/res1` and `/data/res2` are two resources
72+
containing one triple each, which defines their type as follows:
73+
74+
For *res1*:
75+
76+
```
77+
<> a <https://example.org/ns/type#One> .
78+
```
79+
80+
For *res2*:
81+
82+
```
83+
<> a <https://example.org/ns/type#Two> .
84+
```
85+
86+
If one would like to fetch all resources of a container beginning with `res`
87+
(e.g. `/data/res1`, `/data/res2`) in one request, they could do a GET on
88+
`/data/res*` as follows.
89+
90+
REQUEST:
91+
92+
```
93+
GET /data/res* HTTP/1.1
94+
Host: example.org
95+
```
96+
97+
RESPONSE:
98+
99+
```
100+
HTTP/1.1 200 OK
101+
102+
<res1>
103+
a <https://example.org/ns/type#One> .
104+
105+
<res2>
106+
a <https://example.org/ns/type#Two> .
107+
```
108+
109+
Alternatively, one could ask the server to inline *all* resources of a
110+
container, which includes the triples corresponding to the container itself:
111+
112+
REQUEST:
113+
114+
```
115+
GET /data/* HTTP/1.1
116+
Host: example.org
117+
```
118+
119+
RESPONSE:
120+
121+
```
122+
HTTP/1.1 200 OK
123+
124+
<>
125+
a <http://www.w3.org/ns/ldp#BasicContainer> ;
126+
<http://www.w3.org/ns/ldp#contains> <res1>, <res2> .
127+
128+
<res1>
129+
a <https://example.org/ns/type#One> .
130+
131+
<res2>
132+
a <https://example.org/ns/type#Two> .
133+
```
134+
135+
Note: the aggregation process is not currently recursive, therefore it will not
136+
apply to children containers.
137+
138+
### Alternative: using SPARQL
139+
140+
Another possible way of reading and writing data is to use SPARQL. Currently,
141+
our Solid servers support a subset of [SPARQL
142+
1.0](http://www.w3.org/TR/rdf-sparql-query/), where each resource is its own
143+
SPARQL endpoint, accepting basic SELECT, INSERT and DELETE statements.
144+
145+
To read (query) a resource, the client can send a SPARQL `SELECT` through a
146+
form-encoded HTTP GET request. The server will use the given resource as the
147+
default graph that is being queried. The resource can be an RDF document or even
148+
a container. The response will be serialized using `application/json` mime type.
149+
150+
For instance, the client can send the following form-encoded query `SELECT *
151+
WHERE { ?s ?p ?o . }`:
152+
153+
REQUEST:
154+
155+
```
156+
GET /data/?query=SELECT%20*%20WHERE%20%7B%20%3Fs%20%3Fp%20%3Fo%20.%20%7D HTTP/1.1
157+
Host: example.org
158+
```
159+
160+
RESPONSE:
161+
162+
```
163+
HTTP/1.1 200 OK
164+
165+
{
166+
"head": {
167+
"vars": [ "s", "p", "o" ]
168+
},
169+
"results": {
170+
"ordered" : false,
171+
"distinct" : false,
172+
"bindings" : [
173+
{
174+
"s" : { "type": "uri", "value": "https://example.org/data/" },
175+
"p" : { "type": "uri", "value": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" },
176+
"o" : { "type": "uri", "value": "http://www.w3.org/ns/ldp#BasicContainer" }
177+
},
178+
{
179+
"s" : { "type": "uri", "value": "https://example.org/data/" },
180+
"p" : { "type": "uri", "value": "http://purl.org/dc/terms/title" },
181+
"o" : { "type": "literal", "value": "Basic container" }
182+
}
183+
]
184+
}
185+
}
186+
```
187+
188+
## Creating content
189+
190+
When creating new resources (directories or documents) using LDP, the client
191+
must indicate the type for the new resource that is going to be created. LDP
192+
uses `Link` headers with specific URI values, which in turn can be dereferenced
193+
to obtain additional information about each type of resource. Currently, our LDP
194+
implementation supports only [Basic Containers](http://www.w3.org/TR/ldp/#ldpbc).
195+
196+
LDP also offers a mechanism through which clients can provide a preferred name
197+
for the new resource through a header called `Slug`.
198+
199+
### Creating containers (directories)
200+
201+
To create a new *basic container* resource, the Link header value must be set
202+
to the following value:
203+
`Link: <http://www.w3.org/ns/ldp#BasicContainer>; rel="type"`
204+
205+
For example, to create a basic container called `data` under
206+
`https://example.org/`, the client will need to send the following POST request,
207+
with the Content-Type header set to `text/turtle`:
208+
209+
REQUEST:
210+
211+
```
212+
POST / HTTP/1.1
213+
Host: example.org
214+
Content-Type: text/turtle
215+
Link: <http://www.w3.org/ns/ldp#BasicContainer>; rel="type"
216+
Slug: data
217+
218+
<> <http://purl.org/dc/terms/title> "Basic container" .
219+
```
220+
221+
RESPONSE:
222+
223+
```
224+
HTTP/1.1 201 Created
225+
```
226+
227+
### Creating documents (files)
228+
229+
To create a new resource, the `Link` header value must be set to the following
230+
value:
231+
`Link: <http://www.w3.org/ns/ldp#Resource>; rel="type"`
232+
233+
For example, to create a resource called `test` under
234+
`https://example.org/data/`, the client will need to send the following POST
235+
request, with the Content-Type header set to `text/turtle`:
236+
237+
REQUEST:
238+
239+
```
240+
POST / HTTP/1.1
241+
Host: example.org
242+
Content-Type: text/turtle
243+
Link: <http://www.w3.org/ns/ldp#Resource>; rel="type"
244+
Slug: test
245+
246+
<> <http://purl.org/dc/terms/title> "This is a test file" .
247+
```
248+
249+
RESPONSE:
250+
251+
```
252+
HTTP/1.1 201 Created
253+
```
254+
255+
More examples can be found in the LDP [Primer document](http://www.w3.org/TR/ldp-primer/).
256+
257+
#### HTTP PUT to create
258+
259+
An alternative (though not standard) way of creating new resources is to use
260+
HTTP PUT. Although HTTP PUT is commonly used to overwrite resources, this way is
261+
usually preferred when creating new non-RDF resources (i.e. using a mime type
262+
different than `text/turtle`).
263+
264+
REQUEST:
265+
266+
```
267+
PUT /picture.jpg HTTP/1.1
268+
Host: example.org
269+
Content-Type: image/jpeg
270+
...
271+
```
272+
273+
RESPONSE :
274+
275+
```
276+
HTTP/1.1 201 Created
277+
```
278+
279+
Another useful Solid feature that is not yet part of the LDP spec deals with
280+
using HTTP PUT to *recursively* create new resources. This feature is really
281+
useful when the client wants to make sure it has absolute control over the URI
282+
namespace -- e.g. migrating from one personal data store to another. Although
283+
this feature is defined in HTTP1.1
284+
[RFC2616](https://tools.ietf.org/html/rfc2616), we decided to improve it
285+
slightly by having servers create the full path to the resource (including
286+
intermediate containers), if it didn't exist before. (If you're familiar with
287+
the Unix command line, think of it as `mkdir -p`.) For instance, a calendar app
288+
uses a URI pattern (structure) based on dates when storing new events (i.e.
289+
yyyy/mm/dd). Instead of performing several POST requests to create a month and a
290+
day container when switching to a new month, it could send the following request
291+
to create a new event resource called `event1`:
292+
293+
REQUEST:
294+
295+
```
296+
PUT /2015/05/01/event1 HTTP/1.1
297+
Host: example.org
298+
```
299+
300+
RESPONSE:
301+
302+
```
303+
HTTP/1.1 201 Created
304+
```
305+
306+
This request would then create a new resource called `event1`, as well as the
307+
missing intermediate resources -- containers for the month `05` and the day `01`
308+
under the parent container `/2015/`.
309+
310+
To avoid accidental overwrites, Solid servers must support `ETag` checking
311+
through the use of [If-Match or
312+
If-None-Match](https://tools.ietf.org/html/rfc2616#section-14.24) HTTP headers.
313+
314+
**IMPORTANT:** Using PUT to create standalone containers is not supported,
315+
because the behavior of PUT (overwrite) is not well defined for containers. You
316+
MUST use POST (as defined by LDP) to create containers alone.
317+
318+
#### Alternative: Using SPARQL
319+
320+
To write data, clients can send an HTTP PATCH request with a SPARQL payload to
321+
the resource in question. If the resource doesn't exist, it should be created
322+
through an LDP POST or through a PUT.
323+
324+
For instance, to update the `title` of the container from the previous example,
325+
the client would have to send a DELETE statement, followed by an INSERT
326+
statement. Multiple statements (delimited by a `;`) can be sent in the same
327+
PATCH request.
328+
329+
REQUEST:
330+
331+
```
332+
PATCH /data/ HTTP/1.1
333+
Host: example.org
334+
Content-Type: application/sparql-update
335+
336+
DELETE DATA { <> <http://purl.org/dc/terms/title> "Basic container" };
337+
INSERT DATA { <> <http://purl.org/dc/terms/title> "My data container" }
338+
```
339+
340+
RESPONSE:
341+
342+
```
343+
HTTP/1.1 200 OK
344+
```
345+
346+
**IMPORTANT:** There is currently no support for blank nodes and RDF lists in
347+
our SPARQL patches.
348+
349+
### Discovering server capabilities - the OPTIONS method
350+
351+
Returns a list of headers describing the server's capabilities.
352+
353+
REQUEST:
354+
355+
```
356+
OPTIONS /data/ HTTP/1.1
357+
Host: example.org
358+
```
359+
360+
RESPONSE:
361+
362+
```
363+
HTTP/1.1 200 OK
364+
Accept-Patch: application/json, application/sparql-update
365+
Accept-Post: text/turtle, application/ld+json
366+
Access-Control-Allow-Credentials: true
367+
Access-Control-Allow-Methods: OPTIONS, HEAD, GET, PATCH, POST, PUT, DELETE
368+
Access-Control-Allow-Origin: *
369+
Access-Control-Expose-Headers: User, Triples, Location, Link, Vary, Last-Modified, Content-Length
370+
Allow: OPTIONS, HEAD, GET, PATCH, POST, PUT, DELETE
371+
```

0 commit comments

Comments
 (0)