- From: Lee Feigenbaum <lee@thefigtrees.net>
- Date: Wed, 08 Jul 2009 14:09:41 -0400
- To: Simon K Johnston <skjohn@us.ibm.com>
- CC: public-rdf-dawg@w3.org
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