Module: FmRest::V1::ContainerFields

Included in:
FmRest::V1
Defined in:
lib/fmrest/v1/container_fields.rb

Constant Summary collapse

DEFAULT_UPLOAD_CONTENT_TYPE =
"application/octet-stream".freeze

Instance Method Summary collapse

Instance Method Details

#fetch_container_data(container_field_url, base_connection = nil) ⇒ IO

Given a container field URL it tries to fetch it and returns an IO object with its body content (see Ruby's OpenURI for how the IO object is extended with useful HTTP response information).

This method uses OpenURI instead of Faraday for fetching the actual container file.

Parameters:

  • container_field_url (String)

    The URL to the container to download

  • base_connection (Faraday::Connection) (defaults to: nil)

    An optional Faraday connection to use as base settings for the container requests, useful if you need to set SSL or proxy settings. If given, this connection will not be used directly, but rather a new one with copied SSL and proxy options. If omitted, FmRest.default_connection_settings's :ssl and :proxy options will be used instead (if available)

Returns:

  • (IO)

    The contents of the container

Raises:



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/fmrest/v1/container_fields.rb', line 25

def fetch_container_data(container_field_url, base_connection = nil)
  require "open-uri"

  if container_field_url == ""
    raise FmRest::ContainerFieldError, "Container field URL is empty string"
  end

  begin
    url = URI(container_field_url)
  rescue ::URI::InvalidURIError, ArgumentError
    raise FmRest::ContainerFieldError, "Invalid container field URL `#{container_field_url}'"
  end

  # Make sure we don't try to open anything on the file:/ URI scheme
  unless url.scheme.match(/\Ahttps?\Z/)
    raise FmRest::ContainerFieldError, "Container field URL is not HTTP (#{container_field_url})"
  end

  ssl_options = base_connection && base_connection.ssl && base_connection.ssl.to_hash
  proxy_options = base_connection && base_connection.proxy && base_connection.proxy.to_hash

  conn =
    Faraday.new(nil,
      ssl:   ssl_options || FmRest.default_connection_settings[:ssl],
      proxy: proxy_options || FmRest.default_connection_settings[:proxy]
    )

  openuri_options =
    faraday_connection_to_openuri_options(conn).merge(redirect: false)

  begin
    url.open(openuri_options)
  rescue OpenURI::HTTPRedirect => e
    unless cookie = e.io.metas.dig("set-cookie", 0)
      raise FmRest::ContainerFieldError, "Container field's initial request didn't return a session cookie, the URL may be stale (try downloading it again immediately after retrieving the record)"
    end

    url = if e.io.meta["location"].match(/\Ahttps?:/)
      URI(e.io.meta["location"])
    else
      URI.join("#{url.scheme}://#{url.host}:#{url.port}", e.io.meta["location"])
    end

    # Now request the URL again with the proper session cookie using
    # OpenURI, which wraps the response in an IO object which also responds
    # to #content_type
    url.open(openuri_options.merge("Cookie" => cookie))
  end
end

#upload_container_data(connection, container_path, filename_or_io, options = {}) ⇒ Object

Handles the core logic of uploading a file into a container field

Parameters:

  • connection (Faraday::Connection)

    the Faraday connection to use

  • container_path (String)

    the path to the container

  • filename_or_io (String, IO)

    a path to the file to upload or an IO object

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :content_type (String) — default: DEFAULT_UPLOAD_CONTENT_TYPE

    The content type for the uploaded file

  • :filename (String)

    The filename to use for the uploaded file, defaults to filename_or_io.original_filename if available



86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/fmrest/v1/container_fields.rb', line 86

def upload_container_data(connection, container_path, filename_or_io, options = {})
  content_type = options[:content_type] || DEFAULT_UPLOAD_CONTENT_TYPE

  connection.post do |request|
    request.url container_path
    request.headers['Content-Type'] = "multipart/form-data"

    filename = options[:filename] || filename_or_io.try(:original_filename)

    request.body = { upload: Faraday::Multipart::FilePart.new(filename_or_io, content_type, filename) }
  end
end