class FaaStRuby::RPC::Function

Public Class Methods

new(path, raise_errors: true) click to toggle source
# File lib/faastruby-rpc/function.rb, line 24
def initialize(path, raise_errors: true)
  @response = nil
  @path = path
  @methods = {
    'post' => Net::HTTP::Post,
    'get' => Net::HTTP::Get,
    'put' => Net::HTTP::Put,
    'patch' => Net::HTTP::Patch,
    'delete' => Net::HTTP::Delete
  }
  @raise_errors = raise_errors
end
workspace=(workspace) click to toggle source
# File lib/faastruby-rpc/function.rb, line 21
def self.workspace=(workspace)
  @@workspace = workspace
end

Public Instance Methods

body() click to toggle source

alias_method :read, :to_s

# File lib/faastruby-rpc/function.rb, line 114
def body
  # wait unless returned?
  response.body
end
call(*args) { |output| ... } click to toggle source
# File lib/faastruby-rpc/function.rb, line 37
def call(*args)
  @thread = Thread.new do
    output = args.any? ? call_with(*args) : execute(method: 'get')
    @response.body = yield(output) if block_given?
  end
  self
end
code() click to toggle source
# File lib/faastruby-rpc/function.rb, line 119
def code
  # wait unless returned?
  response.code
end
execute(req_body: nil, query_params: {}, headers: {}, method: 'post') click to toggle source
# File lib/faastruby-rpc/function.rb, line 50
def execute(req_body: nil, query_params: {}, headers: {}, method: 'post')
  url = get_endpoint(convert_query_params(query_params))
  uri = URI.parse(url)
  use_ssl = uri.scheme == 'https' ? true : false
  function_response = fetch(use_ssl: use_ssl, uri: uri, headers: headers, method: @methods[method], req_body: req_body)
  resp_headers = {}
  function_response.each{|k,v| resp_headers[k] = v}
  case resp_headers['content-type']
  when 'application/json'
    begin
      resp_body = Oj.load(function_response.body)
    rescue Oj::ParseError => e
      if function_response.body.is_a?(String)
        resp_body = function_response.body
      else
        raise e if @raise_errors
        resp_body = {
          'error' => e.message,
          'location' => e.backtrace&.first
        }
      end
    end
  when 'application/yaml'
    resp_body = YAML.load(function_response.body)
  else
    resp_body = function_response.body
  end
  if function_response.code.to_i >= 400 && @raise_errors
    location = resp_body['location'] ? " @ #{resp_body['location']}" : nil
    error_msg = "#{resp_body['error']}#{location}"
    raise FaaStRuby::RPC::ExecutionError.new("Function '#{@path}' returned status code #{function_response.code}: #{error_msg}")
  end
  @response = FaaStRuby::RPC::Response.new(resp_body, function_response.code.to_i, resp_headers)
  self
end
get_endpoint(query_params) click to toggle source
# File lib/faastruby-rpc/function.rb, line 45
def get_endpoint(query_params)
  return "#{@@endpoint_base_protocol}://#{@@workspace}.#{@@region}.#{@@endpoint_base_host}/#{@path}#{query_params}" if @@endpoint_base_host && @@region && @@workspace
  return "http://localhost:3000/#{@path}#{query_params}"
end
headers() click to toggle source
# File lib/faastruby-rpc/function.rb, line 124
def headers
  # wait unless returned?
  response.headers
end
inspect() click to toggle source
# File lib/faastruby-rpc/function.rb, line 108
def inspect
  body.inspect || ""
end
klass() click to toggle source
# File lib/faastruby-rpc/function.rb, line 129
def klass
  # wait unless returned?
  response.klass
end
method_missing(m, *args, &block) click to toggle source
# File lib/faastruby-rpc/function.rb, line 94
def method_missing(m, *args, &block)
  rsp = response.body
  rsp.send(m.to_sym, *args, &block)
end
response() click to toggle source
# File lib/faastruby-rpc/function.rb, line 99
def response
  wait unless returned?
  @response
end
returned?() click to toggle source
# File lib/faastruby-rpc/function.rb, line 86
def returned?
  !@response.nil?
end
to_s() click to toggle source
# File lib/faastruby-rpc/function.rb, line 104
def to_s
  body.to_s || ""
end
value() click to toggle source
# File lib/faastruby-rpc/function.rb, line 90
def value
  body
end

Private Instance Methods

call_with(*args) click to toggle source
# File lib/faastruby-rpc/function.rb, line 136
def call_with(*args)
  execute(req_body: Oj.dump(args, mode: :compat), headers: {'Content-Type' => 'application/json', 'Faastruby-Rpc' => 'true'})
end
convert_query_params(query_params) click to toggle source
# File lib/faastruby-rpc/function.rb, line 144
def convert_query_params(query_params)
  return "" unless query_params.any?
  "?#{URI.encode_www_form(query_params)}"
end
fetch(use_ssl:, uri:, limit: 10, method: Net::HTTP::Post, headers: {}, req_body: nil) click to toggle source
# File lib/faastruby-rpc/function.rb, line 149
def fetch(use_ssl:, uri:, limit: 10, method: Net::HTTP::Post, headers: {}, req_body: nil)
  # You should choose a better exception.
  raise ArgumentError, 'too many HTTP redirects' if limit == 0
  http = Net::HTTP.new(uri.host, uri.port)
  if use_ssl
    http.use_ssl = true
    http.ssl_options = OpenSSL::SSL::OP_NO_SSLv2 + OpenSSL::SSL::OP_NO_SSLv3 + OpenSSL::SSL::OP_NO_COMPRESSION
  end
  request = method.new(uri.request_uri, headers)
  request.body = req_body
  response = http.request(request)

  case response
  when Net::HTTPSuccess then
    response
  when Net::HTTPRedirection then
    location = URI.parse(response['location'])
    warn "redirected to #{location}"
    fetch(use_ssl: use_ssl, uri: location, limit: limit - 1, method: method, headers: headers, body: body)
  else
    response.value
  end

rescue Net::HTTPServerException, Net::HTTPFatalError
  return response
end
wait() click to toggle source
# File lib/faastruby-rpc/function.rb, line 140
def wait
  @thread.join
end