module FmRest::V1::ContainerFields

Constants

DEFAULT_UPLOAD_CONTENT_TYPE

Public Instance Methods

fetch_container_data(container_field_url, base_connection = nil) click to toggle source

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.

@raise [FmRest::ContainerFieldError] if any step fails @param container_field_url [String] The URL to the container to

download

@param base_connection [Faraday::Connection] 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)

@return [IO] The contents of the container

# File lib/fmrest/v1/container_fields.rb, line 25
def fetch_container_data(container_field_url, base_connection = nil)
  require "open-uri"

  begin
    url = URI(container_field_url)
  rescue ::URI::InvalidURIError
    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 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 = URI(e.io.meta["location"])

    # 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 = {}) click to toggle source

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

@param connection [Faraday::Connection] the Faraday connection to use @param container_path [String] the path to the container @param filename_or_io [String, IO] a path to the file to upload or an

IO object

@param options [Hash] @option options [String] :content_type (DEFAULT_UPLOAD_CONTENT_TYPE)

The content type for the uploaded file

@option options [String] :filename The filename to use for the uploaded

file, defaults to `filename_or_io.original_filename` if available
# File lib/fmrest/v1/container_fields.rb, line 78
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'] = ::Faraday::Request::Multipart.mime_type

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

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

Private Instance Methods

faraday_connection_to_openuri_options(conn) click to toggle source

Copies a Faraday::Connection's relevant options to OpenURI::OpenRead#open format

# File lib/fmrest/v1/container_fields.rb, line 96
def faraday_connection_to_openuri_options(conn)
  openuri_opts = {}

  if !conn.ssl.empty?
    openuri_opts[:ssl_verify_mode] =
      conn.ssl.fetch(:verify, true) ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE

    openuri_opts[:ssl_ca_cert] = conn.ssl.cert_store if conn.ssl.cert_store
  end

  if conn.proxy && !conn.proxy.empty?
    if conn.proxy.user && conn.proxy.password
      openuri_opts[:proxy_http_basic_authentication] =
        [conn.proxy.uri.tap { |u| u.userinfo = ""}, conn.proxy.user, conn.proxy.password]
    else
      openuri_opts[:proxy] = conn.proxy.uri
    end
  end

  openuri_opts
end