This specification refines the semantics and interaction patterns of [[LDP]] in order to better serve the specific needs of those interested in implementing repositories for durable access to digital data. Additionally, this specification contains:
The goal of this specification is to define the behaviors of Fedora server implementations in order to facilitate interoperability with client applications. Although Fedora servers are not necessarily drop-in replacements for one another, a client developed against this specification should work against any Fedora server with little modification. Client applications should not expect the behaviors of every Fedora server implementation to be identical, but the interaction patterns defined in this specification should provide a sufficient mechanism to navigate the differences between Fedora server implementations.
A conforming Fedora server is a conforming [[!LDP]] 1.0 server that follows the additional rules defined in sections , , , and of this specification.
Terminology is based on W3C's Linked Data Platform 1.0 [[!LDP]], Memento [[!RFC7089]], and Web Access Control [[!SOLIDWEBAC]].
Accept-Datetime
-varied negotiation of versions of an URI-R.
The following namespace prefixes are used in this document:
@prefix ldp: <http://www.w3.org/ns/ldp#> . @prefix acl: <https://www.w3.org/ns/auth/acl#> .
Implementations MUST support the creation and management of [[!LDP]] Containers.
LDP Containers MUST distinguish [containment
triples] from [membership] and [minimal-container] triples. If an
implementation cannot make this distinction, it MUST NOT permit ldp:contains
as the [membership predicate] for LDP Direct and
Indirect Containers or as a client-managed property, and requests that would do so MUST fail with 409
(Conflict) and an accompanying constraints document. Implementations that can distinguish containment
triples MAY permit ldp:contains
as a membership predicate or client-managed property; such
implementations SHOULD support Prefer:
header values allowing clients to distinguish this data
in the representation of an LDPR as defined in [[!LDP]]:
http://www.w3.org/ns/ldp#PreferContainment
,
http://www.w3.org/ns/ldp#PreferMembership
, and
http://www.w3.org/ns/ldp#PreferMinimalContainer
.
([[!LDP]] 5.4.1.4 expansion)
Non-normative note: [[!LDP]] defines containment relationships as binding an LDPC to LDPRs whose lifecycle it controls and is aware of, and are expressed through containment triples of the form<LDPC-URI> ldp:contains <LDPR-URI>
. However, implementations that segregate containment and membership triples — for example, by storing containment relationships in a dedicated named graph — may allow the creation of other triples with theldp:contains
predicate, and thus triples with this predicate do not necessarily imply containment.
If, in a successful resource creation request, a Link: rel="type"
request header specifies the
LDP-NR interaction model (http://www.w3.org/ns/ldp#NonRDFSource
, regardless of
Content-Type:
value), then the server SHOULD handle subsequent requests to the newly created
resource as if it is an LDP-NR. ([[!LDP]]
5.2.3.4 extension)
Non-normative note: Neither [[LDP]] nor this specification constrains the underlying storage model for RDF data. Each LDP-RS may be entirely independent RDF content, may be a portion of a shared RDF store, or follow some other arrangement. Implementation choices that result in failure to complete client requests are expressed in a constraints document ([[LDP]] 4.2.1.6) as noted in the appropriate sections of [[LDP]] and below.
Prefer
header
In addition to the requirements of [[!LDP]], an implementation MAY support the value
http://www.w3.org/ns/oa#PreferContainedDescriptions
and SHOULD support the value
http://fedora.info/definitions/fcrepo#PreferInboundReferences
for the Prefer
header when making GET
requests on LDPC resources:
http://www.w3.org/ns/oa#PreferContainedDescriptions
: Requires a server to include
representations of any contained resources in the response, as defined in [[!annotation-vocab]].
http://fedora.info/definitions/fcrepo#PreferInboundReferences
: Requires a server to include
triples from any LDP-RS housed in that server that feature the requested resource as RDF-object.
Responses to GET
requests that apply a Prefer
request header to any LDP-RS
MUST include the Preference-Applied
response header as defined in [[!RFC7240]]
section 3.
When a GET
request is made to an LDP-RS that describes an associated LDP-NR
( and [[!LDP]]
5.2.3.12),
the response MUST include a Link: rel="describes"
header referencing the LDP-NR in
question, as defined in [[!RFC6892]].
GET
requests to any LDP-NR MUST correctly respond to the Want-Digest
header defined in [[!RFC3230]].
Non-normative note: In the presence of aWant-Digest
header, the currentDigest
value should be calculated to enable fixity verification. Otherwise, it is expected that ETag values may be cached. Clients should use theCache-Control: no-cache
header (see [[RFC7234]] section 5.2.1.4) to instruct any intermediate caches or proxies not to return a cached response. See .
The HEAD
method is identical to GET
except that the server MUST NOT return a
message-body in the response, as specified in [[!RFC7231]]
section 4.3.2. The server MUST send the same
Digest
header in the response as it would have sent if the request had been a GET
(or omit it if it would have been omitted for a GET
). In other cases, the server SHOULD send the
same headers in response to a HEAD
request as it would have sent if the request had been a
GET
, except that the payload headers (defined in [[!RFC7231]]
section 3.3) MAY be omitted.
Any LDPR MUST support OPTIONS
per [[!LDP]]
4.2.8.
Non-normative note: Particular Allow:
header responses that clients may use to determine
implementation support for specific features are described in the appropriate sections of this specification.
Any LDPC (except Version Containers (LDPCv)) MUST support POST
([[!LDP]] 4.2.3 /
5.2.3). The default interaction model that will be
assigned when there is no explicit Link
header in the request MUST be recorded in the constraints
document referenced in the Link: rel="http://www.w3.org/ns/ldp#constrainedBy"
header ([[!LDP]]
4.2.1.6 clarification).
Any LDPC MUST support creation of LDP-NRs on POST
([[!LDP]]
5.2.3.3 MAY becomes MUST). On creation of an
LDP-NR, an implementation MUST create an associated LDP-RS describing that LDP-NR
([[!LDP]] 5.2.3.12 MAY becomes
MUST).
An HTTP POST
request that would create an LDP-NR and includes a Digest
header (as described in [[!RFC3230]]) for which the instance-digest in that header does not match that of
the new LDP-NR MUST be rejected with a 409 (Conflict) response.
An HTTP POST
request that includes an unsupported Digest
type (as described in
[[!RFC3230]]), SHOULD be rejected with a 400 (Bad Request) response.
Non-normative note: Implementations may supportContent-Type: message/external-body
extensions for request bodies for HTTPPOST
that would create LDP-NRs. This content-type requires a completeContent-Type
header that includes the location of the external body, e.gContent-Type: message/external-body; access-type=URL; URL="http://www.example.com/file"
, as defined in [[!RFC2017]]. Requirements for this interaction are detailed in .
When accepting a PUT
request against an existing resource, an HTTP Link: rel="type"
header MAY be included. If the type in the Link header is a subtype of a current type of the resource, and
has an interaction model assigned to it by [[!LDP]], then the resource MUST be assigned the new type and the
interaction model of the resource MUST be changed to the interaction model assigned to the new type by
[[!LDP]]. If that type is a value in the LDP namespace and is not either a current type of the resource or a
subtype of a current type of the resource, the request MUST be rejected with a 409 (Conflict) response.
Any LDP-RS MUST support PUT
to update statements that are not server-managed triples
(as defined in [[!LDP]] 2). [[!LDP]] 4.2.4.1
and 4.2.4.3 remain in effect. If an
otherwise valid HTTP PUT
request is received that attempts to modify resource statements that
a server disallows (not ignores per [[!LDP]]
4.2.4.1), the server MUST fail the request by
responding with a 4xx range status code, such as 409 (Conflict). The server MUST provide a corresponding
response body containing information about which statements could not be persisted. ([[!LDP]]
4.2.4.4 SHOULD becomes MUST). In that response,
the restrictions causing such a request to fail MUST be described in a resource indicated by a Link:
rel="http://www.w3.org/ns/ldp#constrainedBy"
response header per [[!LDP]]
4.2.1.6.
Any LDP-NR MUST support PUT
to replace the binary content of that resource.
An HTTP PUT
request that includes a Digest
header (as described in [[!RFC3230]])
for which any instance-digest in that header does not match the instance it describes, MUST be rejected with
a 409 (Conflict) response.
An HTTP PUT
request that includes an unsupported Digest
type (as described in
[[!RFC3230]]), SHOULD be rejected with a 400 (Bad Request) response.
Non-normative note: Implementations may supportContent-Type: message/external-body
extensions for request bodies for HTTPPUT
that would create LDP-NRs. This content-type requires a completeContent-Type
header that includes the location of the external body, e.gContent-Type: message/external-body; access-type=URL; URL="http://www.example.com/file"
, as defined in [[!RFC2017]]. Requirements for this interaction are detailed in .
Non-normative note: An implementation may accept HTTPPUT
to create resources ([[!LDP]] 4.2.4.6). Behavior regarding containment or non-containment of resources created with HTTPPUT
is not defined by [[!LDP]] or this specification.
Any LDP-RS MUST support PATCH
([[!LDP]]
4.2.7 MAY becomes MUST). [[!sparql11-update]] MUST
be an accepted content-type for PATCH
. Other content-types (e.g. [[ldpatch]]) MAY be supported.
If an otherwise valid HTTP PATCH
request is received that attempts to modify resource statements
that a server disallows (not ignores per [[!LDP]]
4.2.4.1), the server MUST fail the request by
responding with a 4xx range status code, such as 409 (Conflict). The server MUST provide a corresponding
response body containing information about which statements could not be persisted. ([[!LDP]]
4.2.4.4 SHOULD becomes MUST). In that response, the
restrictions causing such a request to fail MUST be described in a resource indicated by a Link:
rel="http://www.w3.org/ns/ldp#constrainedBy"
response header per [[!LDP]]
4.2.1.6.
A successful PATCH
request MUST respond with a 2xx status code; the specific code in the 2xx
range MAY vary according to the response body or request state.
PATCH
to update an LDPC’s containment triples; if the
server receives such a request, it SHOULD respond with a 409 (Conflict) status code.
The server MUST disallow a PATCH
request that would change the LDP interaction model of a
resource to a type that is not a subtype of the current resource type. That request MUST be rejected with a
409 (Conflict) response.
The DELETE
method is optional per [[!LDP]]
section 4.2.5 and this specification does not
require Fedora servers to implement it. When a Fedora server supports this method, in addition to the
requirements imposed on LDPRs within containers outlined in [[!LDP]]
section 5.2.5, it must also follow the additional
behavior outlined below.
An implementation that cannot recurse SHOULD NOT advertise DELETE
in response to
OPTIONS
requests for containers with contained resources.
Non-normative note: Clients should assume from an advertised DELETE
that they do not need to
look for contained/child resources to clean up.
If a server supports DELETE
, any recursion MUST be reckoned along the [[!LDP]]
containment relationships linking contained
resources.
An implementation MUST NOT return a 200 (OK) or 204 (No Content) response unless the entire operation successfully completed.
An implementation MUST NOT emit a message that implies the successful DELETE
of a resource
until the resource has been successfully removed.
Non-normative note: Atomicity is not guaranteed for HTTP DELETE
requests that affect multiple
resources.
Non-normative note: Variability among client types and locations may mean that LDP-NR content is addressed in ways that are external to the Fedora server but not resolvable by all clients. This specification describes the use ofContent-Type: message/external-body
values to signal, onPOST
orPUT
, that the Fedora server should not consider the request entity to be the LDP-NR's content, but that aContent-Type
value will signal a name or address at which the content might be retrieved. TheURL
([[RFC2017]] section 3) andlocal-file
([[RFC2046]] section 5.2.3.4) values of theaccess-type
parameter motivate this specification, but a Fedora server may support anyaccess-type
parameters per the requirements for advertisement and rejection specified here.
Fedora servers SHOULD support the creation of LDP-NRs with
Content-Type: message/external-body
and access-type
parameter value
URL
.
Fedora servers MUST advertise support in the Accept-Post
response header for each supported
access-type
parameter value of Content-Type: message/external-body
.
Fedora servers receiving requests that would create or update an LDP-NR with
Content-Type: message/external-body
and an unsupported access-type
parameter value
MUST respond with 415 (Unsupported Media Type). In the case that a Fedora server does not support external
LDP-NR content,
all message/external-body
messages must be rejected with 415 (Unsupported Media Type).
Fedora servers receiving requests that would create or update an LDP-NR with
Content-Type: message/external-body
MUST NOT accept the request if it cannot guarantee all of
the response headers required by the LDP-NR interaction model in this specification.
GET
and HEAD
responses for any external LDP-NR SHOULD include a
Content-Location
header with a URI representation of the location of the external content if
the Fedora server is proxying the content.
GET
and HEAD
requests to any external LDP-NR MUST correctly
respond to the Want-Digest
header defined in [[!RFC3230]].
Non-normative note:
This specification takes no position on the use of message/external-body
to create or update
LDP-RS with Turtle or JSON-LD.
Non-normative note: Fedora servers may choose to support theContent-Type
ofmessage/external-body
by proxying or copying the referenced content.
Per [[!RFC2046]] section 5.2.3, all
Content-Type: message/external-body
values MAY include an expiration
parameter.
Fedora servers receiving requests that would create or update an LDP-NR with a
message/external-body
content type SHOULD respect the expiration
parameter,
if present, by copying content. If the server is unable to copy the external content, the request MUST be
rejected with a 4xx or 5xx status code. Following [[!LDP]]
4.2.1.6 and
4.2.4.3, 4xx responses MUST be
accompanied by a Link
header with http://www.w3.org/ns/ldp#constrainedBy
relation.
Implementations MUST provide resource versioning as per [[RFC7089]] with the additional requirements described in this section.
When an LDPR is created with a Link: rel="type"
header specifying type
http://mementoweb.org/ns#OriginalResource
to indicate versioning, it MUST be created as
an LDPRv and a version container (LDPCv) MUST be created to contain Memento resources
(LDPRm) capturing time-varying representations of the LDPRv. Patterns for version creation
are described in .
A versioned resource (LDPRv) provides a TimeGate interaction model as detailed in the Memento specification [[RFC7089]]. It otherwise follows the [[!LDP]] specification, the requirements, and the additional behaviors below.
The Accept-Datetime
header is used to request a past state, exactly as per [[!RFC7089]]
section 2.1.1. A successful response
MUST be a 302 (Found) redirect to the appropriate LDPRm.
If no LDPRm is appropriate to the Accept-Datetime
value, an implementation SHOULD return a 406 (Unacceptable).
The response to a GET
request on an LDPRv MUST include the following headers:
Link: rel="original timegate"
header referencing itselfLink: <http://mementoweb.org/ns#TimeGate>; rel="type"
headerLink: <http://mementoweb.org/ns#OriginalResource>; rel="type"
headerLink: rel="timemap"
header referencing an associated LDPCvVary: Accept-Datetime
header, exactly as per [[!RFC7089]]
section 2.1.2.It is the presence of these headers that indicates that the resource is versioned.
An implementation MUST support PUT
, as is the case for any LDPR.
An LDPRm MAY be deleted; however, it MUST NOT be modified once created.
An implementation MUST support GET
, as is the case for any LDPR. The headers for
GET
requests and responses on this resource MUST conform to [[!RFC7089]]
section 2.1.
Particularly it should be noted that the relevant TimeGate for an LDPRm is the original
versioned LDPRv. In addition, any response to a GET
request MUST include a
Link: <http://mementoweb.org/ns#Memento>; rel="type"
header.
An implementation MUST support OPTIONS
. A response to an OPTIONS
request MUST
include Allow: GET, HEAD, OPTIONS
as per [[!LDP]]. An implementation MAY include Allow:
DELETE
if clients can remove a version from the version history, as noted in
.
An implementation MUST NOT support POST
for LDPRms.
An implementation MUST NOT support PUT
for LDPRms.
An implementation MUST NOT support PATCH
for LDPRms.
An implementation MAY support DELETE
for LDPRms. If DELETE
is supported,
the server is responsible for all behaviors implied by the LDP-containment of the LDPRm.
An LDPCv is both a TimeMap per Memento [[!RFC7089]] and an LDPC. As a TimeMap an LDPCv MUST conform to the specification for such resources in [[!RFC7089]]. An implementation MUST indicate TimeMap in the same way it indicates the container interaction model of the resource via HTTP headers.
An implementation MUST NOT allow the creation of an LDPCv that is LDP-contained by its associated LDPRv.
Non-normative note: The application/link-format
representation of an LDPCv is not
required to include all statements in the LDPCv graph, only those required by TimeMap
behaviors.
An implementation MUST support GET
, as is the case for any LDPR. Any response to a
GET
request MUST include a Link: <http://mementoweb.org/ns#TimeMap>; rel="type"
header.
An LDPCv MUST respond to GET Accept: application/link-format
as indicated in
[[!RFC7089]] section 5 and specified in
[[!RFC6690]] section 7.3.
An implementation MUST include the Allow
header as outlined in
.
If an LDPCv supports POST
, then it MUST include the Accept-Post
header
described in .
If an LDPCv supports PATCH
, then it MUST include the Accept-Patch
header.
An implementation MUST Allow: GET, HEAD, OPTIONS
as per [[!LDP]].
An implementation MAY Allow: DELETE
if the versioning behavior is removable by deleting
the LDPCv. See for requirements on DELETE
if supported.
An implementation MAY Allow: PATCH
if the LDPCv has mutable properties. See
for requirements on PATCH
if supported.
An implementation MAY Allow: POST
if versions can be explicitly minted by a client. See
for requirements on POST
if supported.
If an LDPCv supports POST
, a POST
that does not contain a
Memento-Datetime
header SHOULD be understood to create a new LDPRm contained by the
LDPCv, reflecting the state of the LDPRv at the time of the POST
. Any request
body MUST be ignored.
If an LDPCv supports POST
, a POST
with a Memento-Datetime
header SHOULD be understood to create a new LDPRm contained by the LDPCv, with the state
given in the request body and the datetime given in the Memento-Datetime
request header.
If an implementation does not support one or both of POST
cases above, it MUST respond to
such requests with a 4xx range status code and a link to an appropriate constraints document (see
LDP 4.2.1.6). As per [[!LDP]], any resource
created via POST
, in this case an LDPRm, SHOULD be advertised in the
Location
response header.
Non-normative note: If an LDPCv does notAllow: POST
, the constraints document indicated inLink: rel="http://www.w3.org/ns/ldp#constrainedBy"
for that LDPCv should describe the versioning mechanism (e.g. byPUT
orPATCH
to the LDPRv described by that LDPCv). DisallowingPOST
suggests that the [[!LDP]] server will manage all LDPRm creation; see Server-Managed Version Creation.
An implementation MAY support DELETE
. An implementation that does support DELETE
SHOULD do so by both removing the LDPCv and removing the versioning interaction model from the
original LDPRv.
Non-normative note: When aPOST
to an LDPCv, or aPUT
orPATCH
to an LDPRv creates a new LDPRm, the response indicates this by using aVary
header as appropriate. When an LDPCv supportsPOST
, and allows clients to specify a datetime for created URI-Ms, Vary-Post/Vary-Put: Memento-Datetime.
Non-normative note: This section describes the way the normative specification might be applied to implement discoverable versioning patterns. If an implementation of an LDPCv does not supportPOST
to mint versions, that must be advertised viaOPTIONS
as described in . This allows a client to perform anOPTIONS
request on an LDPCv to determine if it can explicitly mint versions. If the LDPCv does not supportPOST
, the client should assume some other mechanism is used to mint versions, for example, the implementation may automatically mint versions instead, but that is outside the requirements of this specification. This document specifies normatively only how LDPCvs and LDPRms can be discovered, and how they should act.
Non-normative note: UponPUT
orPATCH
to an LDPRv, a new LDPRm is created in an appropriate LDPCv. This LDPRm is the version of the original LDPRv that was just created.
Non-normative note: An LDPRm for a particular LDPRv is created onPOST
to any LDPCv associated with that LDPRv. The new LDPRm is contained in the LDPCv to which thePOST
was made and features in that LDPCv-as-a-TimeMap. This pattern is very flexible and might be useful for migration from other systems into Fedora implementations. Responses from requests to the LDPRv include aLink: rel="timemap"
to the same LDPCv as per [[!RFC7089]] section 5.
Non-normative note: Using the ingest-by-reference mechanism, one can replace the contents of an LDPRv with that of an LDPRm by providing it's URL as theURL
parameter in aContent-Type: message/external-body
header. For example, given an LDPRm with URLhttp://example.org/some/memento
, the full header would be
Content-Type: message/external-body; access-type=URL; expiration=1;
URL="http://example.org/some/memento"
Non-normative note: This section defines when notifications are made available by a Fedora implementation, the minimal set of data contained in these notifications, and how the data are serialized. Notifications may be emitted synchronously or asynchronously with the API operations that cause them to be emitted. These notifications are typically used to support external integrations. The structure of these notifications draws upon the existing [[activitystreams-core]] and [[ldn]] specifications. An implementation is free to choose from any transport technology so long as the notifications conform to what is described in the following sections.
Implementers should be aware that some operations cause multiple resources to change. In these cases, there will be a corresponding notification describing each of the changes. This is especially true for changes to containment or membership triples. This is also true if a
DELETE
operation triggers changes in any contained resources.Consumers of these notifications should not expect a strict ordering of the events reported therein: the fact that a notification for Event A is received before a notification for Event B should not imply that Event A occurred before Event B. Implementations may choose to make further guarantees about ordering.
According to the [[activitystreams-core]] specification, it is possible to collect multiple events into a single notification. This specification makes no restriction on the use of activity stream collections.
For every resource whose state is changed as a result of an HTTP operation, there MUST be a corresponding notification made available describing that change.
The notification serialization MUST conform to the [[!activitystreams-core]] specification.
Wherever possible, data SHOULD be expressed using the [[!activitystreams-vocabulary]].
Each event described by a notification MUST contain:
Each event described by a notification SHOULD contain:
ldp:inbox
for the resource that was changed, if such an inbox link exists
Notifications SHOULD NOT contain the entire content of repository resources.
{ "@context": "https://www.w3.org/ns/activitystreams", "id": "urn:uuid:3c834a8f-5638-4412-aa4b-35ea80416a18", "type": "Create", "name": "Resource Creation", "actor": "http://example.org/agent/fedoraAdmin", "object": { "id": "http://example.org/fcrepo/rest/resource/path", "type": [ "ldp:Container", "ldp:RDFSource" ] } }
{ "@context": [ "https://www.w3.org/ns/activitystreams", { "isPartOf": { "@id": "http://purl.org/dc/terms/isPartOf", "@type": "@id" } } ], "id": "urn:uuid:be29ae69-2134-f1b0-34be-2f91b6d1f029", "type": "Update", "name": "Resource Modification", "published": "2016-07-04T13:46:39Z", "inbox": "http://example.org/ldn/inbox/path", "actor": [ { "id": "#actor0", "type": "Person", "name": "fedo raAdmin" }, { "id": "#actor1", "type": "Service", "name": "APIX-core/0.1" } ], "object": { "id": "http://example.org/fcrepo/rest/resource/path", "updated": "2016-07-04T13:44:39Z", "type": [ "ldp:Container", "ldp:RDFSource", "http://example.org/type/CustomType" ], "isPartOf": "http://example.org/fcrepo/rest/" } }
Non-normative note: For the purposes of the following specification, a fixity result is an extract or summary of some LDP-NR made according to some explicit procedure. Fixity results are taken for the purpose of comparing different fixity results for the same resource over time, to ensure a continuity of that resource's identity according to the particular procedure used. Examples might include:
- Checksums like MD5 or SHA1, often used for digital images.
- XML Signatures
- Per-segment results as used for time-based media
This specification describes two fixity verification mechanisms: firstly, as part of content transmission, to guard against faults in transmission, and secondly, by comparison to a known or proffered digest value, to monitor for faults in persistence.
Non-normative note: Transmission fixity may be verified by including aDigest
header (defined in [[RFC3230]]) inPOST
andPUT
requests for LDP-NRs.
Non-normative note: A client may retrieve the checksum of an LDP-NR by performing aHEAD
orGET
request on it with theWant-Digest
header (using aHEAD
request allows the client to avoid transferring the entire content when only the checksum is needed). TheDigest
header in the response can be used to infer persistence fixity by comparing it to previously-computed values.
Fedora implementations are subject to the same privacy considerations that are found in the following specifications:
There are security considerations for any HTTP server exposed to the Internet. Implementations SHOULD make use of the many security-related features of HTTP, including use of the authentication framework defined in the Authentication chapter of the HTTP/1.1 specification [[!RFC7235]].
Fedora implementations are subject to the same security considerations that are found in the following specifications:
The following people have been instrumental in providing thoughts, feedback, reviews, content, criticism and input in the creation of this specification:
Sarven Capadisli, Herbert Van de Sompel, and members of the Fedora Repository, Islandora and Samvera communities.