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. Some implementations may be unable to provide all features described in this document due to conscious design decisions, but at least the method of rejection for requests against such features is defined.
A conforming Fedora server is a conforming [[!LDP]] 1.0 server except where described in this document that also follows the rules defined by Fedora in , , , and .
Terminology is based on W3C's Linked Data Platform 1.0 [[LDP]] and Memento [[RFC7089]].
Accept-Datetime
-varied negotiation of versions of an URI-R.
If a Link: rel="type"
header specifies an LDP-NR interaction model
(ldp:NonRDFSource
), then the server SHOULD handle subsequent requests
to the newly created resource as if it is a LDP-NR.
([[!LDP]] 5.2.3.4 extension)
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 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
a LDP-R 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 the ldp:contains predicate, and thus triples with this predicate do not necessarily imply containment.
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 available. If an otherwise valid HTTP PATCH
request is received that attempts to add statements to a
resource 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 (e.g. 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.
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.
Any LDPC 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).
A HTTP POST
request that would create a 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.
A HTTP POST
request that includes an unsupported Digest
type (as described
in [[!RFC3230]]), SHOULD be rejected with a 400 Bad Request response.
Implementations may support Content-Type: message/external-body
extensions for
request bodies for HTTP POST
that would create LDP-NRs.
This content-type requires a complete Content-Type
header that includes the location
of the external body, e.g Content-Type: message/external-body; access-type=URL; URL=\"http://www.example.com/file\"
,
as defined in [[!RFC2017]]. Requirements for this interaction are detailed in External LDP-NR Content.
When accepting a PUT
request against an extant resource, an HTTP Link: rel="type"
header MAY be included. 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. 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]].
Any LDP-NR MUST support PUT
to replace the binary content of that resource.
A 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.
A HTTP PUT
request that includes an unsupported Digest
type (as described
in [[!RFC3230]]), SHOULD be rejected with a 400 Bad Request response.
Implementations may support Content-Type: message/external-body
extensions for
request bodies for HTTP PUT
that would create LDP-NRs.
This content-type requires a complete Content-Type
header that includes the location
of the external body, e.g Content-Type: message/external-body; access-type=URL; URL=\"http://www.example.com/file\"
,
as defined in [[!RFC2017]]. Requirements for this interaction are detailed in External LDP-NR Content.
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 add statements to a resource 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 (e.g. 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.
An implementation MAY accept HTTP PUT
to create resources ([[!LDP]]
4.2.4.6). Behavior regarding
containment or non-containment of resources created with HTTP PUT
is
not defined by [[!LDP]] or this specification.
When the request is to the LDP-RS created to describe a LDP-NR, the response MUST include
a Link: rel="describes"
header referencing the LDP-NR in question, as defined
in [[!RFC6892]].
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.
GET
requests to any LDP-NR MUST correctly respond to the Want-Digest
header
defined in [[!RFC3230]].
Non-normative note: Given the use of checksums to validate content integrity, the digest values should be calculated instead of cached.
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.
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.
A Feodra server MAY support the Depth
header, as defined in [[!RFC4918]] section
10.2 . Implementations MAY choose not to support all of the header's values and MUST reject a request containing an unsupported Depth
value with a 400 (Bad Request). Implementations MUST define their own default behavior if a Depth header is not present.
If a server supports recursive DELETE
, that recursion MUST be reckoned along the [[!LDP]] containment relationships linking contained 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, on POST or PUT, that the Fedora server should 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 retreived. Theurl
andlocal-file
type values motivate this specification, but a Fedora server may support any type parameters per the requirements for advertisement and rejection specified here.
Fedora servers that support LDP-NR with message/external-body
MUST advertise that support in the Accept-Post
response
header for each supported type
parameter of supported Content-Type
values.
Fedora servers receiving requests that would create or update a LDP-NR
with a message/external-body
with an unsupported
type
parameter MUST respond with HTTP 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 HTTP 415.
Fedora servers receiving requests that would create or update a LDP-NR
with a 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.
LDP-NR GET and HEAD responses 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.
Per [[!RFC1521]], all Content-Type: message/external-body
values
MAY include an expiration
parameter. Fedora servers receiving requests that
would create or update a LDP-NR with a message/external-body
content
type SHOULD respect the expiration
parameter, if present, by copying
content. If the expiration
parameter cannot be accommodated, 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.
This specification takes no position on the use of message/external-body
to create or update LDP-RS with ttl or json-ld.
This specification assumes that clients interested in resolving a type='url'
or other value without the Fedora server as an intermediary (effectively, redirection as opposed
to proxying) will be able to negotiate the Content-Location
response header
value from a HEAD request.
A versioned resource for this document provides a TimeGate interaction model as
detailed in the Memento specification and indicated by an HTTP header
Link: rel="timegate"
referencing itself. It otherwise follows the relevant
[[!LDP]] specification with the additional behaviors below.
Accept-Datetime
, exactly as per Memento.
At least one Link: rel="timemap"
referencing an LDPCv. It is the
presence of this header that indicates that the resource is versioned.
Vary: Accept-Datetime
, exactly as per Memento.
An LDPRv MAY support PUT
. An implementation receiving a PUT
request for an
LDPRv MUST both correctly respond as per [[!LDP]] as well as create a new
LDPRm contained in an appropriate LDPCv. The newly-created LDPRm
SHOULD be the version of the LDPRv that was created by the PUT
request.
Accept-Datetime
, exactly as per Memento.
At least one Link: rel="timemap"
referencing a LDPCv. It is the
presence of this header that indicates that the resource is versioned.
Vary: Accept-Datetime
, exactly as per Memento.
When a LDPR is created with a Link
header indicating versioning,
it is created as both an LDP Resource and a Memento: a LDPRm. An LDPRm
MUST be invariant: While it MAY be deleted, it MUST NOT be modified once created.
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 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]] (Memento). Particularly it should be noted that the relevant TimeGate for
an LDPRm is the original versioned LDPRv.
An implementation MUST support HEAD
.
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 above.
An implementation MUST NOT support PATCH
for LDPRms.
An implementation MUST NOT support POST
for LDPRms.
An implementation MUST NOT support PUT
for LDPRms.
When a LDPR is created with a Link
header indicating versioning, a
version container (LDPCv) is created that contains Memento-identified resources
(LDPRm) capturing time-varying representations of the associated LDPR. An
LDPCv is both a TimeMap per [[!RFC7089]] (Memento) and an LDP Container.
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 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 NOT allow the creation of an LDPCv that is LDP-contained by its associated LDPRv.
Non-normative: The application/link-format
representation of a LDPCv
is not required to include all statements in the LDPCv graph, only those required
by TimeMap behaviors.
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.
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.
An implementation MAY Allow: PATCH
, but if so, it MUST NOT permit clients
to modify containment triples.
If a LDPCv supports POST
, POST
SHOULD be understood to
create a new LDPRm contained by the LDPCv, reflecting the state of the
LDPRv at the time of the POST
. If supported, but the representation
at the time of version creation can only be that which is current for the LDPRv,
the Accept-Post
header of any response from the LDPCv SHOULD indicate
that no request body is accepted via the form Accept-Post: */*; p=0.0
, and
that implementation SHOULD respond to any body-containing POST
to that
LDPCv with a 415 response 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 a LDPRm)
SHOULD be advertised in the response's Location
header.
If a LDPCv does accept POST
with a request body, it SHOULD respect
a Memento-Datetime
request header for the created LDPRm.
Absent this header, it MUST use the current time.
Non-normative note: If an LDPCv does not Allow: POST
, the constraints
document indicated in Link: rel="http://www.w3.org/ns/ldp#constrainedBy"
for
that LDPCv should describe the versioning mechanism (e.g. by PUT
or
PATCH
to the LDPRv described by that LDPCv). Disallowing
POST
suggests that the [[!LDP]] server will manage all LDPRm
creation; see here.
When a POST
to an LDPCv or PUT
or PATCH
to
an LDPRv creates a new LDPRm, the response indicates that using a
Vary
header as appropriate. When a LDPCv supports POST
,
and allows clients to specify a datetime for created URI-Ms,
Vary-Post/Vary-Put: Memento-Datetime.
This is a non-normative section describing the way the normative specification might be
applied to implement discoverable versioning patterns. If an implementation of a
LDPCv does not support POST
to mint versions, that must be advertised
via OPTIONS
as described above. 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.
Upon PUT
or PATCH
to the LDPRv, a new LDPRm
is created in an appropriate LDPCv. This LDPRm is the version of the
original LDPRv that was just created.
An LDPRm for a particular LDPRv is created on POST
to any
LDPCv associated with that LDPRv. The new LDPRm is contained in
the LDPCv to which the POST
was made and features in that
LDPCv-as-aTimeMap . This pattern is more open to manipulation and could
be useful for migration from other systems into Fedora implementations. Responses from
requests to the LDPRv include a Link: rel="timemap"
to the same
LDPCv as per [[!RFC7089]] (Memento).
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 existsNotifications 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/date", "@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/" } }
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:
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.
Transmission fixity may be verified by including a Digest
header (defined in
[[RFC3230]]) in POST
and PUT
requests for LDP-NRs.
A client may retrieve the checksum of an LDP-NR by performing a HEAD
or
GET
request on it with the Want-Digest
header (using a HEAD
request allows the client to avoid transferring the entire content when only the checksum is
needed). The Digest
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: