From eaea014699d91fef05377df29e71257d04d7cdd3 Mon Sep 17 00:00:00 2001 From: Ted Thibodeau Jr Date: Mon, 22 Jan 2018 13:13:28 -0500 Subject: [PATCH] Corrections and clarifications of REST API Spec Some markup and language tweaks for better reader clarity; some punctuation fixes for typos. Significant changes to **the `OPTIONS` method** section which did not conform to RFC 7231 -- https://tools.ietf.org/html/rfc7231#section-4.3.7 -- as the example was for the specific `/data/` container, but the description was server-wide. --- api-rest.md | 150 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 88 insertions(+), 62 deletions(-) diff --git a/api-rest.md b/api-rest.md index ef9bfc6..eea2e8d 100644 --- a/api-rest.md +++ b/api-rest.md @@ -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 @@ -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 @@ -58,44 +58,44 @@ HTTP/1.1 200 OK "780" . ``` -#### Globbing (inlining on GET) +#### Globbing (inlining on `GET`) -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 . ``` -For *res2*: +**For *res2*** ```ttl <> a . ``` 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 @@ -111,14 +111,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 @@ -143,24 +143,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 @@ -207,10 +207,10 @@ to the following value: `Link: ; 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 @@ -223,7 +223,7 @@ Slug: data <> "Basic container" . ``` -RESPONSE: +**RESPONSE** ```http HTTP/1.1 201 Created @@ -236,10 +236,10 @@ value: `Link: ; 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 @@ -252,7 +252,7 @@ Slug: test <> "This is a test file" . ``` -RESPONSE: +**RESPONSE** ```http HTTP/1.1 201 Created @@ -260,14 +260,14 @@ 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 standard) 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 MIME type +other than `text/turtle`). -REQUEST: +**REQUEST** ```http PUT /picture.jpg HTTP/1.1 @@ -276,23 +276,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`: @@ -314,25 +314,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 @@ -344,27 +344,30 @@ DELETE DATA { <> "Basic container" }; INSERT DATA { <> "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 @@ -375,4 +378,27 @@ 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 + ```