exe/faastruby-server in faastruby-0.4.8 vs exe/faastruby-server in faastruby-0.4.9
- old
+ new
@@ -1,200 +1,74 @@
#!/usr/bin/env ruby
-
-require 'sinatra'
-require 'sinatra/multi_route'
require 'yaml'
require 'oj'
require 'faastruby-rpc'
require 'base64'
+require 'faastruby/server'
+require 'sinatra'
+require 'sinatra/multi_route'
+require 'colorize'
+FaaStRuby::EventHub.listen_for_events!
-module FaaStRuby
- class DoubleRenderError < StandardError; end
+set :port, 3000
+set :bind, '0.0.0.0'
+case ARGV.shift
+when '-p'
+ set :port, ARGV.shift
+when '-b', '-o'
+ set :bind, ARGV.shift
end
+set :server, %w[puma]
+set :show_exceptions, true
-module FaaStRuby
- class Runner
- def initialize
- @rendered = false
- end
-
- 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
-
- def rendered!
- @rendered = true
- end
- def rendered?
- @rendered
- end
-
- def respond_with(body, status: 200, headers: {}, binary: false)
- 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, binary: binary)
- rendered!
- response
- end
-
- def render(
- js: nil,
- body: nil,
- inline: nil,
- html: nil,
- json: nil,
- yaml: nil,
- text: nil,
- data: nil,
- png: nil,
- svg: nil,
- jpeg: nil,
- gif: nil,
- icon: nil,
- status: 200, headers: {}, content_type: nil, binary: false
- )
- headers["Content-Type"] = content_type if content_type
- bin = false
- 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"
- bin = binary
- resp_body = bin ? Base64.urlsafe_encode64(body) : body
- when data
- headers["Content-Type"] ||= "application/octet-stream"
- resp_body = Base64.urlsafe_encode64(data)
- bin = true
- when js
- headers["Content-Type"] ||= "text/javascript"
- resp_body = js
- when png
- headers["Content-Type"] ||= "image/png"
- resp_body = Base64.urlsafe_encode64(png)
- bin = true
- when svg
- headers["Content-Type"] ||= "image/svg+xml"
- resp_body = svg
- when jpeg
- headers["Content-Type"] ||= "image/jpeg"
- resp_body = Base64.urlsafe_encode64(jpeg)
- bin = true
- when gif
- headers["Content-Type"] ||= "image/gif"
- resp_body = Base64.urlsafe_encode64(gif)
- bin = true
- when icon
- headers["Content-Type"] ||= "image/x-icon"
- resp_body = Base64.urlsafe_encode64(icon)
- bin = true
- end
- respond_with(resp_body, status: status, headers: headers, binary: bin)
- end
+register Sinatra::MultiRoute
+route :get, :post, :put, :patch, :delete, '/:workspace_name/:function_name' do
+ path = "#{params[:workspace_name]}/#{params[:function_name]}"
+ 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
+ body = parse_body(request.body.read, headers['CONTENT_TYPE'], request.request_method)
+ rpc_args = []
end
-
- class Event < Struct
+ query_params = parse_query(request.query_string)
+ context = set_context(params[:workspace_name], params[:function_name])
+ event = FaaStRuby::Event.new(body, query_params, headers, context)
+ response = FaaStRuby::Runner.new.call(params[:workspace_name], params[:function_name], event, rpc_args)
+ status response.status
+ headers response.headers
+ if response.binary?
+ response_body = Base64.urlsafe_decode64(response.body)
+ else
+ response_body = response.body
end
+ puts "[#{path}] #=> status=#{response.status} body=#{response_body.inspect} headers=#{Oj.dump response.headers}".light_blue
+ body response_body
+end
- class Response
- attr_accessor :body, :status, :headers, :binary
- def initialize(body:, status: 200, headers: {}, binary: false)
- @body = body
- @status = status
- @headers = headers
- @binary = binary
- end
+def parse_body(body, content_type, method)
+ return nil if method == 'GET'
+ return {} if body.nil? && method != 'GET'
+ return Oj.load(body) if content_type == 'application/json'
+ return body
+end
- def binary?
- @binary
- end
- end
+def set_context(workspace_name, function_name)
+ return nil unless File.file?('context.yml')
+ yaml = YAML.load(File.read('context.yml'))
+ return nil unless yaml.has_key?(workspace_name)
+ yaml[workspace_name][function_name]
end
-class FaaStRubyServer < Sinatra::Application
- set :port, 3000
- set :bind, '0.0.0.0'
- case ARGV.shift
- when '-p'
- set :port, ARGV.shift
- when '-b'
- set :bind, ARGV.shift
+def parse_query(query_string)
+ hash = {}
+ query_string.split('&').each do |param|
+ key, value = param.split('=')
+ hash[key] = value
end
- set :server, %w[puma]
- set :run, false
- set :show_exceptions, true
-
- register Sinatra::MultiRoute
- route :get, :post, :put, :patch, :delete, '/:workspace_name/:function_name' do
- 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
- body = parse_body(request.body.read, headers['CONTENT_TYPE'], request.request_method)
- 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 = FaaStRuby::Runner.new.call(params[:workspace_name], params[:function_name], event, rpc_args)
- status response.status
- headers response.headers
- if response.binary?
- body Base64.urlsafe_decode64(response.body)
- else
- body response.body
- end
- end
-
- def parse_body(body, content_type, method)
- return nil if method == 'GET'
- return {} if body.nil? && method != 'GET'
- return Oj.load(body) if content_type == 'application/json'
- return body
- end
-
- def set_context(workspace_name, function_name)
- return nil unless File.file?('context.yml')
- yaml = YAML.load(File.read('context.yml'))
- return nil unless yaml.has_key?(workspace_name)
- yaml[workspace_name][function_name]
- end
-
- def parse_query(query_string)
- hash = {}
- query_string.split('&').each do |param|
- key, value = param.split('=')
- hash[key] = value
- end
- hash
- end
- def self.run?
- true
- end
+ hash
end
+def self.run?
+ true
+end
-FaaStRubyServer.run! rescue nil # this will suppress some of the errors messages