class Stash::Sword::Client

Constants

EOL

Attributes

collection_uri[R]
helper[R]
password[R]
username[R]

Public Class Methods

new(collection_uri:, username:, password:, on_behalf_of: nil, logger: nil, helper: nil) click to toggle source

Creates a new {Client} for the specified collection URI, with the specified credentials.

@param collection_uri [URI, String] The collection URI @param username [String] the username @param password [String] the password @param on_behalf_of [String, nil] the user for whom the original sword package was deposited on behalf of.

Defaults to `username`.

@param logger [Logger, nil] the logger to use, or nil to use a default logger

# File lib/stash/sword/client.rb, line 29
def initialize(collection_uri:, username:, password:, on_behalf_of: nil, logger: nil, helper: nil) # rubocop:disable Metrics/ParameterLists
  validate(collection_uri, password, username)
  @collection_uri = to_uri(collection_uri)
  @username     = username
  @password     = password
  @on_behalf_of = on_behalf_of || username
  @helper       = helper || HTTPHelper.new(username: username, password: password, user_agent: "stash-sword #{VERSION}", logger: logger)
  @log          = logger || default_logger
end

Public Instance Methods

create(doi:, zipfile:) click to toggle source

Creates a new resource for the specified DOI with the specified zipfile

@param doi [String] the DOI @param zipfile [String] the zipfile path @return [DepositReceipt] the deposit receipt

# File lib/stash/sword/client.rb, line 44
def create(doi:, zipfile:)
  log.debug("Stash::Sword::Client.create(doi: #{doi}, zipfile: #{zipfile})")
  uri = collection_uri.to_s
  response = do_post(uri, zipfile, create_request_headers(zipfile, doi))
  receipt_from(response)
rescue => e
  log_error(e)
  raise
end
update(edit_iri:, zipfile:) click to toggle source

Updates a resource with a new zipfile

@param edit_iri [URI, String] the Atom Edit-IRI @param zipfile [String] the zipfile path @return [Integer] the response code (if the request succeeds)

# File lib/stash/sword/client.rb, line 59
def update(edit_iri:, zipfile:)
  log.debug("Stash::Sword::Client.update(edit_iri: #{edit_iri}, zipfile: #{zipfile})")
  uri = to_uri(edit_iri).to_s
  response = do_put(uri, zipfile)
  log.debug(to_log_msg(response))
  response.code # TODO: what if anything should we return here?
rescue => e
  log_error(e)
  raise
end

Protected Instance Methods

to_uri(url) click to toggle source
# File lib/stash/sword/client.rb, line 130
def to_uri(url)
  ::XML::MappingExtensions.to_uri(url)
end

Private Instance Methods

do_post(uri, zipfile, headers) click to toggle source
# File lib/stash/sword/client.rb, line 99
def do_post(uri, zipfile, headers)
  File.open(zipfile, 'rb') do |file|
    return helper.post(uri: uri, payload: file, headers: headers)
  end
end
do_put(uri, zipfile) click to toggle source
# File lib/stash/sword/client.rb, line 105
def do_put(uri, zipfile)
  boundary        = "========#{Time.now.to_i}=="
  stream          = stream_for(zipfile: File.open(zipfile, 'rb'), boundary: boundary)
  begin
    return helper.put(uri: uri, headers: update_request_headers(stream, boundary), payload: stream)
  ensure
    stream.close
  end
end
receipt_from(response) click to toggle source
# File lib/stash/sword/client.rb, line 78
def receipt_from(response)
  log.debug(to_log_msg(response))

  body = response.body.strip
  return DepositReceipt.parse_xml(body) unless body.empty?

  receipt_from_location(response)
end
receipt_from_location(response) click to toggle source
# File lib/stash/sword/client.rb, line 87
def receipt_from_location(response)
  log.debug('Desposit receipt not provided in SWORD response body')
  edit_iri = response.headers[:location]
  return nil unless edit_iri

  log.debug("Retrieving deposit receipt from Location header Edit-IRI: #{edit_iri}")
  body = helper.get(uri: to_uri(edit_iri))
  return nil unless body

  DepositReceipt.parse_xml(body)
end
stream_for(zipfile:, boundary:) click to toggle source
# File lib/stash/sword/client.rb, line 115
def stream_for(zipfile:, boundary:)
  content = []
  # strictly speaking, do we need an Atom <entry/> first?
  content << "--#{boundary}#{EOL}"
  update_mime_headers(zipfile).each { |k, v| content << "#{k}: #{v}#{EOL}" }
  content << EOL
  content << zipfile
  content << EOL
  content << "--#{boundary}--#{EOL}"

  log.debug("Payload:\n\t#{content.map(&:to_s).join("\t")}")

  SequenceIO.new(content).binmode
end
validate(collection_uri, password, username) click to toggle source
# File lib/stash/sword/client.rb, line 72
def validate(collection_uri, password, username)
  raise 'no collection URI provided' unless collection_uri
  raise 'no username provided' unless username
  raise 'no password provided' unless password
end