Archives
An archive is a collection of resources stored inside an archive file. The archiving format chosen for this purpose is ZIP. Archive resources are rooted in the /v1/archives/{org_label}/{project_label}/
collection.
Each archive…
- belongs to a
project
identifier by the label{project_label}
- inside an
organization
identifier by the label{org_label}
For both reading and modifying archives, the caller must have resources/read
permissions on the current path of the project or the ancestor paths.
Please visit Authentication & authorization section to learn more about it.
Lifecycle
Contrarily to the rest of the platform resources, archives are not persisted resources, given their nature. Therefore there are no update, tag or deprecation operations available on archive resources.
An archive resource will be automatically erased from the system after certain after certain time. This time is configurable (config property plugins.archive.ephemeral.ttl
) and it defaults to 5 hours.
Payload
{
"resources" : [
{
"@type": "Resource",
"resourceId": "{resource_id}",
"project": "{project}",
"path": "{path}",
"originalSource": "{originalSource}",
"format": "{format}",
"rev": "{rev}",
"tag": "{tag}"
},
{
"@type": "File",
"resourceId": "{resource_id}",
"project": "{project}",
"path": "{path}",
"rev": "{rev}",
"tag": "{tag}"
},
{
"@type": "FileSelf",
"value": "{file_self}",
"path": "{path}",
},
{...}
]
}
where…
{resource_id}
: Iri - the @id value of the resource to be added to the archive.{file_self}
: Uri - the_self
value of the file to be added to the archive. This is the same as the http location of the file in the Delta API.{project}
: String - the project (in the format ‘myorg/myproject’) where the specified resource belongs. This field is optional. It defaults to the current project.{path}
: Path - the relative path on the archive where this resource is going to stored- Optional / defaults to
{project}/{resourceId}.json
for a Resource type and{project}/{filename}
for File type. - The provided filename should not exceed 99 characters.
- Optional / defaults to
{originalSource}
: Boolean - flag to decide the whether to fetch the original payload or its compacted form.- Only allowed for Resource type
- Optional and defaults to false
- Can not be present at the same time as
format
field.
{format}
: String - the format we expect for the resource in the archive.- Only allowed for Resource type
- Optional and defaults to compacted
- Accepts the following values: source (to get the original payload), annotated-source (to get the original payload with metadata), compacted, expanded, n-triples, dot
- Can not be present at the same time as
originalSource
field.
{rev}
: Int - the revision of the resource. This field is optional. It defaults to the latest revision.{tag}
: String - the tag of the resource. This field is optional. This field cannot be present at the same time asrev
field.
In order to decide whether we want to select a resource or a file, the @type
discriminator is used with the following possibilities:
Resource
: targets a resourceFile
: targets a file using its project and idFileSelf
: targets a file using its address (_self
)
Create using POST
This endpoint is used to describe the archive and to subsequently consume it.
POST /v1/archives/{org_label}/{project_label}
The json payload:
- If the
@id
value is found on the payload, this @id will be used. - If the
@id
value is not found on the payload, an @id will be generated as follows:base:{UUID}
. Thebase
is theprefix
defined on the resource’s project ({project_label}
).
The response will be an HTTP 303 Location redirect, which will point to the url where to consume the archive (ZIP).
The following diagram can help to understand the HTTP exchange
Example
The following example shows how to create an archive containing 3 files. 2 of them are resources and the other is a file. As a response, the ZIP file will be offered.
- Request
-
source
curl -L \ -X POST \ -H "Content-Type: application/json" -H "Accept: */*" \ "http://localhost:8080/v1/archives/myorg/myproject" \ -d '{ "resources" : [ { "@type": "Resource", "resourceId": "http://localhost:8080/resource1", "rev": 2 }, { "@type": "Resource", "resourceId": "http://localhost:8080/resource2", "project": "myorg/myproject2", "originalSource": false }, { "@type": "File", "resourceId": "http://localhost:8080/resource2", "project": "myorg/myproject2", "path": "my/custom/path/resource2.json" } ] } '
- Payload
-
source
{ "resources" : [ { "@type": "Resource", "resourceId": "http://localhost:8080/resource1", "rev": 2 }, { "@type": "Resource", "resourceId": "http://localhost:8080/resource2", "project": "myorg/myproject2", "format": "expanded" }, { "@type": "File", "resourceId": "http://localhost:8080/resource2", "project": "myorg/myproject2", "path": "my/custom/path/resource2.json" } ] }
Create using PUT
This alternative endpoint to create an archive is useful in case you want to split the creation of the archive resource and the consumption of it.
It can also be useful in cases where one user wants to create the definition of the archive and share the link with another user who then is going to consume it.
PUT /v1/archives/{org_label}/{project_label}/{archive_id}
Example
- Request
-
source
curl -X POST \ -H "Content-Type: application/json" \ "http://localhost:8080/v1/archives/myorg/myproject/myarchive" \ -d '{ "resources" : [ { "@type": "Resource", "resourceId": "http://localhost:8080/resource1", "rev": 2 }, { "@type": "Resource", "resourceId": "http://localhost:8080/resource2", "project": "myorg/myproject2", "originalSource": false }, { "@type": "File", "resourceId": "http://localhost:8080/resource2", "project": "myorg/myproject2", "path": "my/custom/path/resource2.json" } ] } '
- Payload
-
source
{ "resources" : [ { "@type": "Resource", "resourceId": "http://localhost:8080/resource1", "rev": 2 }, { "@type": "Resource", "resourceId": "http://localhost:8080/resource2", "project": "myorg/myproject2", "format": "expanded" }, { "@type": "File", "resourceId": "http://localhost:8080/resource2", "project": "myorg/myproject2", "path": "my/custom/path/resource2.json" } ] }
- Response
-
source
{ "@context": [ "https://bluebrain.github.io/nexus/contexts/archives-metadata.json", "https://bluebrain.github.io/nexus/contexts/metadata.json" ], "@id": "http://localhost:8080/v1/archives/myorg/myproj/myarchive", "@type": "Archive", "_self": "http://localhost:8080/v1/archives/myorg/myproj/myarchive", "_constrainedBy" : "https://bluebrain.github.io/nexus/schemas/archives.json", "_project": "http://localhost:8080/v1/projects/myorg/myproj", "_rev": 1, "_deprecated": false, "_createdAt": "2021-05-17T14:54:42.939Z", "_createdBy": "http://localhost:8080/v1/realms/myrealm/users/john", "_updatedAt": "2021-05-17T14:54:42.939Z", "_updatedBy": "http://localhost:8080/v1/realms/myrealm/users/john" }
Note that if the payload contains an @id different from the {archive_id}
, the request will fail.
Fetch
When fetching an archive, the response format can be chosen through HTTP content negotiation. In order to fetch the archive metadata, the client can use any of the following MIME types. However, in order to fetch the archive content, the HTTP Accept
header should be provided as application/zip
.
@@@
When downloading the archive, it is possible to ignore resources that does not exist by appending the query parameter ignoreNotFound=true
to the fetch link.
GET /v1/archives/{org_label}/{project_label}/{archive_id}
GET /v1/archives/{org_label}/{project_label}/{archive_id}?ignoreNotFound=true
Example
- Request (ZIP)
-
source
curl "http://localhost:8080/v1/archives/myorg/myproject/myarchive" \ -H "Accept: application/x-zip" \ -o output.zip
- Request (metadata)
-
source
curl "http://localhost:8080/v1/archives/myorg/myproject/myarchive" \ -H "Accept: application/json"
- Response
-
source
{ "@context": [ "https://bluebrain.github.io/nexus/contexts/archives.json", "https://bluebrain.github.io/nexus/contexts/metadata.json" ], "@id": "http://localhost:8080/v1/archives/myorg/myproj/myarchive", "@type": "Archive", "resources" : [ { "@type": "Resource", "resourceId": "http://localhost:8080/resource1", "rev": 2 }, { "@type": "Resource", "resourceId": "http://localhost:8080/resource2", "project": "myorg/myproject2", "format": "expanded" }, { "@type": "File", "resourceId": "http://localhost:8080/resource2", "project": "myorg/myproject2", "path": "my/custom/path/resource2.json" } ], "_self": "http://localhost:8080/v1/archives/myorg/myproj/myarchive", "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/archives.json", "_project": "http://localhost:8080/v1/projects/myorg/myproj", "_rev": 1, "_deprecated": false, "_createdAt": "2021-05-17T14:54:42.939Z", "_createdBy": "http://localhost:8080/v1/realms/myrealm/users/john", "_updatedAt": "2021-05-17T14:54:42.939Z", "_updatedBy": "http://localhost:8080/v1/realms/myrealm/users/john", "_expiresInSeconds": 17530 }