class Filemaker::Server

Attributes

database[R]

@return [Filemaker::Store::DatabaseStore] the database store

databases[R]

@return [Filemaker::Store::DatabaseStore] the database store

db[R]

@return [Filemaker::Store::DatabaseStore] the database store

Public Class Methods

new() { |config| ... } click to toggle source
# File lib/filemaker/server.rb, line 18
def initialize
  @config = Configuration.new
  yield @config if block_given?
  raise ArgumentError, 'Missing config block' if @config.not_configurable?

  @databases = Store::DatabaseStore.new(self)
end

Public Instance Methods

handler_names() click to toggle source
# File lib/filemaker/server.rb, line 79
def handler_names
  @connection.builder.handlers.map(&:name)
end
perform_request(action, args, options = {}) click to toggle source

@api private Mostly used by Filemaker::Api TODO: There must be tracing/instrumentation. CURL etc. Or performance metrics? Also we want to pass in timeout option so we can ignore timeout for really long requests

@return [Array] response and request params Hash

# File lib/filemaker/server.rb, line 34
def perform_request(action, args, options = {})
  params = serialize_args(args)
           .merge(expand_options(options))
           .merge({ action => '' })

  # Serialize the params for submission??
  params.stringify_keys!

  log_action(params)

  # yield params if block_given?

  response = get_typhoeus_connection(params)

  http_status = "#{response.response_code}:#{response.return_code}"

  case response.response_code
  when 200
    [response, params]
  when 401
    raise Errors::AuthenticationError,
          "[#{http_status}] Authentication failed."
  when 0
    if response.return_code == :operation_timedout
      raise Errors::HttpTimeoutError,
            "[#{http_status}] Current timeout value is #{timeout}"
    else
      raise Errors::CommunicationError,
            "[#{http_status}] Empty response."
    end
  when 404
    raise Errors::CommunicationError,
          "[#{http_status}] Not found"
  when 302
    raise Errors::CommunicationError,
          "[#{http_status}] Redirect not supported"
  when 502
    raise Errors::CommunicationError,
          "[#{http_status}] Bad gateway. Too many records."
  else
    msg = "Unknown response code = #{http_status}"
    raise Errors::CommunicationError, msg
  end
end

Private Instance Methods

colorize(color, message) click to toggle source
# File lib/filemaker/server.rb, line 219
def colorize(color, message)
  "\e[#{color}m#{message}\e[0m"
end
expand_options(options) click to toggle source
# File lib/filemaker/server.rb, line 119
def expand_options(options)
  expanded = {}
  options.each do |key, value|
    case key
    when :max
      expanded['-max'] = value
    when :skip
      expanded['-skip'] = value
    when :sortfield
      if value.is_a? Array
        msg = 'Too many sortfield, limit=9'
        raise(Filemaker::Errors::ParameterError, msg) if value.size > 9
        value.each_index do |index|
          expanded["-sortfield.#{index + 1}"] = value[index]
        end
      else
        expanded['-sortfield.1'] = value
      end
    when :sortorder
      if value.is_a? Array
        # Use :sortfield as single source of truth for array size
        msg = 'Too many sortorder, limit=9'
        raise(Filemaker::Errors::ParameterError, msg) if value.size > 9
        options[:sortfield].each_index do |index|
          expanded["-sortorder.#{index + 1}"] = value[index] || 'ascend'
        end
      else
        expanded['-sortorder.1'] = value
      end
    when :lay_response
      expanded['-lay.response'] = value
    when :lop
      expanded['-lop'] = value
    when :modid
      expanded['-modid'] = value
    when :relatedsets_filter
      expanded['-relatedsets.filter'] = value
    when :relatedsets_max
      expanded['-relatedsets.max'] = value
    when :delete_related
      expanded['-delete.related'] = value
    when :script
      if value.is_a? Array
        expanded['-script'] = value[0]
        expanded['-script.param'] = value[1]
      else
        expanded['-script'] = value
      end
    when :script_prefind
      if value.is_a? Array
        expanded['-script.prefind'] = value[0]
        expanded['-script.prefind.param'] = value[1]
      else
        expanded['-script.prefind'] = value
      end
    when :script_presort
      if value.is_a? Array
        expanded['-script.presort'] = value[0]
        expanded['-script.presort.param'] = value[1]
      else
        expanded['-script.presort'] = value
      end
    end
  end

  expanded
end
get_typhoeus_connection(body) click to toggle source
# File lib/filemaker/server.rb, line 85
def get_typhoeus_connection(body)
  request = Typhoeus::Request.new(
    "#{url}#{endpoint}",
    method: :post,
    ssl_verifypeer: ssl_verifypeer,
    ssl_verifyhost: ssl_verifyhost,
    userpwd: "#{account_name}:#{password}",
    body: body,
    timeout: timeout || 0
  )

  request.run
end
log_action(params) click to toggle source

TODO: Should we convert it to string so 'cURL' will work also?

# File lib/filemaker/server.rb, line 188
def log_action(params)
  case @config.log.to_s
  when 'simple'    then log_simple(params)
  when 'curl'      then log_curl(params)
  when 'curl_auth' then log_curl(params, true)
  end
end
log_curl(params, has_auth = false) click to toggle source
# File lib/filemaker/server.rb, line 196
def log_curl(params, has_auth = false)
  full_url        = "#{url}#{endpoint}?#{log_params(params)}"
  curl_ssl_option = ''
  auth            = ''

  curl_ssl_option = ' -k' unless ssl_verifypeer

  auth = " -u #{account_name}:[FILTERED]" if has_auth

  # warn 'Pretty print like so: `curl XXX | xmllint --format -`'
  warn "curl -XGET '#{full_url}'#{curl_ssl_option} -i#{auth}"
end
log_params(params) click to toggle source
# File lib/filemaker/server.rb, line 213
def log_params(params)
  params.map do |key, value|
    "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}"
  end.join('&')
end
log_simple(params) click to toggle source
# File lib/filemaker/server.rb, line 209
def log_simple(params)
  warn colorize('48;2;255;0;0', "#{endpoint}?#{log_params(params)}")
end
serialize_args(args) click to toggle source

{“-db”=>“mydb”, “-lay”=>“mylay”, “email”=>“a@b.com”, “updated_at”: Date} Take Ruby type and serialize into a form FileMaker can understand

# File lib/filemaker/server.rb, line 101
def serialize_args(args)
  return {} if args.nil?

  args.each do |key, value|
    case value
    when DateTime, Time
      args[key] = value.strftime('%m/%d/%Y %H:%M:%S')
    when Date
      args[key] = value.strftime('%m/%d/%Y')
    else
      # Especially for range operator (...), we want to output as String
      args[key] = value.to_s
    end
  end

  args
end