nodeSolidServer/node-solid-server

PATCH does not work on JSON-LD file

uvdsl opened this issue · 6 comments

uvdsl commented

Hi all,
I was unsuccessfully trying to HTTP PATCH a jsonld file. But the same patch works on a turtle file with the exact same RDF statements.


I have a .jsonld (see here) file with the following content:

{
  "@context" : [ "https://uvdsl.solid.aifb.kit.edu/ontology/svcs-context" ], 
  "id" : "#status" , 
  "type" : "svcs:CredentialStatusInformation" ,
  "currentStatus" : "svcs:Revoked" , 
  "statusReason" : "because"
}

It holds the same RDF statements as the turtle file (see here), which I retrieved by simply requesting turtle instead of jsonld from the Pod:

@prefix : <#>.
@prefix cre: <https://purl.org/solid-vc/credentialStatus#>.

:status
    a cre:CredentialStatusInformation;
    cre:currentStatus cre:Revoked;
    cre:statusReason "because".

Applying the following PATCH does work on the turtle, but not on the jsonld file:

@prefix solid: <http://www.w3.org/ns/solid/terms#>. 
@prefix cre: <https://purl.org/solid-vc/credentialStatus#>.

_:rename a solid:InsertDeletePatch; 
     solid:deletes { <#status> cre:currentStatus cre:Revoked  };
     solid:inserts { <#status> cre:currentStatus cre:Issued }.

For example, the curl command:
curl --request PATCH -d " @prefix solid: <http://www.w3.org/ns/solid/terms#>. @prefix cre: <https://purl.org/solid-vc/credentialStatus#>. _:rename a solid:InsertDeletePatch; solid:deletes { <#status> cre:currentStatus cre:Revoked }; solid:inserts { <#status> cre:currentStatus cre:Issued }." -H "Content-type:text/n3" https://uvdsl.solidweb.org/public/patchtest-jsonld.jsonld
yields
The patch could not be applied. Could not find to delete: <https://uvdsl.solidweb.org/public/patchtest-jsonld.jsonld#status> <https://purl.org/solid-vc/credentialStatus#currentStatus> <https://purl.org/solid-vc/credentialStatus#Revoked> .

Am I missing something? :/
Thank you very much for your help!


PS: Yes, I am aware of the fact that the statements to be deleted MUST be existent in the file, but that is not the issue here.

I can confirm that, using that data and that patch - which looks ok to me -

  • the patch returns 409 against an ld+json file
  • the patch returns 200 against a turtle file created from a get text/turtle on the ld+json file
  1. Using your file example it fails on CSS
  2. PATCH is working perfectly on a CSS server with the following process. And fails on NSS. Need to be investigated

I made the following experiment, creating directly with PATCH the jsonld file :
PATCH to create the source JSONLD

@prefix solid: <http://www.w3.org/ns/solid/terms#>. 
@prefix cre: <https://purl.org/solid-vc/credentialStatus#>.

_:rename a solid:InsertDeletePatch; 
     
   solid:inserts { <#status> a cre:CredentialStatusInformation;
      cre:currentStatus cre:Revoked;
      cre:statusReason "because". }.

JSONLD file created

[
  {
    "@id": "https://bourgeoa.bourgeoa.ga:3100/public/uvsl.jsonld#status",
    "@type": [
      "https://purl.org/solid-vc/credentialStatus#CredentialStatusInformation"
    ],
    "https://purl.org/solid-vc/credentialStatus#currentStatus": [
      {
        "@id": "https://purl.org/solid-vc/credentialStatus#Revoked"
      }
    ],
    "https://purl.org/solid-vc/credentialStatus#statusReason": [
      {
        "@value": "because"
      }
    ]
  }
]

result of PATCH with delete Revoked and insert Issued

[
  {
    "@id": "https://bourgeoa.bourgeoa.ga:3100/public/uvsl.jsonld#status",
    "https://purl.org/solid-vc/credentialStatus#currentStatus": [
      {
        "@id": "https://purl.org/solid-vc/credentialStatus#Issued"
      }
    ],
    "https://purl.org/solid-vc/credentialStatus#statusReason": [
      {
        "@value": "because"
      }
    ],
    "@type": [
      "https://purl.org/solid-vc/credentialStatus#CredentialStatusInformation"
    ]
  }
]

I'm also having a similar problem. I identified a problem within the 'writeGraph' function that is called in the patch routine. On line 180, the call to rdflib's serialize function needs a callback function to receive the serialization result if the resource's contentType is "application/ld+json".

A possible rewrite of the function would be:

// Writes the RDF graph to the given resource
function writeGraph(graph, resource, root, serverUri) {
  debug('PATCH -- Writing patched file')
  return new Promise((resolve, reject) => {
    const resourceSym = graph.sym(resource.url)

    function doWrite(serialized) {
      // First check if we are above quota
      overQuota(root, serverUri).then((isOverQuota) => {
        if (isOverQuota) {
          return reject(error(413,
            'User has exceeded their storage quota'))
        }

        fs.writeFile(resource.path, serialized, { encoding: 'utf8' }, function (err) {
          if (err) {
            return reject(error(500, `Failed to write file after patch: ${err}`))
          }
          debug('PATCH -- applied successfully')
          resolve('Patch applied successfully.\n')
        })
      }).catch(() => reject(error(500, 'Error finding user quota')))
    }

    if (resource.contentType === "application/ld+json") {
      $rdf.serialize(resourceSym, graph, resource.url, resource.contentType, function (err, result) {
        if(err) return reject(error(500, `Failed to serialize after patch: ${err}`))
        doWrite(result)
      })
    } else {
      serialized = $rdf.serialize(resourceSym, graph, resource.url, resource.contentType, setSerialize)
      doWrite(serialized)
    }
  })
}

[ edited to add codefences so data is more clear -- @TallTed ]

Hi all,
I'm also having another similar problem. I was unsuccessfully trying to HTTP PATCH a jsonld file. But the same patch works on a turtle file with the exact same RDF statements.

Original resource:

[
  {
    "@id": "https://diegoalbuquerque.localhost:8443/tests/collections/notes/mynotes",
    "https://www.w3.org/ns/activitystreams#current": [
      {
        "@id": "https://diegoalbuquerque.localhost:8443/tests/collections/notes/pages/f4ec7ef9-58e1-4919-a16f-efa58eeca18e"
      }
    ],
    "https://www.w3.org/ns/activitystreams#first": [
      {
        "@id": "https://diegoalbuquerque.localhost:8443/tests/collections/notes/pages/f4ec7ef9-58e1-4919-a16f-efa58eeca18e"
      }
    ],
    "https://www.w3.org/ns/activitystreams#items": [
      {
        "@id": "https://diegoalbuquerque.localhost:8443/tests/collections/notes/pages/f4ec7ef9-58e1-4919-a16f-efa58eeca18e"
      }
    ],
    "https://www.w3.org/ns/activitystreams#last": [
      {
        "@id": "https://diegoalbuquerque.localhost:8443/tests/collections/notes/pages/f4ec7ef9-58e1-4919-a16f-efa58eeca18e"
      }
    ],
    "https://www.w3.org/ns/activitystreams#totalItems": [
      {
        "@value": "1",
        "@type": "http://www.w3.org/2001/XMLSchema#integer"
      }
    ]
  }
]

PATCH:
INSERT DATA { <https://diegoalbuquerque.localhost:8443/tests/collections/notes/mynotes> <https://www.w3.org/ns/activitystreams#items> <https://diegoalbuquerque.localhost:8443/tests/collections/notes/items/e635bb42-6769-4811-883e-fafe62d465b3>. }

result of PATCH:

[
  {
    "@id": "https://diegoalbuquerque.localhost:8443/tests/collections/notes/mynotes",
    "https://www.w3.org/ns/activitystreams#items": [
      {
        "@id": "https://diegoalbuquerque.localhost:8443/tests/collections/notes/items/e635bb42-6769-4811-883e-fafe62d465b3"
      }
    ]
  }
]

[ edited to add codefences so data is more clear -- @TallTed ]

I'm also having a similar problem. I identified a problem within the 'writeGraph' function that is called in the patch routine. On line 180, the call to rdflib's serialize function needs a callback function to receive the serialization result if the resource's contentType is "application/ld+json".

Thanks for your contribution. I created #1695
feel free to amend if needed.