Copyright © 2009 IBM Corporation. All Rights Reserved.
This document describes the Graph Update Protocol, an update facility for RDF graphs. It uses a derivation of the Atom Publishing Protocol. Update operations are performed on a collection of named graphs in a Graph Store. Operations are provided to change existing RDF named graphs as well as to create and remove named graphs with the Graph Store.
This document is made available by the W3 Consortium for discussion only. This indicates no endorsement of its content, nor that the Consortium has had any editorial control in it preparation, nor that the Consortium has, is, or will be allocating any resources to the issues addressed by this document.
This document is based upon the IBM Jazz Foundation Index Store Update API, a capability described and implemented in the IBM Jazz Foundation for the update of the graph store used to index resources stored within a Jazz Foundation Server instance.
The Graph Update Protocol is intended to allow the addition, replacement or deletion of named graphs from an RDF Graph Store. It is intended to be a standard mechanism by which updates to a remote RDF Graph Store can be described and transmitted. The Graph Update Protocol is inspired by the Atom Publishing Protocol in it's use of HTTP verbs to provide a RESTful protocol for managing named graphs in an RDF Graph Store.
The Graph Update Protocol provides the following facilities:
Related work:
The specification presented here is for a RESTful API for updating graphs within an RDF Graph Store. The intent is to allow a programmatic client the ability to create new graphs, update, replace and delete existing graphs using a simple HTTP binding.
In this specification the following definitions shall be used.
Examples are shown in the following format, note that the preceding ">" indicates a message from client to the server and the "<" indicates response back to the client.
> POST /graphstore/update HTTP/1.1 > Host: client.example.com > Date: 12-02-2008T18:42:00 > Content-Type: text/plain > Content-Length: 83 > > <http://example.com/res.rdf> <http://purl.org/dc/terms/title> "My Resource" . < HTTP/1.1 201 CREATED < Date: 12-02-2008T18:42:30 < Content-Length: 0 < Location: /graphstore/update/12-02-2008T18:42:30
The Graph Update Protocol supports the insertion of a new Named Graph into the Graph Store using the HTTP POST method to a store-specific URI, returning a new URI identifying the graph in the graph store. The protocol then allows operations on this named graph using standard HTTP methods against the URI returned from the creation action.
The URI for the graph store is obviously implementation and installation
specific, in the specification below we will use the URI template
{graph-store}
instead of a specific URI. Similarly the URI for a
particular graph managed by the graph store is specific and the template
{graph-uri}
will be used.
The following table summarizes the methods used to manage graphs in the graph store. Note that those methods marked in italics are optional, a server may or may not provide these methods however all other methods must be provided and must be implemented according to the required features of the protocol described in the sections below.
Method | URI | Comments |
---|---|---|
POST |
{graph-store} |
Inserts a graph into the store. |
* |
{graph-store} |
Not permitted - returns 405 (Method not allowed). |
GET |
{graph-uri} |
Retrieve the graph identified by the URI. |
HEAD |
{graph-uri} |
Retrieve the headers for the graph identified by the URI. |
PUT |
{graph-uri} |
Replace the graph identified by the URI. |
PATCH |
{graph-uri} |
Update the graph identified by the URI. |
DELETE |
{graph-uri} |
Delete the graph identified by the URI. |
* |
{graph-uri} |
Not permitted - returns 405 (Method not allowed). |
Inserting a graph is performed using an HTTP POST method against the
{graph-store}
URI. A client may provide a value to the server to
help construct the URI for the new graph in the HTTP Graph
request
header (this is similar to the Slug
or Name
header
described in the Atom Publishing Protocol). The server is at liberty to create
a URI of any reasonable form, but unique for any successfully created graph.
This resulting URI is returned to the client in the HTTP Location
response header. If the client does not provide a Graph
header on
the request the server may use any reasonable value in constructing the graph
URI. Therefore the Graph
header is optional in a request, however
the Location
header is required in the response.
The graph to insert is included as the body of the HTTP message and may be
provided in any reasonable representation the server can process (e.g.
N-Triples, Turtle, N3, RDF/XML), and the representation is identified by the
client using the standard HTTP Content-Type
request header. If the
representation cannot be processed by the server the server must respond with a
415 error, otherwise it should be parsed and processed. If the server fails to
parse the message body, i.e. the server accepted the value of the
Content-Type
header but the body was not a legal resource
according to that type, then the server must respond with a 400 error.
To allow for concurrent modification checks the server must also provide a
valid HTTP ETag
response header in the response to a creation
request.
The expected responses possible from the graph store are therefore:
Location
header that
identifies the newly inserted graph.Graph
header
was provided that already exists or the message body could not be parsed
as a legal representation of a graph.Content-Type
HTTP header identifies a
representation that cannot be handled by the graph store.Retrieving a graph is an optional feature of the protocol, it may not be
possible for the server to construct and return the complete contents of a
named graph in an appropriate manner, and as this protocol is intended to be
used in conjunction with the standard SPARQL protocol the graph should be
retrievable using standard SPARQL queries. However, it must be possible to
retrieve the current ETag
value for a named graph and so while the
GET method is optional a server must support the use of HEAD on a
{graph-uri}
which will return the HTTP ETag
response
header.
Where a server implements the GET method it may also, optionally, provide
content-negotiation in the standard HTTP manner using a client-specified HTTP
Accept
request header. This allows for the client to specify the
particular representation(s) it would prefer and the server can then pick the
most appropriate representation to return. If a server provides this feature
then the error 415 identifies the case that no requested representation can be
provided by the server.
The expected responses possible from the graph store are therefore:
ETag
response header,ETag
, Content-Type
and
Content-Length
response header as well as the graph
represented in a form compatible with the client's specified HTTP
Accept
request header.{graph-uri}
specified does not identify a named graph
in the graph store.{graph-uri}
specified identifies a named graph that
has been removed from the graph store. This is an optional response, if
the server is able to track deleted graphs then this response should be
used, else the server should respond with 404.Accept
request header that
cannot be satisfied by the server to create a valid response.Replacing a graph is performed using an HTTP PUT method against the
{graph-store}
URI. The body of the request method is a valid graph
representation (see section 2.2 above), and the current value of the graph will
be replaced entirely by the graph provided in the request.
The server must provide for concurrent modification protection, specifically
using entity tag values on all update requests. This requires the client to
provide an entity tag in either an HTTP If-Match
or
If-None-Match
request header which is returned by the server on
all update methods or by retrieving the graph (using either GET or HEAD).
The expected responses possible from the graph store are therefore:
ETag
response header.If-Match
or
If-None-Match
request header, or{graph-uri}
specified does not identify a named graph
in the graph store.If-Match
or If-None-Match
request header does
not match the current value for the graph. This implies that the graph
has been concurrently modified between the time the client retrieved the
entity tag for the graph and this attempt to update it.{graph-uri}
specified identifies a named graph that
has been removed from the graph store. This is an optional response, if
the server is able to track deleted graphs then this response should be
used, else the server should respond with 404.Accept
request header that
cannot be satisfied by the server to create a valid response.Updating a graph is an optional feature, performed using an HTTP PATCH
method against the {graph-store}
URI. If supported the server must
accept some representation that allows for the identification of the difference
between the existing state of the graph and the expected end state; for example
the Delta ontology.
The server must provide for concurrent modification protection, specifically
using entity tag values on all update requests. This requires the client to
provide an entity tag in either an HTTP If-Match
or
If-None-Match
request header which is returned by the server on
all update methods or by retrieving the graph (using either GET or HEAD).
The expected responses possible from the graph store are therefore:
ETag
response header.If-Match
or
If-None-Match
request header, or{graph-uri}
specified does not identify a named graph
in the graph store.If-Match
or If-None-Match
request header does
not match the current value for the graph. This implies that the graph
has been concurrently modified between the time the client retrieved the
entity tag for the graph and this attempt to update it.{graph-uri}
specified identifies a named graph that
has been removed from the graph store. This is an optional response, if
the server is able to track deleted graphs then this response should be
used, else the server should respond with 404.Deleting a graph is performed using an HTTP DELETE method against the
{graph-store}
URI. No body should be provided in the request,
which also implies that no HTTP Content-Type
or
Content-Length
request headers; if these are provided they will be
ignored.
The server must provide for concurrent modification protection, specifically
using entity tag values on all update requests. This requires the client to
provide an entity tag in either an HTTP If-Match
or
If-None-Match
request header which is returned by the server on
all update methods or by retrieving the graph (using either GET or HEAD).
The expected responses possible from the graph store are therefore:
ETag
response header.If-Match
or
If-None-Match
request header. {graph-uri}
specified does not identify a named graph
in the graph store.If-Match
or If-None-Match
request header does
not match the current value for the graph. This implies that the graph
has been concurrently modified between the time the client retrieved the
entity tag for the graph and this attempt to update it.{graph-uri}
specified identifies a named graph that
has been removed from the graph store. This is an optional response, if
the server is able to track deleted graphs then this response should be
used, else the server should respond with 404.Exposing RDF data for update creates many security issues which any deployment must be aware of, and consider the risks involved. While this specification does not provide a detailed security specification it is expected that servers provide mechanisms for authentication of users and authorizations of update actions.
While the details of implementation are out of scope of this specification it is expected that servers make use of the standard HTTP authentication mechanism and associated error codes listed below:
In the following examples the URI templates described above have the
following values where {identifier} is either taken from the client-provided
Graph
request header, or assigned by the server.
{graph-store}
-
http://example.com/graphstore/update
{graph-uri}
-
http://example.com/graphstore/graph/{identifier}
The following example demonstrates the client requesting the insertion of a graph into the graph store providing an explicit value to be used for the graph identifier.
> POST /graphstore/update HTTP/1.1 > Host: client.example.com > Date: 12-02-2008T18:42:00 > Content-Type: text/plain > Content-Length: 83 > Graph: my-resource > > <http://example.com/res.rdf> <http://purl.org/dc/terms/title> "My Resource" . < HTTP/1.1 201 CREATED < Date: 12-02-2008T18:42:30 < Location: http://example.com/graphstore/graph/my-resource < ETag: "8726363623523"
Graph
request header.Content-Type
request
header to the corresponding "text/plain" value.Location
response header,
the URI of the newly created graph.ETag
response header, the
entity tag value of the the newly created graph.Alternatively the client could have left out the Graph
request
header and the server would have created and used some unique value in the
place of "my-resource" in the resulting URI.
The following example demonstrates an attempt to replace the graph created above, however the client has specified the wrong graph URI in the request.
> PUT /graphstore/graph/my-bad-resource HTTP/1.1 > Host: client.example.com > Date: 12-02-2008T18:42:00 > Content-Type: text/plain > Content-Length: 83 > > <http://example.com/res.rdf> <http://purl.org/dc/terms/title> "New Resource" . < HTTP/1.1 404 NOT FOUND
The following example uses the correct URI now but does not include the entity tag value used to ensure that the request takes concurrent modification into account.
> PUT /graphstore/graph/my-resource HTTP/1.1 > Host: client.example.com > Date: 12-02-2008T18:42:00 > Content-Type: text/plain > Content-Length: 83 > > <http://example.com/res.rdf> <http://purl.org/dc/terms/title> "New Resource" . < HTTP/1.1 400 BAD REQUEST
The following example uses the correct URI now but includes an invalid entity tag value.
> PUT /graphstore/graph/my-resource HTTP/1.1 > Host: client.example.com > Date: 12-02-2008T18:42:00 > Content-Type: text/plain > Content-Length: 83 > If-Match: "1111111111111" > > <http://example.com/res.rdf> <http://purl.org/dc/terms/title> "New Resource" . < HTTP/1.1 409 CONFLICT
The following example specifies a complete and correct request.
> PUT /graphstore/graph/my-resource HTTP/1.1 > Host: client.example.com > Date: 12-02-2008T18:42:00 > Content-Type: text/plain > Content-Length: 83 > If-Match: "8726363623523" > > <http://example.com/res.rdf> <http://purl.org/dc/terms/title> "New Resource" . < HTTP/1.1 200 OK < Date: 12-02-2008T18:44:22 < ETag: "8726343622134"
If-Match
request header.Content-Type
request
header to the corresponding "text/plain" value.ETag
response header, the
entity tag value of the the updated graph.The following example shows how the HTTP HEAD method can be used to retrieve the entity tag value, required for update requests.
> HEAD /graphstore/graph/my-resource HTTP/1.1 > Host: client.example.com > Date: 12-02-2008T18:42:00 < HTTP/1.1 200 OK < Date: 12-02-2008T18:44:22 < ETag: "8726343622134"
Our example server does support the required HEAD method as shown above, but does not support the optional GET method. When the client issues a GET method the server responds with the 405 error message as described in the specification above.
> GET /graphstore/graph/my-resource HTTP/1.1 > Host: client.example.com > Date: 12-02-2008T18:42:00 < HTTP/1.1 405 METHOD NOT ALLOWED
The following example demonstrates a request to delete the resource shown in the examples so far.
> DELETE /graphstore/graph/my-bad-resource HTTP/1.1 > Host: client.example.com > Date: 12-02-2008T18:42:00 < HTTP/1.1 200 OK
Note that in this case no HTTP ETag
response header is
provided, the graph has been deleted and therefore has no state that can be
represented by an entity tag.
Our example server keeps track of graphs that have been deleted, therefore if the client attempts to perform another HEAD on the graph the server is able to return 410 instead of the more general 404.
> HEAD /graphstore/graph/my-resource HTTP/1.1 > Host: client.example.com > Date: 12-02-2008T18:42:00 < HTTP/1.1 410 GONE