-
Notifications
You must be signed in to change notification settings - Fork 1
Home
Welcome to the Notch8 willow_sword fork wiki! For the full legacy documentation, please see CottageLabs/willow_sword/wiki. This fork provides SWORD V2 support for Valkyrized Hyrax implementations.
NOTE: This fork only supports Valkyrized Hyrax implementations.
Hyku 6 comes with WillowSword pre-installed and ready to use. All tenants can utilize WillowSword's SWORD V2 implementation for depositing and managing content, provided they have a valid API key. This document describes the SWORD V2 endpoints serviced by the willow_sword engine.
Add this line to your application's Gemfile:
gem 'willow_sword', git: 'https://github.com/notch8/willow_sword.git'
And then execute:
$ bundle
$ bundle exec rails generate willow_sword:install
Mount the engine in config/routes.rb:
mount WillowSword::Engine => '/sword'
Configure in config/initializers/willow_sword.rb:
WillowSword.setup do |config|
# The title used by the sword server, in the service document
config.title = 'Hyrax Sword V2 server'
# Default collection if not using collections in Sword
config.default_collection = {id: 'default', title: ['Default collection']}
# Model names for retrieving collections (based on Hyrax integration)
config.collection_models = ['Collection']
# Work models supported by Sword
config.work_models = ['Work']
# FileSet model supported by Sword
config.file_set_models = ['FileSet']
# Remove parameters not in model's permitted attributes
config.allow_only_permitted_attributes = true
# XML mappings
config.xml_mapping_create = 'DC'
config.xml_mapping_read = 'DC'
# Authorize Sword requests using Api-key header
config.authorize_request = true
# Default work model when none provided
config.default_work_model = 'GenericWork'
end
All requests require an API key to be included in the headers:
Api-key: example-key-12345
Failure to provide a valid API key will result in a 403 Forbidden response.
Currently, API keys can only be generated by developers with access to the Rails console:
require 'securerandom'
u = User.find_by_email('hyku_user@instance.test')
u.api_key = SecureRandom.uuid
u.save!
The following metadata namespaces are used in SWORD responses:
| Prefix | Namespace URI | Description |
|---|---|---|
| dc | http://purl.org/dc/elements/1.1/ | Dublin Core (DC) elements for broad compatibility |
| dcterms | http://purl.org/dc/terms/ | Dublin Core Terms (DC Terms), an extended set of metadata elements |
| h4cmeta | https://hykucommons.org/schema/metadata | Hyku Commons-specific metadata for descriptive elements |
| h4csys | https://hykucommons.org/schema/system | Hyku Commons-specific system metadata (e.g., internal identifiers) |
Example error response:
<?xml version="1.0"?>
<error xmlns="http://purl.org/net/sword/error/">
<title>Bad Request</title>
<summary>Title is required</summary>
<sword:treatment>processing failed</sword:treatment>
<generator uri="https://demo.hykucommons.org/" version="2.0"/>
</error>
This implementation is based on the original WillowSword gem created by Cottage Labs CottageLabs/willow_sword. The fork was necessary to modernize the gem for compatibility with Hyrax's Valkyrie resources, moving away from the previous ActiveFedora implementation.
# Welcome to the willow_sword wiki!Welcome to the Notch8 willow_sword fork wiki! For the full legacy documentation, please see [CottageLabs/willow_sword/wiki](https://github.com/CottageLabs/willow_sword/wiki). This fork provides SWORD V2 support for Valkyrized Hyrax implementations.
NOTE: This fork only supports Valkyrized Hyrax implementations.
Hyku 6 comes with WillowSword pre-installed and ready to use. All tenants can utilize WillowSword's SWORD V2 implementation for depositing and managing content, provided they have a valid API key. This document describes the SWORD V2 endpoints serviced by the willow_sword engine.
Add this line to your application's Gemfile:
gem 'willow_sword', git: 'https://github.com/notch8/willow_sword.git'And then execute:
$ bundle
$ bundle exec rails generate willow_sword:installMount the engine in config/routes.rb:
mount WillowSword::Engine => '/sword'Configure in config/initializers/willow_sword.rb:
WillowSword.setup do |config|
# The title used by the sword server, in the service document
config.title = 'Hyrax Sword V2 server'
# Default collection if not using collections in Sword
config.default_collection = {id: 'default', title: ['Default collection']}
# Model names for retrieving collections (based on Hyrax integration)
config.collection_models = ['Collection']
# Work models supported by Sword
config.work_models = ['Work']
# FileSet model supported by Sword
config.file_set_models = ['FileSet']
# Remove parameters not in model's permitted attributes
config.allow_only_permitted_attributes = true
# XML mappings
config.xml_mapping_create = 'DC'
config.xml_mapping_read = 'DC'
# Authorize Sword requests using Api-key header
config.authorize_request = true
# Default work model when none provided
config.default_work_model = 'GenericWork'
endAll requests require an API key to be included in the headers:
Api-key: example-key-12345
Failure to provide a valid API key will result in a 403 Forbidden response.
Currently, API keys can only be generated by developers with access to the Rails console:
require 'securerandom'
u = User.find_by_email('hyku_user@instance.test')
u.api_key = SecureRandom.uuid
u.save!The following metadata namespaces are used in SWORD responses:
| Prefix | Namespace URI | Description |
|---|---|---|
| dc | http://purl.org/dc/elements/1.1/ | Dublin Core (DC) elements for broad compatibility |
| dcterms | http://purl.org/dc/terms/ | Dublin Core Terms (DC Terms), an extended set of metadata elements |
| h4cmeta | https://hykucommons.org/schema/metadata | Hyku Commons-specific metadata for descriptive elements |
| h4csys | https://hykucommons.org/schema/system | Hyku Commons-specific system metadata (e.g., internal identifiers) |
Dublin Core Terms (dcterms) is a superset of the original Dublin Core (dc) metadata standard. While Hyrax/Hyku primarily uses DC Terms, the SWORD response also includes DC elements to support legacy clients that may only recognize the dc namespace whenever possible.
<feed xmlns="http://www.w3.org/2005/Atom"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:dcterms="http://purl.org/dc/terms/"
xmlns:h4cmeta="https://hykucommons.org/schema/metadata"
xmlns:h4csys="https://hykucommons.org/schema/system">
<title>A Test, For Documentation</title>
<content rel="src" href="https://demo.hykucommons.org/sword/collections/default/works/some-work-id"/>
<link rel="edit" href="https://demo.hykucommons.org/sword/collections/default/works/some-work-id/file_sets"/>
<entry>
<content rel="src" href=".../file_sets/some-file-set-id"/>
<link rel="edit" href=".../file_sets/some-file-set-id"/>
</entry>
<h4csys:id>some-work-id-1234</h4csys:id>
<h4csys:internal_resource>Image</h4csys:internal_resource>
<h4csys:created_at>2024-07-10 23:04:45 UTC</h4csys:created_at>
<h4csys:updated_at>2025-02-05 22:19:27 UTC</h4csys:updated_at>
<h4cmeta:title>A Test</h4cmeta:title>
<h4cmeta:title>For Documentation</h4cmeta:title>
<dc:title>A Test</dc:title>
<dcterms:abstract>This is the abstract, it's so short!</dcterms:abstract>
<!-- ... additional metadata fields ... -->
</feed>The service document will deliver collection elements representing both Admin Sets and Collections. The type child element will describe this with values of "AdminSet" and "Collection".
| Type | Description |
|---|---|
| AdminSet | Represents an Admin Set in Hyrax, used for policy and workflow control |
| Collection | Represents a Collection, created by end users to organize works |
<feed xmlns="http://www.w3.org/2005/Atom">
<title>A Collection</title>
<type>Collection</type>
<link rel="edit" href="https://demo.hykucommons.org/sword/collections/some-collection-id/works"/>
<entry>
<content rel="src" href=".../works/some-work-id"/>
<link rel="edit" href=".../works/some-work-id/file_sets"/>
</entry>
</feed>Replace https://demo.hykucommons.org with your instance's base URL in all examples.
To specify a work type when creating a new work, add the Hyrax-Work-Model header to your request:
Hyrax-Work-Model: Etd
You can pass either the standard name (e.g., Etd) or the resource name (e.g., EtdResource). The system will prioritize creating the Valkyrie version (EtdResource) when available.
If this header is not included, the system will default to GenericWorkResource.
There are two ways to specify the Admin Set for a new work:
-
Via URL (Recommended): Include the Admin Set ID in the URL path:
https://demo.hykucommons.org/sword/collections/{admin_set_id}/works/Example:
curl --request POST \ --url https://demo.hykucommons.org/sword/collections/e01455cb-9877-4c28/works/ \ --header 'Hyrax-Work-Model: Etd' \ --header 'Api-key: example-key-12345' \ --data-binary @metadata.xml
-
Via Metadata XML (not in spec with SWORD): Include the Admin Set ID in the metadata XML:
<admin_set_id>e01455cb-9877-4c28-aa1c-012caa000642</admin_set_id>
If the Admin Set ID is not provided through either method, or if an invalid ID is used, the system will default to the Default Admin Set.
To deposit into the default admin set, use the string default:
--url https://demo.hykucommons.org/sword/collections/default/works/Note: When depositing to a Collection (not an Admin Set), you should continue to use the collection ID in the metadata XML.
When creating a work, the response includes the work ID and file set IDs:
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Molecular Mechanisms Controlling Immunity</title>
<content rel="src" href=".../works/ddb7aef4-ef23-4cdb-a777-78d3f35126d9"/>
<link rel="edit" href=".../works/ddb7aef4-ef23-4cdb-a777-78d3f35126d9/file_sets"/>
<entry>
<content rel="src" href=".../file_sets/c7426a7f-def1-481d-abf3-dcd54b5c9ef2"/>
<link rel="edit" href=".../file_sets/c7426a7f-def1-481d-abf3-dcd54b5c9ef2"/>
</entry>
<!-- Additional file entries may be listed here -->
</feed>Retrieves the SWORD service document describing available collections and accepted package formats.
Request:
curl --request GET \
--url https://demo.hykucommons.org/sword/service_document \
--header 'Content-Type: application/xml' \
--header 'Api-key: example-key-12345'Returns a list of works in the specified collection.
Request:
curl --request GET \
--url https://demo.hykucommons.org/sword/collections/example-collection-id-12345 \
--header 'Content-Type: application/xml' \
--header 'Api-key: example-key-12345'There are two methods to create a new work with metadata only:
Request:
curl --request POST \
--url https://demo.hykucommons.org/sword/collections/example-admin-set-id-12345/works \
--header 'Content-Disposition: attachment; filename=metadata.xml' \
--header 'Content-Type: application/xml' \
--header 'In-Progress: false' \
--header 'On-Behalf-Of: admin@example.com' \
--header 'Packaging: application/atom+xml;type=entry' \
--header 'Hyrax-Work-Model: Etd' \
--header 'Api-key: example-key-12345' \
--data-binary @dc.xmlRequest:
curl --request POST \
--url https://demo.hykucommons.org/sword/collections/example-admin-set-id-12345/works \
--header 'In-Progress: false' \
--header 'On-Behalf-Of: admin@example.com' \
--header 'Hyrax-Work-Model: Etd' \
--header 'Api-key: example-key-12345' \
-F metadata=@dc.xmlSeveral methods are available for adding works with associated files:
Request:
curl --request POST \
--url https://demo.hykucommons.org/sword/collections/example-admin-set-id-12345/works/ \
--header 'Content-Disposition: attachment; filename=testPackage.zip' \
--header 'Content-Type: application/zip' \
--header 'In-Progress: false' \
--header 'On-Behalf-Of: admin@example.com' \
--header 'Packaging: http://purl.org/net/sword/package/SimpleZip' \
--header 'Hyrax-Work-Model: Etd' \
--header 'Api-key: example-key-12345' \
--data-binary @testPackage.zipRequest:
curl --request POST \
--url https://demo.hykucommons.org/sword/collections/example-admin-set-id-12345/works/ \
--header 'In-Progress: false' \
--header 'On-Behalf-Of: admin@example.com' \
--header 'Hyrax-Work-Model: Etd' \
--header 'Api-key: example-key-12345' \
-F metadata=@metadata.xml \
-F payload=@testPackage.zipRequest:
curl --request POST \
--url https://demo.hykucommons.org/sword/collections/example-admin-set-id-12345/works/ \
--header 'In-Progress: false' \
--header 'On-Behalf-Of: admin@example.com' \
--header 'Hyrax-Work-Model: Etd' \
--header 'Api-key: example-key-12345' \
-F payload=@testPackage.zipThe API supports BagIt-formatted packages:
Request:
curl --request POST \
--url https://demo.hykucommons.org/sword/collections/example-admin-set-id-12345/works/ \
--header 'Content-Disposition: attachment; filename=testPackage1InBagit.zip' \
--header 'Content-MD5: example-md5-12345' \
--header 'Content-Type: application/zip' \
--header 'Packaging: http://purl.org/net/sword/package/BagIt' \
--header 'Hyrax-Work-Model: Etd' \
--header 'Api-key: example-key-12345' \
--data-binary @testPackageInBagit.zipRequest:
curl --request GET \
--url https://demo.hykucommons.org/sword/collections/default/works/example-work-id-12345 \
--header 'Api-key: example-key-12345'Request:
curl --request GET \
--url https://demo.hykucommons.org/sword/collections/default/works/example-work-id-12345/file_sets/example-file-set-id-12345 \
--header 'Api-key: example-key-12345'Request:
curl --request POST \
--url https://demo.hykucommons.org/sword/collections/default/works/example-work-id-12345/file_sets/ \
--header 'Content-Disposition: attachment; filename=example.pdf' \
--header 'Content-MD5: example-md5-12345' \
--header 'Content-Type: application/pdf' \
--header 'In-Progress: false' \
--header 'On-Behalf-Of: admin@example.com' \
--header 'Packaging: http://purl.org/net/sword/package/Binary' \
--header 'Api-key: example-key-12345' \
--data-binary @example.pdfRequest:
curl --request PUT \
--url https://demo.hykucommons.org/sword/collections/default/works/example-work-id-12345/ \
--header 'Content-Disposition: attachment; filename=metadata.xml' \
--header 'Content-Type: application/xml' \
--header 'Packaging: application/atom+xml;type=entry' \
--header 'Api-key: example-key-12345' \
--data-binary @dc.xmlRequest:
curl --request PUT \
--url https://demo.hykucommons.org/sword/collections/default/works/example-work-id-12345/file_sets/example-file-set-id-12345 \
--header 'Content-Disposition: attachment; filename=metadata.xml' \
--header 'Content-Type: application/xml' \
--header 'Packaging: application/atom+xml;type=entry' \
--header 'Api-key: example-key-12345' \
--data-binary @dc.xmlBasic ZIP file containing files and optional metadata.xml:
package.zip
├── file1.pdf
├── file2.jpg
└── metadata.xml (optional)
Standardized format for digital preservation:
bagit.zip
├── bag-info.txt
├── bagit.txt
├── manifest-md5.txt
├── data/
│ ├── file1.pdf
│ ├── file2.jpg
│ └── metadata/
│ └── metadata.xml
└── tagmanifest-md5.txt
Single file upload without packaging. Use header:
Packaging: http://purl.org/net/sword/package/Binary
A set of test files is available for validating your implementation: [swordv2_test_files.zip](https://github.com/scientist-softserv/palni-palci/files/15228815/swordv2_test_files.zip)
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<title>Test Record</title>
<creator>Hyku User</creator>
<subject>Sword</subject>
<subject>Implementation</subject>
<description>This is a test dc record to test</description>
<publisher>PALNI-PALCI</publisher>
<contributor>Notch8</contributor>
<created>29/05/2018</created>
<source>https://www.hykucommons.org/</source>
<language>English</language>
<rights_statement>http://rightsstatements.org/vocab/InC/1.0/</rights_statement>
<resource_type>Article</resource_type>
<keyword>Test</keyword>
<keyword>Another</keyword>
<visibility>lease</visibility>
<visibility_during_lease>authenticated</visibility_during_lease>
<lease_expiration_date>2024-05-31</lease_expiration_date>
<visibility_after_lease>restricted</visibility_after_lease>
<!-- if no admin set id is specified, it will fallback to the Default Admin Set -->
<admin_set_id>some-admin-set-id</admin_set_id>
</metadata>The API uses standard SWORD V2 error responses:
| Error | HTTP Code | Description |
|---|---|---|
| ErrorContent | 415 | Unsupported media type |
| ErrorChecksumMismatch | 412 | MD5 checksum mismatch |
| ErrorBadRequest | 400 | Malformed request |
| TargetOwnerUnknown | 403 | Unknown On-Behalf-Of user |
| MediationNotAllowed | 412 | Mediation not permitted |
| MethodNotAllowed | 405 | HTTP method not supported |
| MaxUploadSizeExceeded | 413 | File too large |
| ErrorUnprocessableEntity | 422 | Cannot process entity |
Example error response:
<?xml version="1.0"?>
<error xmlns="http://purl.org/net/sword/error/">
<title>Bad Request</title>
<summary>Title is required</summary>
<sword:treatment>processing failed</sword:treatment>
<generator uri="https://demo.hykucommons.org/" version="2.0"/>
</error>This implementation is based on the original WillowSword gem created by Cottage Labs [CottageLabs/willow_sword](https://github.com/CottageLabs/willow_sword). The fork was necessary to modernize the gem for compatibility with Hyrax's Valkyrie resources, moving away from the previous ActiveFedora implementation.