Graph Update Protocol

A protocol for updating RDF graphs

This version:
2009-07-08.
Authors:
Simon Johnston, IBM
Scott Rich, IBM

Abstract

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.

Status of This Document

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.


Table of Contents

  1. Introduction
  2. The Protocol
  3. Examples

1 Introduction

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:

1.1 Background

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.

Client
A programmatic client sending messages to the RDF Graph Store using the protocol described herein.
RDF Graph Store
Like an RDF Dataset operated on by SPARQL, a Graph Store zero or more named graphs, but does not have an unnamed graph. Unlike an RDF dataset, named graphs can be added or deleted to a graph store.
Server
Some service providing an implementation of the protocol described herein.

1.2 Document Conventions

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

2 The Protocol

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.

2.1 Protocol Overview

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).

2.2 Insert Graph

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:

201 (Created)
The graph was successfully added to the graph store. The graph store will return a URI in the HTTP Location header that identifies the newly inserted graph.
400 (Bad Request)
This error may be returned because either a Graph header was provided that already exists or the message body could not be parsed as a legal representation of a graph.
415 (Unsupported Media Type)
The required Content-Type HTTP header identifies a representation that cannot be handled by the graph store.

2.3 Retrieve Graph

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:

200 (OK)
The request was successful;
If the method was HEAD then the response will at least contain the HTTP ETag response header,
If the method was GET then the response will at least contain the HTTP 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.
404 (Not Found)
The {graph-uri} specified does not identify a named graph in the graph store.
410 (Gone)
The {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.
415 (Unsupported Media Type)
The client provided an HTTP Accept request header that cannot be satisfied by the server to create a valid response.

2.4 Replace Graph

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:

200 (OK)
The request was successful, the response must contain a value for the HTTP ETag response header.
400 (Bad Request)
The request was either:
did not contain either an HTTP If-Match or If-None-Match request header, or
did not contain a message body (graph representation) at all, or
the message body could not be parsed as a legal representation of a graph.
404 (Not Found)
The {graph-uri} specified does not identify a named graph in the graph store.
409 (Conflict)
The entity tag information provided in either the HTTP 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.
410 (Gone)
The {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.
415 (Unsupported Media Type)
The client provided an HTTP Accept request header that cannot be satisfied by the server to create a valid response.

2.5 Update Graph

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:

200 (OK)
The request was successful, the response must contain a value for the HTTP ETag response header.
400 (Bad Request)
The request was either:
did not contain either an HTTP If-Match or If-None-Match request header, or
did not contain a message body (graph representation) at all, or
the message body could not be parsed as a legal representation of a graph diff.
404 (Not Found)
The {graph-uri} specified does not identify a named graph in the graph store.
409 (Conflict)
The entity tag information provided in either the HTTP 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.
410 (Gone)
The {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.

2.6 Delete Graph

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:

200 (OK)
The request was successful, the response must contain a value for the HTTP ETag response header.
400 (Bad Request)
The request did not contain either an HTTP If-Match or If-None-Match request header.
404 (Not Found)
The {graph-uri} specified does not identify a named graph in the graph store.
409 (Conflict)
The entity tag information provided in either the HTTP 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.
410 (Gone)
The {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.

2.7 Security Responses

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:

401 (Unauthorized)
The server requires clients to be authenticated before update operations may be performed, the client request has not provided authentication headers.
403 (Forbidden)
The authenticated user does not have permission to perform the requested operation.

3 Examples

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.

3.1 Inserting Graph with Explicit 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"

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.

3.2 Replacing a Graph

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"

3.3 Retrieving Graph HTTP Headers

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

3.4 Deleting a Graph

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

References

[SPARQL-P]
SPARQL Protocol for RDF, Kendall Clark, Lee Feigenbaum, Elias Torres (editors), W3C Recommendation.
[SPARQL-Q]
SPARQL Query Language for RDF, Eric Prud'hommeaux, Andy Seaborne (editors), W3C Recommendation.
[SPARQL-R]
SPARQL Query Results XML Format , D. Beckett (editor), W3C Recommendation.
[RFC2616]
RFC 2616 Hypertext Transfer Protocol -- HTTP/1.1, R. Fielding, J. Gettys, J. Mogul, H. Frystyk, L. Masinter, P. Leach, T. Berners-Lee.
[RFC3986]
RFC 3986 Uniform Resource Identifier (URI): Generic Syntax, T. Berners-Lee, R. Fielding, L. Masinter.
[RFC3987]
RFC 3987 Internationalized Resource Identifiers (IRIs), M. Dürst , M. Suignard.
[RFC5023]
RFC 5023 The Atom Publishing Protocol, J. Gregorio, B. de hOra.
[UNICODE]
The Unicode Standard, Version 4. ISBN 0-321-18578-1, as updated from time to time by the publication of new versions. The latest version of Unicode and additional information on versions of the standard and of the Unicode Character Database is available at http://www.unicode.org/unicode/standard/versions/.
[URI-T]
URI Template, J. Gregorio, M. Hadley, M. Nottingham, D. Orchard.

 

--=_mixed 00634040852575ED_=--