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

Corrections and clarifications of REST API Spec #103

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 89 additions & 62 deletions api-rest.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
# Solid HTTPS REST API Spec

**Note:** This spec is a component of the parent
***Note:** This spec is a component of the parent
[Solid specification](README.md); the parent spec and all its components are
versioned as a whole.
versioned as a whole.*

## Reading Resources

Resources can be commonly accessed (i.e. read) using HTTP GET requests. Solid
Resources can be commonly accessed (i.e., read) using HTTP `GET` requests. Solid
servers are encouraged to perform content negotiation for RDF resources,
depending on the value of the `Accept` header.

**IMPORTANT:** a default `Content-Type: text/turtle` will be used for requests
***IMPORTANT:** a default `Content-Type: text/turtle` will be used for requests
for RDF resources or views (containers) that do not have an `Accept`
header.
header.*

### Streams

Being LDP (BasicContainer) compliant, Solid servers MUST return a full listing
Being LDP (`BasicContainer`) compliant, Solid servers MUST return a full listing
of container contents when receiving requests for containers. For every resource
in a container, a Solid server may include additional metadata, such as the time
the resource was modified, the size of the resource, and more importantly any
Expand All @@ -31,14 +31,14 @@ container maps to a file or a directory on the server, using the [POSIX
vocabulary](http://www.w3.org/ns/posix/stat#). Here is an example that reflects
how our current server implementations handle such a request:

REQUEST:
**REQUEST**

```http
GET /
Host: example.org
```

RESPONSE:
**RESPONSE**

```http
HTTP/1.1 200 OK
Expand All @@ -58,50 +58,51 @@ HTTP/1.1 200 OK
<http://www.w3.org/ns/posix/stat#size> "780" .
```

#### Globbing (inlining on GET)
#### Globbing (inlining on `GET`)

**Note: this feature is _at risk_ of being
[changed](https://github.com/solid/solid-spec/pull/148)
or [removed](https://github.com/solid/solid-spec/pull/151).
Please join the discussion.
Code depending on this will still work for now.**

We have found that in some cases, using the existing LDP features was not
enough. For instance, to optimize certain applications we needed to aggregate
all RDF resources from a container and retrieve them with a single GET
In some cases, we have found that using the existing LDP features was not
enough. For instance, to optimize certain applications, we needed to aggregate
all RDF resources from a container and retrieve them with a single `GET`

operation. We implemented this feature on the servers and decided to call it
"globbing". Similar to [UNIX shell
glob](https://en.wikipedia.org/wiki/Glob_(programming)), doing a GET on any URI
glob](https://en.wikipedia.org/wiki/Glob_(programming)), doing a `GET` on any URI
which ends with a `*` will return an aggregate view of all the resources that
match the indicated pattern.

For example, let's assume that `/data/res1` and `/data/res2` are two resources
containing one triple each, which defines their type as follows:

For *res1*:
**For *res1***

```ttl
<> a <https://example.org/ns/type#One> .
```

For *res2*:
**For *res2***

```ttl
<> a <https://example.org/ns/type#Two> .
```

If one would like to fetch all resources of a container beginning with `res`
(e.g. `/data/res1`, `/data/res2`) in one request, they could do a GET on
(e.g., `/data/res1`, `/data/res2`) in one request, they could do a `GET` on
`/data/res*` as follows.

REQUEST:
**REQUEST**

```http
GET /data/res* HTTP/1.1
Host: example.org
```

RESPONSE:
**RESPONSE**

```http
HTTP/1.1 200 OK
Expand All @@ -117,14 +118,14 @@ HTTP/1.1 200 OK
Alternatively, one could ask the server to inline *all* resources of a
container, which includes the triples corresponding to the container itself:

REQUEST:
**REQUEST**

```http
GET /data/* HTTP/1.1
Host: example.org
```

RESPONSE:
**RESPONSE**

```http
HTTP/1.1 200 OK
Expand All @@ -149,24 +150,24 @@ apply to children containers.
Another possible way of reading and writing data is to use SPARQL. Currently,
our Solid servers support a subset of [SPARQL
1.1](https://www.w3.org/TR/sparql11-overview/), where each resource is its own
SPARQL endpoint, accepting basic SELECT, INSERT and DELETE statements.
SPARQL endpoint, accepting basic `SELECT`, `INSERT`, and `DELETE` statements.

To read (query) a resource, the client can send a SPARQL `SELECT` through a
form-encoded HTTP GET request. The server will use the given resource as the
form-encoded HTTP `GET` request. The server will use the given resource as the
default graph that is being queried. The resource can be an RDF document or even
a container. The response will be serialized using `application/json` mime type.
a container. The response will be serialized using `application/json` MIME type.

For instance, the client can send the following form-encoded query `SELECT *
For instance, the client can form-encode and send the query `SELECT *
WHERE { ?s ?p ?o . }`:

REQUEST:
**REQUEST**

```http
GET /data/?query=SELECT%20*%20WHERE%20%7B%20%3Fs%20%3Fp%20%3Fo%20.%20%7D HTTP/1.1
Host: example.org
```

RESPONSE:
**RESPONSE**

```http
HTTP/1.1 200 OK
Expand Down Expand Up @@ -213,10 +214,10 @@ to the following value:
`Link: <http://www.w3.org/ns/ldp#BasicContainer>; rel="type"`

For example, to create a basic container called `data` under
`https://example.org/`, the client will need to send the following POST request,
with the Content-Type header set to `text/turtle`:
`https://example.org/`, the client will need to send the following `POST` request,
with the `Content-Type` header set to `text/turtle`:

REQUEST:
**REQUEST**

```http
POST / HTTP/1.1
Expand All @@ -229,7 +230,7 @@ Slug: data
<> <http://purl.org/dc/terms/title> "Basic container" .
```

RESPONSE:
**RESPONSE**

```http
HTTP/1.1 201 Created
Expand All @@ -245,10 +246,10 @@ value:
`Link: <http://www.w3.org/ns/ldp#Resource>; rel="type"`

For example, to create a resource called `test` under
`https://example.org/data/`, the client will need to send the following POST
request, with the Content-Type header set to `text/turtle`:
`https://example.org/data/`, the client will need to send the following `POST`
request, with the `Content-Type` header set to `text/turtle`:

REQUEST:
**REQUEST**

```http
POST / HTTP/1.1
Expand All @@ -261,22 +262,22 @@ Slug: test
<> <http://purl.org/dc/terms/title> "This is a test file" .
```

RESPONSE:
**RESPONSE**

```http
HTTP/1.1 201 Created
```

More examples can be found in the LDP [Primer document](http://www.w3.org/TR/ldp-primer/).

#### HTTP PUT to create
#### HTTP `PUT` to create

An alternative (though not common) way of creating new resources is to use
HTTP PUT. Although HTTP PUT is commonly used to overwrite resources, this way is
usually preferred when creating new non-RDF resources (i.e. using a mime type
different than `text/turtle`).
HTTP `PUT`. Although HTTP `PUT` is commonly used to overwrite resources, this way is
usually preferred when creating new non-RDF resources (i.e., using a different MIME
type than `text/turtle`).

REQUEST:
**REQUEST**

```http
PUT /picture.jpg HTTP/1.1
Expand All @@ -285,23 +286,23 @@ Content-Type: image/jpeg
...
```

RESPONSE :
**RESPONSE**

```http
HTTP/1.1 201 Created
```

Another useful Solid feature that is not yet part of the LDP spec deals with
using HTTP PUT to *recursively* create new resources. This feature is really
using HTTP `PUT` to *recursively* create new resources. This feature is really
useful when the client wants to make sure it has absolute control over the URI
namespace -- e.g. migrating from one personal data store to another. Although
namespace -- e.g., migrating from one personal data store to another. Although
this feature is defined in HTTP1.1
[RFC2616](https://tools.ietf.org/html/rfc2616), we decided to improve it
slightly by having servers create the full path to the resource (including
intermediate containers), if it didn't exist before. (If you're familiar with
the Unix command line, think of it as `mkdir -p`.) For instance, a calendar app
uses a URI pattern (structure) based on dates when storing new events (i.e.
yyyy/mm/dd). Instead of performing several POST requests to create a month and a
uses a URI pattern (structure) based on dates when storing new events (i.e.,
`yyyy/mm/dd`). Instead of performing several POST requests to create a month and a
day container when switching to a new month, it could send the following request
to create a new event resource called `event1`:

Expand All @@ -323,25 +324,25 @@ missing intermediate resources -- containers for the month `05` and the day `01`
under the parent container `/2015/`.

To avoid accidental overwrites, Solid servers must support `ETag` checking
through the use of [If-Match or
If-None-Match](https://tools.ietf.org/html/rfc2616#section-14.24) HTTP headers.
through the use of [`If-Match` or
`If-None-Match`](https://tools.ietf.org/html/rfc2616#section-14.24) HTTP headers.

**IMPORTANT:** Using PUT to create standalone containers is not supported,
because the behavior of PUT (overwrite) is not well defined for containers. You
MUST use POST (as defined by LDP) to create containers alone.
***IMPORTANT:** Using `PUT` to create standalone containers is not supported,
because the behavior of `PUT` (overwrite) is not well defined for containers. You
MUST use `POST` (as defined by LDP) to create containers alone.*

#### Alternative: Using SPARQL

To write data, clients can send an HTTP PATCH request with a SPARQL payload to
To write data, clients can send an HTTP `PATCH` request with a SPARQL payload to
the resource in question. If the resource doesn't exist, it should be created
through an LDP POST or through a PUT.
through an LDP `POST` or through a `PUT`.

For instance, to update the `title` of the container from the previous example,
the client would have to send a DELETE statement, followed by an INSERT
the client would have to send a `DELETE` statement, followed by an `INSERT`
statement. Multiple statements (delimited by a `;`) can be sent in the same
PATCH request.
`PATCH` request.

REQUEST:
**REQUEST**

```http
PATCH /data/ HTTP/1.1
Expand All @@ -353,27 +354,30 @@ DELETE DATA { <> <http://purl.org/dc/terms/title> "Basic container" };
INSERT DATA { <> <http://purl.org/dc/terms/title> "My data container" }
```

RESPONSE:
**RESPONSE**

```http
HTTP/1.1 200 OK
```

**IMPORTANT:** There is currently no support for blank nodes and RDF lists in
our SPARQL patches.
***IMPORTANT:** There is currently no support for blank nodes nor RDF lists in
our SPARQL patches.*

### Discovering server capabilities - the OPTIONS method
### Discovering server capabilities - the `OPTIONS` method

Returns a list of headers describing the server's capabilities.
Returns a list of headers describing the server's capabilities (with an
asterisk \[`*`\] as the `request-target`), or the subset of those capabilities
which are made available on a specific resource (if specified as the
`request-target`).

REQUEST:
**REQUEST**

```http
OPTIONS /data/ HTTP/1.1
OPTIONS * HTTP/1.1
Host: example.org
```

RESPONSE:
**RESPONSE**

```http
HTTP/1.1 200 OK
Expand All @@ -384,6 +388,29 @@ Access-Control-Allow-Methods: OPTIONS, HEAD, GET, PATCH, POST, PUT, DELETE
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: User, Triples, Location, Link, Vary, Last-Modified, Content-Length
Allow: OPTIONS, HEAD, GET, PATCH, POST, PUT, DELETE
MS-Author-Via: DAV, SPARQL
```

**REQUEST**

```http
OPTIONS /data/ HTTP/1.1
Host: example.org
```

**RESPONSE**

```http
HTTP/1.1 200 OK
Accept-Patch: application/sparql-update
Accept-Post: text/turtle
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: OPTIONS, HEAD, GET, PATCH, POST
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: User, Triples, Location, Link, Vary, Last-Modified, Content-Length
Allow: OPTIONS, HEAD, GET, PATCH, POST
MS-Author-Via: SPARQL

```

### WAC-Allow headers
Expand Down