Copyright © 2013 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved. W3C liability, trademark and document use rules apply.
This document describes a set of best practices and simple approach for a read-write Linked Data architecture, based on HTTP access to web resources that describe their state using the RDF data model.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
This document was published by the Linked Data Platform Working Group as a Last Call Working Draft. This document is intended to become a W3C Recommendation. If you wish to make comments regarding this document, please send them to public-ldp-comments@w3.org (subscribe, archives). The Last Call period ends 02 September 2013. All comments are welcome.
Publication as a Last Call Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This is a Last Call Working Draft and thus the Working Group has determined that this document has satisfied the relevant technical requirements and is sufficiently stable to advance through the Technical Recommendation process.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This section is non-normative.
This document describes the use of HTTP for accessing, updating, creating and deleting resources from servers that expose their resources as Linked Data. It provides clarifications and extensions of the four rules of Linked Data [LINKED-DATA]:
1. Use URIs as names for things
2. Use HTTP URIs so that people can look up those names
3. When someone looks up a URI, provide useful information, using the standards (RDF*, SPARQL)
4. Include links to other URIs, so that they can discover more things
This specification discusses standard HTTP and RDF techniques and best practices that you should use, and anti-patterns you should avoid, when constructing clients and servers that read and write Linked Data resources.
A special type of Linked Data Platform Resource is a Container. Containers are very useful in building application models involving collections of homogeneous resources. For example, universities offer a collection of classes and have a collection of faculty members, each faculty member teaches a collection of courses, etc. This specification discusses how to work with containers. Resources can be added to containers in several ways. As a special case, members can both be created and added to a container by overloading the POST operation (see section 5.4 ).
Another contribution of this specification is how to deal with large amounts of data. Depending on the server’s capabilities, a GET request on a Linked Data Platform Resource returns a set of pages and uses a convention to access any subsequent page (see section 4.10 ).
The intention of this document is to enable additional rules and layered groupings of rules as additional specifications. The scope is intentionally narrow to provide a set of key rules for reading and writing Linked Data that most, if not all, other specifications will depend upon and implementations will support.
Terminology is based on W3C's Architecture of the World Wide Web [WEBARCH] and Hyper-text Transfer Protocol [HTTP11].
Any given program may be capable of being both a client and a server; our use of these terms refers only to the role being performed by the program for a particular connection, rather than to the program's capabilities in general. Likewise, any server may act as an origin server, proxy, gateway, or tunnel, switching behavior based on the nature of each request [HTTP11].
Sample resource representations are provided in text/turtle
format [TURTLE].
Commonly used namespace prefixes:
@prefix dcterms: <http://purl.org/dc/terms/>. @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>. @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>. @prefix ldp: <http://www.w3.org/ns/ldp#>. @prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this specification are to be interpreted as described in [RFC2119].
The status of the sections of Linked Data Platform 1.0 (this document) is as follows:
A conforming LDP server is an application program that processes HTTP requests and generates HTTP responses that conform to the rules defined in section 4. Linked Data Platform Resources and section 5. Linked Data Platform Containers.
A conforming LDP client is an application program that generates HTTP requests and processes HTTP responses that conform to the rules defined in section 4. Linked Data Platform Resources and section 5. Linked Data Platform Containers.
This section is non-normative.
Linked Data Platform Resources (LDPRs) are HTTP resources that conform to the simple patterns and conventions in this section. HTTP requests to access, modify, create or delete LDPRs are accepted and processed by LDPR servers. Most LDPRs are domain-specific resources that contain data for an entity in some domain, which could be commercial, governmental, scientific, religious, or other.
Some of the rules defined in this document provide clarification and refinement of the base Linked Data rules [LINKED-DATA]; others address additional needs.
The rules for Linked Data Platform Resources address basic questions such as:
Additional informative guidance is available on the working group's wiki that addresses deployment questions such as:
The following sections define the rules and guidelines for use of LDPRs. This document also explains how to include information about each member in the resource’s own representation and how to paginate the resource representation if it gets too big.
Request-URI of the LDPR is typically the subject of most triples in the response.
rdf:type
set explicitly. This makes the representations much more useful to
client applications that don’t support inferencing.
ETag header values.
rdf:type predicates, datatypes of
the objects of predicates, and the number of occurrences of predicates in an LDPR, but
servers SHOULD minimize those restrictions. Enforcement of
more complex constraints will greatly restrict the set of clients
that can modify resources. For some server applications, excessive
constraints on modification of resources may be required.
Link header
with a target URI of http://www.w3.org/ns/ldp/Resource, and
a link relation type of type (that is, rel="type")
in all responses to requests made
to the resource's HTTP Request-URI. This is notionally equivalent to the
presence of a (subject-URI, rdf:type, ldp:Resource) triple in the resource.
The HTTP Link header is the method by which servers assert their support for the LDP specification in a way
that clients can introspect dynamically at run-time. Conservative clients should note that
a server can host a mixture of LDPRs and other resources, and therefore there is no implication
that LDP support advertised on one HTTP Request-URI means that other
resources on the same server are also LDPRs. Each HTTP Request-URI needs to be
individually introspected by a conservative client, in the absence of outside information.
Request-URI when the resource already exists, and to the URI of the created resource when the request results
in the creation of a new resource.
GET Method for LDPRs.
text/turtle
representation of the requested LDPR [TURTLE].
text/turtle SHOULD be returned.
rdf:type.
rdf:type values
of a given LDPR can change over time.
This specification adds no new requirements on HTTP POST for LDPRs
even when the LDPR supports that method. This specification does not impose any
new requirement to support that method, and [HTTP11] makes it optional.
Creation of LDPRs can be done via POST (section 5.4 ) or
PUT (section 5.5 ) to a LDPC, see those
sections for more details.
This specification imposes the following new requirements on HTTP PUT for LDPRs
only when the LDPR supports that method. This specification does not impose any
new requirement to support that method, and [HTTP11] makes it optional.
PUT is performed on an existing resource, LDPR servers MUST
replace the entire persistent state of the identified resource with
the entity representation in the body of the request.
LDPR servers MAY ignore server managed properties such as dcterms:modified
and dcterms:creator if they are not under
client control. Any LDPR servers that wish
to support a more sophisticated merge of data provided by the client
with existing state stored on the server for a resource MUST use HTTP
PATCH, not HTTP PUT.
If-Match
header and HTTP ETags to ensure it isn’t
modifying a resource that has changed since the client last retrieved
its representation. LDPR servers SHOULD require the HTTP If-Match header and HTTP ETags
to detect collisions. LDPR servers MUST respond with status code 412
(Condition Failed) if ETags fail to match when there are no other
errors with the request [HTTP11]. LDPR servers that require conditional requests MUST respond with status code 428
(Precondition Required) when the absence of a precondition is the only reason for rejecting the request [RFC6585].
PUT to update the resource.
GET that
it doesn’t change whether it understands the predicates or not, when
its intent is to perform an update using HTTP PUT. The use of HTTP
PATCH instead of HTTP PUT for update avoids this burden for clients
[RFC5789].
PUT.
This specification imposes the following new requirements on HTTP DELETE for LDPRs
only when the LDPR supports that method. This specification does not impose any
new requirement to support that method, and [HTTP11] makes it optional.
Additional requirements on HTTP DELETE of LDPRs within containers can be found in
section 5.6 .
Request-URI.
After a successful HTTP DELETE, a subsequent HTTP GET on the same
Request-URI MUST result in a 404 (Not found) or 410 (Gone) status
code. Clients SHOULD note that servers MAY reuse a URI under some circumstances.
DELETE request. For example, it is acceptable for the server to
remove triples from other resources whose subject or object is the
deleted resource. It is also acceptable and common for LDPR servers to
not do this – behavior is server application specific.
Note that certain LDP mechanisms, such as paging, rely on HTTP headers, and HTTP generally requires that
HEAD responses include the same headers as GET responses.
Thus, implementers should also carefully read section 4.3
and section 4.9 .
HEAD method.This specification imposes the following new requirements on HTTP PATCH for LDPRs
only when the LDPR supports that method. This specification does not impose any
new requirement to support that method, and [HTTP11] makes it optional.
PATCH to allow modifications,
especially partial replacement, of their resources [RFC5789]. No
minimal set of patch document formats is mandated by this document.
PATCH.
POST (to an LDPC) and/or PUT should be used as the standard way to create new LDPRs.
PATCH MUST
include an Accept-Patch HTTP response header [RFC5789] on HTTP OPTIONS
requests, listing patch document media type(s) supported by the server.
This specification imposes the following new requirements on HTTP OPTIONS for LDPRs
beyond those in [HTTP11]. Other sections of this specification, for example
PATCH,
Accept-Post
and Paging,
add other requirements on OPTIONS responses.
OPTIONS method.OPTIONS request on the LDPR’s URL with the HTTP
Method tokens in the HTTP response header Allow.
This section is non-normative.
It sometimes happens that a resource is too large to reasonably transmit its representation in a single HTTP response. This will be especially true if the resource representation includes many triples both from its own representation and from the representations of any inlined resources. A client could anticipate that a resource will be too large - for example, a client tool that accesses defects may assume that an individual defect will usually be of sufficiently constrained size that it makes sense to request all of it at once, but that the container of all the defects ever created will typically be too big. Alternatively, a server could recognize that a resource that has been requested is too big to return in a single message.
To address this problem, LDPRs should support a technique called Paging. Paging can be achieved with a
simple RDF pattern. For each resource, <resourceURL>, we define a new
'first page' resource. In this example, its URL will be <resourceURL>?firstPage,
but servers are free to construct the URL as they see fit.
The triples in the representation of the each page
are typically a subset of the triples in the resource
- same subject, predicate and object.
LDPR servers may respond to requests for a resource by redirecting the client to the first page resource – using a 303 “See Other” redirect to the actual URL for the page resource. Alternatively, clients may introspect the resource for a paged representation and use it preferentially when available.
Looking at an example resource representing Example Co.'s customer
relationship data, we’ll split the response across two pages.
To find the URL of the first page, the client makes a OPTIONS request
to the resource's URL, and in the response looks for a HTTP Link
header with rel="first"; the target URI in the header is the URL
of the first page resource.
The client then
requests the first page as http://example.org/customer-relations?firstPage:
# The following is the representation of # http://example.org/customer-relations?firstPage @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>. @prefix dcterms: <http://purl.org/dc/terms/>. @prefix foaf: <http://xmlns.com/foaf/0.1/>. @prefix ldp: <http://www.w3.org/ns/ldp#>. @prefix o: <http://example.org/ontology/>. <http://example.org/customer-relations> a o:CustomerRelations; dcterms:title "The customer information for Example Co."; o:client <client#JohnZSmith>, <client#BettyASmith>, <client#JoanRSmith>. <http://example.org/customer-relations?firstPage> a ldp:Page; ldp:pageOf <http://example.org/customer-relations>; ldp:nextPage <http://example.org/customer-relations?p=2>. <client#JohnZSmith> a foaf:Person; o:status o:ActiveCustomer; foaf:name "John Z. Smith". <client#BettyASmith> a foaf:Person; o:status o:PreviousCustomer; foaf:name "Betty A. Smith". <client#BettyASmith> a foaf:Person; o:status o:PotentialCustomer; foaf:name "Joan R. Smith".
The server determines the size of the pages using application specific methods not defined within this specificiation. Note also, the actual name for the query parameter (such as ?p=2) is also defined by the server and not this specification.
The following example is the result of retrieving the representation for the next page:
# The following is the representation of # http://example.org/customer-relations?p=2 @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>. @prefix dcterms: <http://purl.org/dc/terms/>. @prefix foaf: <http://xmlns.com/foaf/0.1/>. @prefix ldp: <http://www.w3.org/ns/ldp#>. @prefix o: <http://example.org/ontology/>. <http://example.org/customer-relations> o:client <client#GlenWSmith>, <client#AlfredESmith>. <http://example.org/customer-relations?p=2> a ldp:Page; ldp:pageOf <http://example.org/customer-relations>; ldp:nextPage rdf:nil. <client#GlenWSmith> a foaf:Person; o:status o:ActiveCustomer, o:GoldCustomer; foaf:name "Glen W. Smith". <client#AlfredESmith> a foaf:Person; o:status o:ActiveCustomer, o:BronzeCustomer; foaf:name "Alfred E. Smith".
In this example, there are only two customers provided in the
final page. To indicate this is the last page, a value of rdf:nil is used for the ldp:nextPage
predicate of the page resource.
In addition to the requirements set forth in section 4.3 on HTTP GET, LDPR servers that support paging must also follow the requirements in this section
GET requests with an LDPR as the Request-URI,
LDPR servers that support paging SHOULD provide an HTTP Link
header whose target URI is the first page resource, and whose link relation type is first [RFC5988].
This is the mechanism by which clients discover the URL of the first page. If no such Link
header is present, then conservative clients will assume that the LDPR does not support paging.
For example, if there is a LDPR with URL <resourceURL> that supports paging and whose
first page URL is <resourceURL>?theFirstPage, then the corresponding link header
would be Link: <?theFirstPage>;rel="first".
The representation for any page, including the first, will include
the URL for the next page. See section 4.10 for additional details.
303 See
Other response with an HTTP Location header providing the first page resource URL.
ldp:nextPage and
object being the URL for the subsequent page.
<http://example.org/customer-relations?firstPage>
ldp:nextPage <http://example.org/customer-relations?p=2> .ldp:nextPage and object being rdf:nil.
<http://example.org/customer-relations?p=2>
ldp:nextPage rdf:nil .rdf:type and object is ldp:Page.
It also SHOULD have 1 triple to indicate the resource it is paging,
whose subject is the URL of the page, predicate is ldp:pageOf,
and object is the URL of the LDPR.
<http://example.org/customer-relations?firstPage>
rdf:type ldp:Page;
ldp:pageOf <http://example.org/customer-relations>.OPTIONS request on the LDPR’s URL with the HTTP
response header for link relations using the header name of Link and link relation type first [RFC5988].
Feature At Risk
The LDP Working Group proposes incorporation of the features described in this section.
Feedback, both positive and negative, is invited by sending email to the mailing list in Status of This Document.
This section is non-normative.
Servers whose resources are relatively granular may wish to optimistically provide more information in a response than what the client actually requested, in order to reduce the average number of client application HTTP flows. LDP provides some basic building blocks to enable this, that implementations can re-use to build complete solutions, and they may serve as complete solutions in applications with sufficient controls on resource content. These building blocks are resource inlining and member inlining.
LDP does not provide clients with any way to detect whether or not the server is capable of inlining (all its resources or any specific resource), nor does it provide clients with any way to influence which (if any) resources are inlined in any given response.
Servers can return extra triples on any response, but fail to meet the definition of resource inlining,
by either returning a subset of the other resource(s) triples or by failing to assert that
all triples were included (even through they were). Clients might still find the extra
information useful, but the only way for clients to be sure they had all available
information would be to make a HTTP GET request against all the other resource(s).
In some applications, knowing that these requests are unnecessary saves significant latency
and server/network load.
This section is non-normative.
The building blocks LDP provides can only be safely used if certain assumptions hold.
Said another way, resource inlining solves a subset of scenarios, not all scenarios in the general case —
so if you care about any of the following in a given application, your server should avoid returning
any triples beyond those found at the HTTP Request-URI.
Provenance is lost: because RDF graphs from multiple HTTP resources are merged in the response without attributing each statement to its originating graph (i.e. without quotation), it is impossible for a client to reliably know which triples came from which HTTP resource(s). A general solution allowing quotation is RDF Datasets; that is expected to be standardized independently, and can be used in these cases once it is available.
The response may contain contradictions that are trivially obvious (or subtle), and those may or may not be a problem at the application level. For a trivial example, two triples may have identical subjects and predicates but different objects: "75F is too hot"; "75F is too cold". Again, quotation via RDF Datasets (or any equivalent mechanism) is believed to provide a long term solution once standardized.
In addition to the requirements set forth in other sections, LDPR servers that support resource inlining must also follow the requirements in this section.
ldp:Page resource in the representation describing the set of inlined resources,
whether or not the representation contains subsequent pages. The ldp:Page resource conceptually contains
metadata about the representation; it is usually not part of the HTTP resource's state, and its presence does not indicate that
the LDPR server supports paging in general.
LDPR servers that include the ldp:Page resource for inlining and also support
paging MUST use the same ldp:Page resource for the triples required by both,
in order to minimize client code complexity.
The ldp:Page resource's triples are the LDP-defined means by which the servers communicate to LDP clients
the set of HTTP resources whose state is included in a representation, allowing clients to avoid HTTP GET
requests for them.
ldp:Page resource described in section 4.11.3.1
one triple for each inlined resource,
whose subject is the ldp:Page resource URI,
whose predicate is ldp:inlinedResource, and
whose object is the HTTP Request-URI of an inlined resource [HTTP11].
GET requests
against any resource whose HTTP Request-URI is the object of a triple of the form
described in section 4.11.3.2, unless there are application-specific
reasons for doing so. Clients should note that by the time the representation is received, the actual state
of any inlined resource(s) may have changed due to subsequent requests.
ldp:Page resource or lacking the triple
described in section 4.11.3.2 contain all the triples for any resource(s)
listed in the representation whose HTTP Request-URI differs from
the HTTP Request-URI used by the client.
The representation might in fact contain all such triples, or some
subset of them, and that might or might not be completely adequate for the client's intended usage, but
an LDP client has no way to discern from such a representation which interpretation is accurate.
This section is non-normative.
Many HTTP applications and sites have organizing concepts that partition the overall space of resources into smaller containers. Blog posts are grouped into blogs, wiki pages are grouped into wikis, and products are grouped into catalogs. Each resource created in the application or site is created within an instance of one of these container-like entities, and users can list the existing artifacts within one. Containers answer some basic questions, which are:
This document defines the representation and behavior of containers
that address these issues. The set of members of a container is
defined by a set of triples in its representation (and state) called
the membership triples. The membership triples of a container all
have the same subject and predicate – the objects of the membership
triples define the members of the container. The subject of the
membership triples is called the membership subject and the predicate
is called the membership predicate. In the simplest cases, the
membership subject will be the LDPC resource itself, but it does not
have to be. The membership predicate is also variable and will often
be a predicate from the server application vocabulary or the rdfs:member predicate.
This document includes a set of guidelines for using POST to create new resources and add them to the list of members of a container. It goes on to explain how to learn about a set of related resources, they may have been created using POST or through other means. It also defines behavior when POST created resources are deleted, to clean up container membership, and deleting containers removes membership information and possibly perform some cleanup tasks on unreferenced member resources.
The following illustrates a very simple container with only three members and some information about the container (the fact that it is a container and a brief title):
# The following is the representation of # http://example.org/container1/ @prefix dcterms: <http://purl.org/dc/terms/>. @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>. @prefix ldp: <http://www.w3.org/ns/ldp#>. <> a ldp:Container; ldp:membershipSubject <> ldp:membershipPredicate rdfs:member; ldp:membershipObject ldp:MemberSubject; dcterms:title "A very simple container"; rdfs:member <member1>, <member2>, <member3>.
This example is very straightforward - the
membership predicate is rdfs:member and the membership subject is the container
itself. A POST to this container will create a new resource
and add it to the list of members by adding a new membership triple
to the container.
Sometimes it is useful to use a subject
other than the container itself as the membership subject and to use
a predicate other than rdfs:member as the membership predicate. Let's
start with a domain resource for a person's net worth, as illustrated below:
# The following is a partial representation of
# http://example.org/netWorth/nw1
@prefix ldp: <http://www.w3.org/ns/ldp#>.
@prefix o: <http://example.org/ontology/>.
<>
a o:NetWorth;
o:netWorthOf <http://example.org/users/JohnZSmith>;
o:asset
<assetContainer/a1>,
<assetContainer/a2>;
o:liability
<liabilityContainer/l1>,
<liabilityContainer/l2>,
<liabilityContainer/l3>.From this example, there is a rdf:type of o:NetWorth indicating the
resource represents an instance of a person's net worth and o:netWorthOf predicate indicating
the associated person. There are two sets of same-subject, same-predicate pairings; one for assets and
one for liabilities. It would be helpful to be able to associate these multi-valued sets using a URL
for them to assist with managing these, this is done by associating containers with them as
illustrated below:
# The following is an elaborated representation of
# http://example.org/netWorth/nw1/
@prefix ldp: <http://www.w3.org/ns/ldp#>.
@prefix dcterms: <http://purl.org/dc/terms/>.
@prefix o: <http://example.org/ontology/>.
<>
a o:NetWorth;
o:netWorthOf <http://example.org/users/JohnZSmith>;
o:asset
<assetContainer/a1>,
<assetContainer/a2>;
o:liability
<liabilityContainer/l1>,
<liabilityContainer/l2>,
<liabilityContainer/l3>.
<assetContainer/>
a ldp:Container;
dcterms:title "The assets of JohnZSmith";
ldp:membershipSubject <>;
ldp:membershipPredicate o:asset;
ldp:membershipObject ldp:MemberSubject.
<liabilityContainer/>
a ldp:Container;
dcterms:title "The liabilities of JohnZSmith";
ldp:membershipSubject <>;
ldp:membershipPredicate o:liability;
ldp:membershipObject ldp:MemberSubject.The essential structure of the container is
the same, but in this example, the membership subject is not the
container itself – it is a separate net worth resource. The
membership predicates are o:asset and o:liability – predicates
from the domain model. A POST of an asset representation to the asset container will create a new
asset and add it to the list of members by adding a new membership triple
to the container. You might wonder why
http://example.org/netWorth/nw1 isn't made a container itself and POST
the new asset directly there. That would be a fine design if http://example.org/netWorth/nw1
had only assets, but if it has separate predicates for assets and liabilities,
that design will not work because it is unspecified to which predicate the POST
should add a membership triple. Having separate http://example.org/netWorth/nw1/assetContainer/
and http://example.org/netWorth/nw1/liabilityContainer/ container
resources allows both assets and liabilities to be created.
# The following is the representation of # http://example.org/netWorth/nw1/assetContainer/ @prefix ldp: <http://www.w3.org/ns/ldp#>. @prefix o: <http://example.org/ontology/>. <> a ldp:Container; ldp:membershipSubject <http://example.org/netWorth/nw1>; ldp:membershipPredicate o:asset; ldp:membershipObject ldp:MemberSubject. <http://example.org/netWorth/nw1> a o:NetWorth; o:asset <a1>, <a2>.
In this example, clients cannot simply guess which resource is the membership subject and which predicate is the membership predicate, so the example includes this information in triples whose subject is the LDPC resource itself.
In many – perhaps most – applications involving containers, it is desirable for the client to be able to get information about each container member without having to do a GET on each one. LDPC allows servers to include this information directly in the representation of the container. The server decides the amount of data about each member that is provided. Some common strategies include providing a fixed number of standard properties, or providing the entire RDF representation of each member resource, or providing nothing. The server application domain and its use-cases will determine how much information is required.
Continuing on from the net worth example, there will be additional triples for the member resources (assets) in the representation:
# The following is the representation of # http://example.org/netWorth/nw1/assetContainer/ @prefix dcterms: <http://purl.org/dc/terms/>. @prefix ldp: <http://www.w3.org/ns/ldp#>. @prefix o: <http://example.org/ontology/>. <> a ldp:Container; dcterms:title "The assets of JohnZSmith"; ldp:membershipSubject <http://example.org/netWorth/nw1>; ldp:membershipPredicate o:asset; ldp:membershipObject ldp:MemberSubject. <http://example.org/netWorth/nw1> a o:NetWorth; o:asset <a1>, <a3>, <a2>. <a1> a o:Stock; o:value 10000. <a2> a o:Bond; o:value 20000. <a3> a o:RealEstateHolding; o:value 300000.
In a similar manner, when the representation for the resource of asset .../<a1> is returned a server may include the membership triple of the form (.../nw1, o:asset, .../a1).
The representation of a container that has many members will be large. There are several important cases where clients need to access only the non-member properties of the container. Since retrieving the whole container representation to get this information may be onerous for clients and cause unnecessary overhead on servers, it is desired to define a way to retrieve only the non-member property values. Defining for each LDPC a corresponding resource, called the “non-member resource”, whose state is a subset of the state of the container, does this.
The example listed here only show a simple case where only a few simple non-member properties are retrieved. In real world situations more complex cases are likely, such as those that add other predicates to containers, for example providing validation information and associating SPARQL endpoints. [SPARQL-QUERY]
Here is an example requesting the non-member properties of a
container identified by the URL http://example.org/container1/.
In this case, the non-member resource is identified by the URL
http://example.org/container1?non-member-properties:
Request:
GET /container1?non-member-properties HTTP/1.1 Host: example.org Accept: text/turtle; charset=UTF-8
Response:
HTTP/1.1 200 OK Content-Type: text/turtle; charset=UTF-8 ETag: "_87e52ce291112" Content-Length: 325 @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>. @prefix dcterms: <http://purl.org/dc/terms/>. @prefix ldp: <http://www.w3.org/ns/ldp#>. <http://example.org/container1/> a ldp:Container; dcterms:title "A Linked Data Platform Container of Acme Resources"; ldp:membershipSubject http://example.org/container1/; ldp:membershipPredicate rdfs:member; ldp:membershipObject ldp:MemberSubject; dcterms:publisher <http://acme.com/>.
While the same non-member resource could be used to update the non-member properties via PUT, LDP recommends using PATCH for this purpose.
There are many cases where an ordering of the members of the
container is important. LDPC does not provide any particular support
for server ordering of members in containers, because any client can
order the members in any way it chooses based on the value of any
available property of the members. In the example below, the value of
the o:value predicate is present for each
member, so the client can easily order the members according to the
value of that property. In this way, LDPC avoids the use of RDF
constructs like Seq and List for expressing order.
Order becomes more important for LDPC servers when containers are
paginated. If the server does not respect ordering when constructing
pages, the client would be forced to retrieve all pages before
sorting the members, which would defeat the purpose of pagination.
In cases where ordering is important, an LDPC server exposes all the
members on a page with the proper sort order with relation to all
members on the next and previous pages.
When the sort is ascending, all the members on a current page have a
higher sort order than all members on the previous page and
lower sort order than all the members on the next page.
When the sort is descending, the opposite order is used.
Since more than one value may be used to sort members,
the LDPC specification allows servers to assert the ordered list
of sort criteria used to sort the members, using the
ldp:containerSortCriteria relation.
Each member of the ordered list exposes one ldp:containerSortCriterion,
consisting of a ldp:containerSortOrder,
ldp:containerSortPredicate, and
optionally a ldp:containerSortCollation.
Here is an example container described previously, with representation for ordering of the assets:
# The following is the ordered representation of # http://example.org/netWorth/nw1/assetContainer/ @prefix dcterms: <http://purl.org/dc/terms/>. @prefix ldp: <http://www.w3.org/ns/ldp#>. @prefix o: <http://example.org/ontology/>. <> a ldp:Container; dcterms:title "The assets of JohnZSmith"; ldp:membershipSubject <http://example.org/netWorth/nw1>; ldp:membershipPredicate o:asset; ldp:membershipObject ldp:MemberSubject. <?firstPage> a ldp:Page; ldp:pageOf <>; ldp:containerSortCriteria (#SortValueAscending). <#SortValueAscending> a ldp:ContainerSortCriterion; ldp:containerSortOrder ldp:Ascending; ldp:containerSortPredicate o:value. <http://example.org/netWorth/nw1> a o:NetWorth; o:asset <a1>, <a3>, <a2>. <a1> a o:Stock; o:value 100.00. <a2> a o:Cash; o:value 50.00. <a3> a o:RealEstateHolding; o:value 300000.
As you can see by the addition of the ldp:ContainerSortCriteria
predicate, the o:value predicate is used
to order the page members in ascending order. It is up to the domain model
and server to determine the appropriate predicate to indicate the
resource’s order within a page, and up to the client receiving this
representation to use that order in whatever way is appropriate, for
example to sort the data prior to presentation on a user interface.
The Linked Data Platform does not define how clients discover LDPCs.
rdfs:member predicate. Member resources can be
any kind of resource identified by its URI, LDPR or otherwise.
ldp:membershipSubject,
and whose object is the LDPC's membership subject URI.
ldp:membershipPredicate or ldp:membershipPredicateInverse.
The object of the triple is constrained by other sections, such as
5.2.5.1 or 5.2.5.2.
ldp:membershipPredicate, the object MUST be the URI of the membership predicate P used to
indicate membership to the linked to LDPC, or simply: T = ( C, ldp:membershipPredicate, P).
For the membership predicate URI object used in the triple T, it would be found in a resource's
same subject R and same predicate P membership triples of the form:
(R, P, MR), where MR represents URI of
a member resource.
ldp:membershipPredicateInverse, the object MUST be the URI of the membership predicate P used to
indicate membership to the linked to LDPC, or simply: T = ( C, ldp:membershipPredicateInverse, P).
For the membership predicate URI object used in the triple T, it would be found in a resource's
object subject R and same predicate P membership triples of the form:
(MR, P, R), where MR represents URI of
a member resource.
GET
on each member individually. See sections 5.1.1 Container
Member Information, section 4.11 , and
section 5.10 for additional details.
rdf:type
of ldp:Container, but it MAY have additional
rdf:types.
rdf:Bag,
rdf:Seq or rdf:List.
POST, PUT, etc.).
Certain specific cases exist where a LDPC server MAY delete a resource and then later re-use the
URI when it identifies the same resource, but only when consistent with Web architecture [WEBARCH].
While it is difficult to provide absolute implementation guarantees of non-reuse in all failure
scenarios, re-using URIs creates ambiguities for clients that are best avoided.
ldp:membershipObject, with an object MO.
Where MO and the HTTP URI R from POST create (as found in HTTP response Location header) can be
used to locate a triple of the form: (R, MO, N) and
where N can be used to construct the membership triple of the form: (membership subject, membership predicate, N).
When ldp:membershipPredicateInverse is used instead of ldp:membershipPredicate, the membership triple MUST be
of the form: (N, membership predicate, membership subject). To indicate that the member resource URI is the membership object
(the default or typical case), the object MUST be set to predefined URI ldp:MemberSubject such that it forms the triple:
(LDPC URI, ldp:membershipObject, ldp:MemberSubject).
ldp:containerSortCriteria,
and whose object is a rdf:List of
ldp:containerSortCriterion resources.
The resulting order MUST be as defined by SPARQL SELECT’s ORDER BY clause
[SPARQL-QUERY].
Sorting criteria MUST be the same for all pages of a representation; if
the criteria were allowed to vary, the ordering among members of a container
across pages would be undefined.
The first list entry provides the primary
sorting criterion, any second entry provides a secondary criterion used to order members considered
equal according to the primary criterion, and so on.
See section 5.1.4 Ordering for
an example.
ldp:containerSortCriteria MUST contain,
in every ldp:containerSortCriterion list entry,
a triple
whose subject is the sort criterion identifier,
whose predicate is ldp:containerSortPredicate
and whose object is
the predicate whose value is used to order members between pages (the page-ordering values).
The only predicate data types whose behavior LDP constrains are those defined
by SPARQL SELECT’s ORDER BY clause [SPARQL-QUERY]. Other data types
can be used, but LDP
assigns no meaning to them and interoperability will be limited.
ldp:containerSortCriteria MUST contain,
in every ldp:containerSortCriterion list entry,
a triple
whose subject is the sort criterion identifier,
whose predicate is ldp:containerSortOrder
and whose object describes the order used. LDP defines two values,
ldp:Ascending and ldp:Descending, for use
as the object of this triple. Other values can be used, but LDP
assigns no meaning to them and interoperability will be limited.
ldp:containerSortCriteria MAY contain,
in any ldp:containerSortCriterion list entry,
a triple
whose subject is the sort criterion identifier,
whose predicate is ldp:containerSortCollation
and whose object identifies the collation used. LDP defines no values for use
as the object of this triple. While it is better for interoperability to use
open standardized values, any value can be used.
When the ldp:containerSortCollation triple is absent and the
page-ordering values are strings or simple literals [SPARQL-QUERY], the
resulting order is as defined by SPARQL SELECT’s ORDER BY clause
[SPARQL-QUERY] using two-argument fn:compare, that is,
it behaves as if http://www.w3.org/2005/xpath-functions/collation/codepoint
was the specified collation.
When the ldp:containerSortCollation triple is present and the
page-ordering values are strings or simple literals
[SPARQL-QUERY], the
resulting order is as defined by SPARQL SELECT’s ORDER BY clause
[SPARQL-QUERY] using three-argument fn:compare, that is, the
specified collation.
The ldp:containerSortCollation triple SHOULD be omitted for comparisons
involving page-ordering values for which [SPARQL-QUERY] does not use collations.
This specification imposes the following new requirements on HTTP POST for LDPCs
only when an LDPC supports that method. This specification does not impose any
new requirement to support that method, and [HTTP11] makes it optional.
POST to a known LDPC. If the resource was created successfully, LDPC servers MUST
respond with status code 201 (Created) and the Location
header set to the new resource’s URL. Clients shall not expect any representation in the response
entity body on a 201 (Created) response.
POST request to a LDPC, the new resource MUST
appear as a member of the LDPC until the new resource is deleted or
removed by other methods. An LDPC MAY also contain resources that were
added through other means - for example through the user interface of
the site that implements the LDPC.
POST of non-RDF representations for
creation of any kind of resource, for example binary resources. See 5.4.13 for introspection
details.
Content-Type with value of text/turtle [TURTLE].
Content-Type request header
to determine the representation format when the request has an entity body. When the header is absent,
LDPC servers MAY infer the content type by inspecting the entity body contents [HTTP11].
POST, using the HTTP Slug header as defined in [RFC5023]. LDP adds
no new requirements to this usage, so its presence functions as a client hint to the server
providing a desired string to be incorporated into the server's final choice of resource URI.
POST
SHOULD NOT re-use URIs, per the
general requirements on LDPCs.
Location response header), LDPC servers MAY create an associated LDPR
to contain data about the created resource. If an LDPC server creates this associated LDPR it MUST indicate
its location on the HTTP response using the HTTP response header Link and relationship type meta
and href to be the URI of the meta-resource [RFC5988].
POST MUST
include an Accept-Post response header on HTTP OPTIONS
responses, listing post document media type(s) supported by the server.
LDP only specifies the use of POST for the purpose of creating new resources, but a server
can accept POST requests with other semantics.
While "POST to create" is a common interaction pattern, LDP clients are not guaranteed, even when
making requests to an LDP server, that every successful POST request will result in the
creation of a new resource; they must rely on out of band information for knowledge of which POST requests,
if any, will have the "create new resource" semantics.
This requirement on LDP servers is intentionally stronger than the one levied in the
header registration; it is unrealistic to expect all existing resources
that support POST to suddenly return a new header or for all new specifications constraining
POST to be aware of its existence and require it, but it is a reasonable requirement for new
specifications such as LDP.
ldp:created predicate for this purpose.
An LDPC that tracks members created through the LDPC MUST add a triple
whose subject is the container's URI,
whose predicate is ldp:created, and
whose object is the newly created member resource's URI;
it MAY add other triples as well.
This specification imposes the following new requirements on HTTP PUT for LDPCs
only when an LDPC supports that method. This specification does not impose any
new requirement to support that method, and [HTTP11] makes it optional.
PUT to update a LDPC’s membership triples;
if the server receives such a request, it SHOULD respond with a 409
(Conflict) status code.
PUT on a corresponding non-member resource, which
MAY exclude server-managed properties such as ldp:membershipSubject, ldp:membershipPredicate
and ldp:membershipPredicateInverse.
The section 5.9 describes the process by which clients
use HTTP OPTIONS to discover whether the server offers such a resource, and if so its URL.
PUT requests
with inlined member information in the request representation.
See section 5.1.1 Container
Member Information for additional details.
PUT
SHOULD NOT re-use URIs, per the
general requirements on LDPCs.
This specification imposes the following new requirements on HTTP DELETE for LDPRs and LDPCs
only when a LDPC supports that method. This specification does not impose any
new requirement to support that method, and [HTTP11] makes it optional.
POSTed to the LDPC and then referenced by a membership triple) is deleted, and the LDPC server is aware of the member's deletion
(for example, the member is managed by the same server), the LDPC server MUST also remove it from
the LDPC by removing the corresponding membership triple.
DELETE request on a LDPC, it MUST remove any
membership triples associated with the LDPC as indicated by the canonical Request-URI. The LDPC server MAY perform additional removal
of member resources.
For example, the server could perform additional cleanup tasks for resources it knows are no longer referenced or have not
been accessed for some period of time.
ldp:created predicate, the LDPC server MUST also remove
the deleted member's ldp:created triple.
POSTed to the LDPC and then referenced by a membership triple) is deleted, and the LDPC server
created an associated LDPR (see 5.4.12), the LDPC server must also remove the associated LDPR it created.
Note that certain LDP mechanisms, such as paging, rely on HTTP headers, and HTTP generally requires that
HEAD responses include the same headers as GET responses. Also LDPC servers must also include HTTP headers
on response to OPTIONS, see .
Thus, implementers supporting HEAD should also carefully read the
section 5.3 and section 5.9 .
This specification imposes the following new requirements on HTTP PATCH for LDPCs
only when a LDPC supports that method. This specification does not impose any
new requirement to support that method, and [HTTP11] makes it optional.
PATCH as the preferred
method for updating LDPC non-membership properties.
This specification imposes the following new requirements on HTTP OPTIONS for LDPCs.
OPTIONS requests with an LDPC as the Request-URI,
LDPC servers that define a non-member resource SHOULD provide an HTTP Link
header whose target URI is the non-member resource, and whose link relation type is
http://www.w3.org/ns/ldp#nonMemberResource [RFC5988].
This is the mechanism by which clients discover the URL of the non-member resource.
If no such Link
header is present, then conservative clients will assume that the LDPC does not have a corresponding
non-member resource.
For example, if there is a LDPC with URL <containerURL> whose corresponding
non-member resource
URL is <containerURL>?nonMemberProperties, then the corresponding link header
would be Link: <?nonMemberProperties>;rel="http://www.w3.org/ns/ldp#nonMemberResource"
POSTed to the LDPC and then referenced by a membership triple) it might create an associated LDPR to contain data about the
non-LDPR (see 5.4.12). For non-LDPRs that have this associated LDPR, an LDPC server MUST provide an HTTP Link
header whose target URI is the associated LDPR, and whose link relation type is
meta [RFC5988].Feature At Risk
The LDP Working Group proposes incorporation of the features described in this section.
Feedback, both positive and negative, is invited by sending email to the mailing list in Status of This Document.
This section is non-normative.
One of the most commonly cited scenarios for resource inlining is to save clients enumerating a container of m members from having to perform m+1 HTTP requests (or m+p, if the container is paged into p pages). The desire is to allow the server to reduce the number of HTTP round-trips by returning some (perhaps all) members' content as part of the container's representation. In addition to the general resource inlining mechanism useful in cases where only a subset of the members' content is inlined, LDP also provides a predicate for the special case where all of a container's or page's members are inlined. Rather than forcing the server to add a triple for each inlined member, forcing clients to compare the list of inlined members against the set of members in the representation, and enlarging the representation needlessly, a single triple can be used. This is called member inlining.
LDP does not provide clients with any way to detect whether or not the server is capable of resource inlining (all its resources or any specific resource), nor does it provide clients with any way to influence which (if any) resources are inlined in any given response.
The inlining building blocks LDP provides can only be safely used if certain assumptions hold. This is no less true for containers than for LDPRs in general. See the general cautions on resource inlining.
In addition to the requirements set forth in other sections, LDPC servers that support member inlining, and LDP clients aware of the same facility, must also follow the requirements in this section.
ldp:Page resource in the representation, whether or not the representation contains
multiple pages, as described in section 4.11.3.1. In addition to satisfying
those requirements, the representation MUST contain a triple
whose subject is the ldp:Page resource URI,
whose predicate is ldp:membersInlined, and
whose object is "true"^^xsd:boolean.
This is means by which the server communicates to LDP clients that they can avoid HTTP GET
requests for the members listed on the page.
GET requests
against any members in a LDPC representation containing a ldp:Page resource with the triple
described in section 5.10.2.1, unless there are application-specific
reasons for doing so. Clients should note that by the time the representation is received, the actual state
of inlined members may have changed due to subsequent requests.
ldp:Page resource or lacking the triple
described in section 5.10.2.1 contain all the triples for all members
listed in the representation. The representation might in fact contain all those triples, or some
subset of them, that might or might not be completely adequate for the client's intended usage, but
an LDP client has no way to discern from such a representation which interpretation is accurate.
Feature At Risk
The LDP Working Group proposes incorporation of the features described in this section.
This specification introduces a new HTTP response header Accept-Post used
to specify the document formats accepted by the server on HTTP POST requests.
It is modeled after the Accept-Patch header defined in [RFC5789].
Accept-Post, using
the ABNF syntax defined in Section 2.1 of [HTTP11], is:
Accept-Post = "Accept-Post" ":" 1#media-typeThe
Accept-Postheader specifies a comma-separated list of media- types (with optional parameters) as defined by [HTTP11], Section 3.7.
Accept-Post HTTP header SHOULD appear in the OPTIONS response for any resource
that supports the use of the POST method. The presence of the
Accept-Post header in response to any method is an implicit
indication that POST is allowed on the resource identified by the
Request-URI. The presence of a specific document format in
this header indicates that that specific format is allowed on POST requests to the
resource identified by the Request-URI.
The Accept-Post response header must be added to the permanent registry (see [RFC3864]).
Header field name: Accept-Post
Applicable Protocol: HTTP
Author/Change controller: W3C
Specification document: this specification
This section is non-normative.
The following people have been instrumental in providing thoughts, feedback, reviews, content, criticism and input in the creation of this specification:
Tim Berners-Lee, Steve Battle, Olivier Berger, Alexandre Bertails, Reza B'Far, Cody Burleson, Richard Cyganiak, Raúl García Castro, Miguel Esteban Gutiérrez, Sandro Hawke, Kingsley Idehen, Yves Lafon, Arnaud Le Hors, Antonis Loizou, Ashok Malhota, Roger Menday, Nandana Mihindukulasooriya, Kevin Page, Eric Prud'hommeaux, Andy Seaborne, Steve Speicher, Henry Story, Ted Thibodeau, Bart van Leeuwen, Miel Vander Sande, Ruben Verborgh, Serena Villata, Erik Wilde, David Wood, Martin P. Nally