class Rack::Handler::AlchemyFlux
Alchemy Rack
handler
Public Class Methods
create_rack_env(message)
click to toggle source
create the environment hash to be sent to the app
# File lib/alchemy-flux/flux_rack_handler.rb, line 85 def self.create_rack_env(message) stream = StringIO.new(message['body']) stream.set_encoding(Encoding::ASCII_8BIT) # Full description of rack env http://www.rubydoc.info/github/rack/rack/master/file/SPEC rack_env = {} # CGI-like (adopted from PEP333) variables # The HTTP request method, such as “GET” or “POST” rack_env['REQUEST_METHOD'] = message['verb'].to_s.upcase # This is an empty string to correspond with the “root” of the server. rack_env['SCRIPT_NAME'] = '' # The remainder of the request URL's “path”, designating the virtual “location” of the request's target within the application. rack_env['PATH_INFO'] = message['path'] # The portion of the request URL that follows the ?, if any rack_env['QUERY_STRING'] = Rack::Utils.build_query(message['query']) # Used to complete the URL rack_env['SERVER_NAME'] = message['host'] rack_env['SERVER_PORT'] = message['port'].to_s # Headers are added to the rack env as described by RFC3875 https://www.ietf.org/rfc/rfc3875 if message['headers'].is_a? Hash message['headers'].each do |name, value| name = "HTTP_" + name.to_s.upcase.gsub(/[^A-Z0-9]/,'_') rack_env[name] = value.to_s end end # The environment must not contain the keys HTTP_CONTENT_TYPE or HTTP_CONTENT_LENGTH (use the versions without HTTP_) rack_env['CONTENT_TYPE'] = rack_env['HTTP_CONTENT_TYPE'] || 'application/octet-stream' rack_env['CONTENT_LENGTH'] = rack_env['HTTP_CONTENT_LENGTH'] || stream.length.to_s rack_env.delete('HTTP_CONTENT_TYPE') rack_env.delete('HTTP_CONTENT_LENGTH') # Rack-specific variables # The Array representing this version of Rack See Rack::VERSION rack_env['rack.version'] = Rack::VERSION # http or https, depending on the request URL. rack_env['rack.url_scheme'] = message['scheme'] # the input stream. rack_env['rack.input'] = stream # the error stream. rack_env['rack.errors'] = STDERR # true if the application object may be simultaneously invoked by another thread in the same process, false otherwise. rack_env['rack.multithread'] = true # true if an equivalent application object may be simultaneously invoked by another process, false otherwise. rack_env['rack.multiprocess'] = false # true if the server expects (but does not guarantee!) that the application will only be invoked this one time during the life of its containing process. rack_env['rack.run_once'] = false # present and true if the server supports connection hijacking. rack_env['rack.hijack?'] = false rack_env end
run(app, options={})
click to toggle source
Start the app server with the supplied Rack
application and options
app
[Rack Application] The Application to run. options
[Hash] The options to start the server with.
# File lib/alchemy-flux/flux_rack_handler.rb, line 18 def self.run(app, options={}) start(app) puts "Started #{@@service.inspect}" Signal.trap("INT") do puts "Stopping #{@@service.inspect}" stop end Signal.trap("TERM") do puts "Stopping #{@@service.inspect}" stop end EM.reactor_thread.join end
start(app)
click to toggle source
start the service for rack
# File lib/alchemy-flux/flux_rack_handler.rb, line 37 def self.start(app) service_name = ENV['ALCHEMY_SERVICE_NAME'] raise RuntimeError.new("Require ALCHEMY_SERVICE_NAME environment variable") if !service_name options = { ampq_uri: ENV['AMQ_URI'] || 'amqp://127.0.0.1', prefetch: (ENV['PREFETCH'] || 20).to_i, timeout: (ENV['TIMEOUT'] || 30000).to_i, threadpool_size: (ENV['THREADPOOL_SIZE'] || 500).to_i, resource_paths: (ENV['ALCHEMY_RESOURCE_PATHS'] || '').split(',') } if options[:prefetch] > options[:threadpool_size] puts "WARNING: 'prefect' is greater than the available threads which may cause performance blocking problems" end @@service = ::AlchemyFlux::Service.new(service_name, options) do |message| rack_env = create_rack_env(message) # add Alchemy Service so the app may call other services rack_env['alchemy.service'] = @@service rack_env['alchemy.session'] = message['session'] status, headers, body = app.call(rack_env) # process the body into a single response string body.close if body.respond_to?(:close) response = "" body.each { |part| response << part } { 'status_code' => status, 'headers' => headers, 'body' => response } end @@service.start end
stop()
click to toggle source
stops the app service
# File lib/alchemy-flux/flux_rack_handler.rb, line 79 def self.stop @@service.stop EM.stop end