Re: IBM Graph Update Protocol document

Thanks, Simon.

For those without HTML-friendly email clients, here's the URL to the 
document in our mailing list archives:

http://lists.w3.org/Archives/Public/public-rdf-dawg/2009JulSep/att-0040/SPARQL-UProtocol-20090707.html

Lee

Simon K Johnston wrote:
> All, the document(s) that describe our RESTful update protocol 
> (mentioned on the WG call two weeks ago) are behind a sign-up on our 
> Jazz.net site. So, I extracted the content and ensured it is a 
> stand-alone document and removed the Jazz formatting. As it would take a 
> while to rehost this on an IBM site without some sort of sign-up 
> protection I am posting to the mailing list so that we can at least use 
> the archive URL for the attachment as a reference.
> 
> 
> 
> Thanks,
> 
> ------------------------------------------------------------------------
> 
> /Simon K. Johnston (//_skjohn@us.ibm.com_/ <mailto:skjohn@us.ibm.com>/) 
> - STSM, Jazz Foundation Services
> Mobile: //_+1 (919) 200-9973_/ <tel:+1.919.200.9973>/
> Office: //_+1 (919) 595-0786_/ <tel:+1.919.595.0786>/ (tie-line: 
> //_268-6838_/ <tel:268.6838>/)
> Blog: //_http://www.ibm.com/developerworks/blogs/page/johnston_// /
> 
> ------------------------------------------------------------------------
> 
> 
>   Graph Update Protocol
> 
> 
>     A protocol for updating RDF graphs
> 
> This version:
>     2009-07-08.
> Authors:
>     Simon Johnston, IBM
>     Scott Rich, IBM
> 
> Copyright © 2009 IBM Corporation. All Rights Reserved.
> 
> ------------------------------------------------------------------------
> 
> 
>     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/ <https://jazz.net:443/wiki/bin/view/Main/JFSIndexStoreWriteAPI>, 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 <#sec_intro>
>    2. The Protocol <#sec_protocol>
>    3. Examples <#sec_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:
> 
>     * Insert new graph to an RDF Graph Store.
>     * Replace or update a graph within an RDF Graph Store.
>     * Delete a graph from an RDF Graph Store.
> 
> Related work:
> 
>     * SPARQL Update: A language for updating RDF graphs
>       <http://www.w3.org/Submission/SPARQL-Update/>.
>     * the wiki page SparqlUpdateLanguage
>       <http://esw.w3.org/topic/SparqlUpdateLanguage> for a related proposal
>     * Delta: an ontology for the distribution of differences between RDF
>       graphs <http://www.w3.org/DesignIssues/Diff>
> 
> 
>       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.
> 
>     * |{graph-store}| - |http://example.com/graphstore/update|
>     * |{graph-uri}| - |http://example.com/graphstore/graph/{identifier}|
> 
> 
>       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"
> 
>     * The client is providing an explicit identifier, "my-resource" to
>       the server using the |Graph| request header.
>     * The client is providing a graph in the request body with an
>       N-Triples representation and setting the HTTP |Content-Type|
>       request header to the corresponding "text/plain" value.
>     * The server responds with the status code 201, the new graph has
>       been inserted.
>     * The server provides, in the HTTP |Location| response header, the
>       URI of the newly created graph.
>     * The server provides, in the HTTP |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.
> 
> 
>       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"
> 
>     * The client specifies a correct value for the HTTP |If-Match|
>       request header.
>     * The client is providing a graph in the request body with an
>       N-Triples representation and setting the HTTP |Content-Type|
>       request header to the corresponding "text/plain" value.
>     * The server responds with the status code 200, the graph has been
>       replaced.
>     * The server provides, in the HTTP |ETag| response header, the
>       entity tag value of the the updated graph.
> 
> 
>       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 <http://www.w3.org/TR/rdf-sparql-protocol/>,
>     Kendall Clark, Lee Feigenbaum, Elias Torres (editors), W3C
>     Recommendation.
> [SPARQL-Q]
>     SPARQL Query Language for RDF
>     <http://www.w3.org/TR/rdf-sparql-query/>, Eric Prud'hommeaux, Andy
>     Seaborne (editors), W3C Recommendation.
> [SPARQL-R]
>     SPARQL Query Results XML Format
>     <http://www.w3.org/TR/rdf-sparql-XMLres/> , D. Beckett (editor), W3C
>     Recommendation. 
> [RFC2616]
>     RFC 2616 Hypertext Transfer Protocol -- HTTP/1.1
>     <http://www.ietf.org/rfc/rfc2616.txt>, R. Fielding, J. Gettys, J.
>     Mogul, H. Frystyk, L. Masinter, P. Leach, T. Berners-Lee.
> [RFC3986]
>     RFC 3986 Uniform Resource Identifier (URI): Generic Syntax
>     <http://www.ietf.org/rfc/rfc3986.txt>, T. Berners-Lee, R. Fielding,
>     L. Masinter. 
> [RFC3987]
>     RFC 3987 Internationalized Resource Identifiers (IRIs)
>     <http://www.ietf.org/rfc/rfc3987.txt>, M. Dürst , M. Suignard.
> [RFC5023]
>     RFC 5023 The Atom Publishing Protocol
>     <http://www.ietf.org/rfc/rfc5023.txt>, 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
>     <http://tools.ietf.org/html/draft-gregorio-uritemplate-03>, J.
>     Gregorio, M. Hadley, M. Nottingham, D. Orchard.
> 
>  
> 

Received on Wednesday, 8 July 2009 18:10:44 UTC