exe/faastruby-server in faastruby-0.4.2 vs exe/faastruby-server in faastruby-0.4.3

- old
+ new

@@ -4,61 +4,88 @@ require 'sinatra/multi_route' require 'yaml' require 'oj' require 'faastruby-rpc' -module FaaStRubyFunction - def self.call(workspace_name, function_name, event, args) - begin - load "./#{workspace_name}/#{function_name}/handler.rb" - response = handler(event, *args) - return response if response.is_a?(FaaStRubyFunction::Response) - body = { - 'error' => "Please use the helpers 'render' or 'respond_with' as your function return value." - } - respond_with(Oj.dump(body), status: 500, headers: {'Content-Type' => 'application/json'}) - rescue Exception => e - body = { - 'error' => e.message, - 'location' => e.backtrace&.first, - } - respond_with(Oj.dump(body), status: 500, headers: {'Content-Type' => 'application/json'}) +module FaaStRuby + class DoubleRenderError < StandardError; end +end + +module FaaStRuby + class Runner + def initialize + @rendered = false end - end - def self.respond_with(body, status: 200, headers: {}) - r = FaaStRubyFunction::Response.new(:body, :status, :headers) - r.new(body, status, headers) - end - def self.render(js: nil, body: nil, inline: nil, html: nil, json: nil, yaml: nil, text: nil, status: 200, headers: {}, content_type: nil) - headers["Content-Type"] = content_type if content_type - case - when json - headers["Content-Type"] ||= "application/json" - resp_body = json.is_a?(String) ? json : Oj.dump(json) - when html, inline - headers["Content-Type"] ||= "text/html" - resp_body = html - when text - headers["Content-Type"] ||= "text/plain" - resp_body = text - when yaml - headers["Content-Type"] ||= "application/yaml" - resp_body = yaml.to_yaml - when body - headers["Content-Type"] ||= "application/octet-stream" - resp_body = raw - when js - headers["Content-Type"] ||= "text/javascript" - resp_body = js + def call(workspace_name, function_name, event, args) + begin + load "./#{workspace_name}/#{function_name}/handler.rb" + response = handler(event, *args) + return response if response.is_a?(FaaStRuby::Response) + body = { + 'error' => "Please use the helpers 'render' or 'respond_with' as your function return value." + } + FaaStRuby::Response.new(body: Oj.dump(body), status: 500, headers: {'Content-Type' => 'application/json'}) + rescue Exception => e + body = { + 'error' => e.message, + 'location' => e.backtrace&.first, + } + FaaStRuby::Response.new(body: Oj.dump(body), status: 500, headers: {'Content-Type' => 'application/json'}) + end end - respond_with(resp_body, status: status, headers: headers) + + def rendered! + @rendered = true + end + def rendered? + @rendered + end + + def respond_with(body, status: 200, headers: {}) + raise FaaStRuby::DoubleRenderError.new("You called 'render' or 'respond_with' twice in your handler method") if rendered? + response = FaaStRuby::Response.new(body: body, status: status, headers: headers) + rendered! + response + end + + def render(js: nil, body: nil, inline: nil, html: nil, json: nil, yaml: nil, text: nil, status: 200, headers: {}, content_type: nil) + headers["Content-Type"] = content_type if content_type + case + when json + headers["Content-Type"] ||= "application/json" + resp_body = json.is_a?(String) ? json : Oj.dump(json) + when html, inline + headers["Content-Type"] ||= "text/html" + resp_body = html + when text + headers["Content-Type"] ||= "text/plain" + resp_body = text + when yaml + headers["Content-Type"] ||= "application/yaml" + resp_body = yaml.is_a?(String) ? yaml : YAML.load(yaml) + when body + headers["Content-Type"] ||= "application/octet-stream" + resp_body = raw + when js + headers["Content-Type"] ||= "text/javascript" + resp_body = js + end + respond_with(resp_body, status: status, headers: headers) + end end + class Event < Struct end - class Response < Struct + class Response + attr_accessor :body, :status, :headers + def initialize(body:, status: 200, headers: {}) + @body = body + @status = status + @headers = headers + end end end class FaaStRubyServer < Sinatra::Application set :port, 3000 @@ -69,15 +96,15 @@ when '-b' set :bind, ARGV.shift end set :server, %w[puma] set :run, false - set :show_exceptions, false + set :show_exceptions, true register Sinatra::MultiRoute route :get, :post, :put, :patch, :delete, '/:workspace_name/:function_name' do - e = FaaStRubyFunction::Event.new(:body, :query_params, :headers, :context) + e = FaaStRuby::Event.new(:body, :query_params, :headers, :context) headers = env.select { |key, value| key.include?('HTTP_') || ['CONTENT_TYPE', 'CONTENT_LENGTH', 'REMOTE_ADDR', 'REQUEST_METHOD', 'QUERY_STRING'].include?(key) } if headers.has_key?("HTTP_FAASTRUBY_RPC") body = nil rpc_args = parse_body(request.body.read, headers['CONTENT_TYPE'], request.request_method) || [] else @@ -85,10 +112,10 @@ rpc_args = [] end query_params = parse_query(request.query_string) context = set_context(params[:workspace_name], params[:function_name]) event = e.new(body, query_params, headers, context) - response = FaaStRubyFunction.call(params[:workspace_name], params[:function_name], event, rpc_args) + response = FaaStRuby::Runner.new.call(params[:workspace_name], params[:function_name], event, rpc_args) status response.status headers response.headers body response.body end