浏览代码

Allow empty PUTs on existing resources.

Stefano Cossu 6 年之前
父节点
当前提交
a642c8668a
共有 3 个文件被更改,包括 24 次插入14 次删除
  1. 13 0
      docs/fcrepo4_deltas.rst
  2. 2 11
      lakesuperior/api/resource.py
  3. 9 3
      lakesuperior/model/ldp_factory.py

+ 13 - 0
docs/fcrepo4_deltas.rst

@@ -76,6 +76,19 @@ identifiers will be different).
 This seems to break Hyrax at some point, but might have been fixed. This
 needs to be verified further.
 
+Allow PUT requests with empty body on existing resources
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+FCREPO4 returns a ``409 Conflict`` if a PUT request with no payload is sent
+to an existing resource.
+
+LAKEsuperior allows to perform this operation, which would result in deleting
+all the user-provided properties in that resource.
+
+If the original resource is an LDP-NR, however, the operation will raise a
+``415 Unsupported Media Type`` because the resource will be treated as an empty
+LDP-RS, which cannot replace an existing LDP-NR.
+
 Non-standard client breaking changes
 ------------------------------------
 

+ 2 - 11
lakesuperior/api/resource.py

@@ -215,15 +215,10 @@ def create(parent, slug, **kwargs):
 
 
 @transaction(True)
-def create_or_replace(uid, stream=None, **kwargs):
+def create_or_replace(uid, **kwargs):
     r"""
     Create or replace a resource with a specified UID.
 
-    If the resource already exists, all user-provided properties of the
-    existing resource are deleted. If the resource exists and the provided
-    content is empty, an exception is raised (not sure why, but that's how
-    FCREPO4 handles it).
-
     :param string uid: UID of the resource to be created or updated.
     :param BytesIO stream: Content stream. If empty, an empty container is
         created.
@@ -234,11 +229,7 @@ def create_or_replace(uid, stream=None, **kwargs):
     :rtype: str
     :return: Event type: whether the resource was created or updated.
     """
-    rsrc = LdpFactory.from_provided(uid, stream=stream, **kwargs)
-
-    if not stream and rsrc.is_stored:
-        raise InvalidResourceError(rsrc.uid,
-                'Resource {} already exists and no data set was provided.')
+    rsrc = LdpFactory.from_provided(uid, **kwargs)
 
     return rsrc.create_or_replace()
 

+ 9 - 3
lakesuperior/model/ldp_factory.py

@@ -105,6 +105,11 @@ class LdpFactory:
                     'Creating empty container.')
             inst = Ldpc(uid, provided_imr=Graph(identifier=uri), **kwargs)
 
+            # Make sure we are not updating an LDP-NR with an LDP-RS.
+            if inst.is_stored and LDP_NR_TYPE in inst.ldp_types:
+                raise IncompatibleLdpTypeError(uid, mimetype)
+
+        # Otherwise, determine LDP type from provided content.
         else:
             # If the stream is RDF, or an IMR is provided, create a container
             # and populate it with provided RDF data.
@@ -119,7 +124,8 @@ class LdpFactory:
             #        pformat(set(provided_imr))))
 
             if not mimetype or __class__.is_rdf_parsable(mimetype):
-                # Determine whether it is a basic, direct or indirect container.
+                # Determine whether it is a basic, direct or indirect
+                # container.
                 if Ldpr.MBR_RSRC_URI in provided_imr.predicates() and \
                         Ldpr.MBR_REL_URI in provided_imr.predicates():
                     if Ldpr.INS_CNT_REL_URI in provided_imr.predicates():
@@ -131,7 +137,7 @@ class LdpFactory:
 
                 inst = cls(uid, provided_imr=provided_imr, **kwargs)
 
-                # Make sure we are not updating an LDP-RS with an LDP-NR.
+                # Make sure we are not updating an LDP-NR with an LDP-RS.
                 if inst.is_stored and LDP_NR_TYPE in inst.ldp_types:
                     raise IncompatibleLdpTypeError(uid, mimetype)
 
@@ -143,7 +149,7 @@ class LdpFactory:
                 inst = LdpNr(uid, stream=stream, mimetype=mimetype,
                         provided_imr=provided_imr, **kwargs)
 
-                # Make sure we are not updating an LDP-NR with an LDP-RS.
+                # Make sure we are not updating an LDP-RS with an LDP-NR.
                 if inst.is_stored and LDP_RS_TYPE in inst.ldp_types:
                     raise IncompatibleLdpTypeError(uid, mimetype)