lib/faastruby-rpc/function.rb in faastruby-rpc-0.1.3 vs lib/faastruby-rpc/function.rb in faastruby-rpc-0.2.0

- old
+ new

@@ -1,88 +1,128 @@ module FaaStRuby FAASTRUBY_HOST = ENV['FAASTRUBY_HOST'] || "http://localhost:3000" module RPC - @@response = {} - def self.stub_call(function_path, &block) - helper = TestHelper.new - block.call(helper) - response = Struct.new(:body, :code, :headers, :klass) - @@response[function_path] = response.new(helper.body, helper.code, helper.headers, helper.klass) - end - def self.stub_call?(path) - @@response[path] - end - - def self.response(path) - @@response[path] - end - class ExecutionError < StandardError end + class Response + attr_reader :body, :code, :headers, :klass + def initialize(body, code, headers, klass = nil) + @body = body + @code = code + @headers = headers + @klass = klass + end + end class Function 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 } - @response = Struct.new(:body, :code, :headers, :klass) @raise_errors = raise_errors end - def with(*args) - call(body: Oj.dump(args), headers: {'Content-Type' => 'application/json', 'Faastruby-Rpc' => 'true'}) + def call_with(*args) + execute(req_body: Oj.dump(args), headers: {'Content-Type' => 'application/json', 'Faastruby-Rpc' => 'true'}) end - def call(body: nil, query_params: {}, headers: {}, method: 'post') - url = "#{FAASTRUBY_HOST}/#{@path}#{convert_query_params(query_params)}" - uri = URI.parse(url) - use_ssl = uri.scheme == 'https' ? true : false - response = FaaStRuby::RPC.stub_call?(@path) ? FaaStRuby::RPC.response(@path) : fetch(use_ssl: use_ssl, uri: uri, headers: headers, method: @methods[method], body: body) - resp_headers = {} - response.each{|k,v| resp_headers[k] = v} - case resp_headers['content-type'] - when 'application/json' - begin - resp_body = Oj.load(response.body) - rescue Oj::ParseError => e - if response.body.is_a?(String) - resp_body = response.body - else - raise e if @raise_errors - resp_body = { - 'error' => e.message, - 'location' => e.backtrace&.first - } + def call(*args) + return call_with(*args) if args.any? + execute(method: 'get') + end + + def execute(req_body: nil, query_params: {}, headers: {}, method: 'post') + @thread = Thread.new do + url = "#{FAASTRUBY_HOST}/#{@path}#{convert_query_params(query_params)}" + uri = URI.parse(url) + use_ssl = uri.scheme == 'https' ? true : false + response = fetch(use_ssl: use_ssl, uri: uri, headers: headers, method: @methods[method], req_body: req_body) + resp_headers = {} + response.each{|k,v| resp_headers[k] = v} + case resp_headers['content-type'] + when 'application/json' + begin + resp_body = Oj.load(response.body) + rescue Oj::ParseError => e + if response.body.is_a?(String) + resp_body = 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(response.body) + else + resp_body = response.body end - when 'application/yaml' - resp_body = YAML.load(response.body) - else - resp_body = response.body + raise FaaStRuby::RPC::ExecutionError.new("Function #{@path} returned status code #{response.code} - #{resp_body['error']} - #{resp_body['location']}") if response.code.to_i >= 400 && @raise_errors + @response = FaaStRuby::RPC::Response.new(resp_body, response.code.to_i, resp_headers) end - raise FaaStRuby::RPC::ExecutionError.new("Function #{@path} returned status code #{response.code} - #{resp_body['error']} - #{resp_body['location']}") if response.code.to_i >= 400 && @raise_errors - @response.new(resp_body, response.code.to_i, resp_headers) + self end + def returned? + !@response.nil? + end + + def response + wait unless returned? + @response + end + + def to_s + body || "" + end + + def body + # wait unless returned? + response.body + end + + def code + # wait unless returned? + response.code + end + + def headers + # wait unless returned? + response.headers + end + + def klass + # wait unless returned? + response.klass + end + private + + def wait + @thread.join + end + def convert_query_params(query_params) return "" unless query_params.any? "?#{URI.encode_www_form(query_params)}" end - def fetch(use_ssl:, uri:, limit: 10, method: Net::HTTP::Post, headers: {}, body: nil) + 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 = body + request.body = req_body response = http.request(request) case response when Net::HTTPSuccess then response