2012-01-19 20:59:05 +00:00
|
|
|
require 'rack'
|
|
|
|
require 'net/http'
|
|
|
|
require 'socket'
|
2012-03-14 17:07:28 +00:00
|
|
|
require 'rack/builder'
|
2012-03-14 21:41:02 +00:00
|
|
|
require 'thin'
|
2012-01-19 20:59:05 +00:00
|
|
|
|
|
|
|
module Flowerbox
|
|
|
|
module Delivery
|
|
|
|
class Server
|
|
|
|
attr_reader :options
|
|
|
|
|
|
|
|
def initialize(options = {})
|
2012-03-02 18:29:15 +00:00
|
|
|
@options = { :logging => false }.merge(options || {})
|
2012-01-19 20:59:05 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def start
|
|
|
|
@server_thread = Thread.new do
|
2012-03-02 18:29:15 +00:00
|
|
|
server_options = { :Port => port, :Host => interface }
|
2012-03-14 17:07:28 +00:00
|
|
|
|
|
|
|
app = options[:app]
|
|
|
|
|
2012-03-14 21:41:02 +00:00
|
|
|
Thin::Logging.silent = !options[:logging]
|
|
|
|
|
2012-03-14 17:07:28 +00:00
|
|
|
if options[:logging]
|
|
|
|
real_app = app
|
|
|
|
app = ::Rack::Builder.new do
|
|
|
|
use ::Rack::CommonLogger, STDOUT
|
|
|
|
run real_app
|
|
|
|
end
|
2012-03-02 18:29:15 +00:00
|
|
|
end
|
|
|
|
|
2012-03-14 17:07:28 +00:00
|
|
|
::Rack::Handler::Thin.run(app, server_options) do |server|
|
2012-01-19 20:59:05 +00:00
|
|
|
Thread.current[:server] = server
|
2012-03-15 18:22:20 +00:00
|
|
|
|
|
|
|
trap('QUIT') { server.stop }
|
2012-02-29 19:24:07 +00:00
|
|
|
end
|
2012-01-19 20:59:05 +00:00
|
|
|
end
|
|
|
|
|
2012-02-29 19:24:07 +00:00
|
|
|
while !@server_thread[:server] && @server_thread.alive?
|
2012-01-19 20:59:05 +00:00
|
|
|
sleep 0.1
|
|
|
|
end
|
2012-02-29 19:24:07 +00:00
|
|
|
|
2012-03-15 18:22:20 +00:00
|
|
|
raise StandardError.new("Server died") if !@server_thread[:server].running?
|
2012-01-19 20:59:05 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def stop
|
|
|
|
if @server_thread
|
2012-03-14 17:07:28 +00:00
|
|
|
@server_thread[:server].stop
|
2012-01-19 20:59:05 +00:00
|
|
|
|
|
|
|
wait_for_server_to_stop
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def interface
|
|
|
|
options[:interface] || '0.0.0.0'
|
|
|
|
end
|
|
|
|
|
|
|
|
def port
|
|
|
|
return @port if @port ||= options[:port]
|
|
|
|
|
2012-01-23 13:56:43 +00:00
|
|
|
attempts = 20
|
2012-01-19 20:59:05 +00:00
|
|
|
|
|
|
|
begin
|
|
|
|
attempts -= 1
|
|
|
|
|
|
|
|
current_port = random_port
|
|
|
|
|
|
|
|
begin
|
|
|
|
socket = TCPSocket.new(interface, current_port)
|
|
|
|
socket.close
|
|
|
|
rescue Errno::ECONNREFUSED => e
|
|
|
|
@port = current_port
|
|
|
|
end
|
|
|
|
end while !@port and attempts > 0
|
|
|
|
|
|
|
|
raise StandardError.new("can't start server") if attempts == 0
|
|
|
|
|
|
|
|
@port
|
|
|
|
end
|
|
|
|
|
2012-03-14 17:07:28 +00:00
|
|
|
def address
|
|
|
|
"http://#{interface}:#{port}/"
|
|
|
|
end
|
|
|
|
|
|
|
|
def alive?
|
|
|
|
@server_thread.alive?
|
|
|
|
end
|
|
|
|
|
2012-01-19 20:59:05 +00:00
|
|
|
private
|
|
|
|
def wait_for_server_to_start
|
|
|
|
while true do
|
|
|
|
begin
|
|
|
|
connect_interface = '127.0.0.1' if interface == '0.0.0.0'
|
|
|
|
|
|
|
|
TCPSocket.new(connect_interface, port)
|
|
|
|
break
|
|
|
|
rescue Errno::ECONNREFUSED => e
|
|
|
|
end
|
|
|
|
|
|
|
|
sleep 0.1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def wait_for_server_to_stop
|
2012-03-14 17:07:28 +00:00
|
|
|
while alive? do
|
2012-01-19 20:59:05 +00:00
|
|
|
begin
|
|
|
|
connect_interface = '127.0.0.1' if interface == '0.0.0.0'
|
|
|
|
|
|
|
|
socket = TCPSocket.new(connect_interface, port)
|
|
|
|
socket.close
|
|
|
|
rescue Errno::ECONNREFUSED => e
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
sleep 0.1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def random_port
|
|
|
|
25000 + Kernel.rand(1000)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|