socky 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.textile +25 -0
- data/README.textile +27 -0
- data/Rakefile +19 -0
- data/VERSION +1 -1
- data/lib/em-websocket_hacks.rb +1 -3
- data/lib/socky.rb +17 -15
- data/lib/socky/connection.rb +12 -6
- data/lib/socky/connection/authentication.rb +7 -6
- data/lib/socky/connection/finders.rb +3 -3
- data/lib/socky/message.rb +26 -20
- data/lib/socky/misc.rb +2 -2
- data/lib/socky/net_request.rb +2 -2
- data/lib/socky/options.rb +16 -18
- data/lib/socky/options/config.rb +37 -18
- data/lib/socky/options/parser.rb +50 -40
- data/lib/socky/runner.rb +3 -4
- data/lib/socky/server.rb +1 -1
- data/spec/em-websocket_spec.rb +37 -0
- data/spec/files/default.yml +7 -0
- data/spec/files/invalid.yml +1 -0
- data/spec/socky/connection/authentication_spec.rb +162 -0
- data/spec/socky/connection/finders_spec.rb +96 -0
- data/spec/socky/connection_spec.rb +143 -0
- data/spec/socky/message_spec.rb +260 -0
- data/spec/socky/misc_spec.rb +74 -0
- data/spec/socky/net_request_spec.rb +43 -0
- data/spec/socky/options/config_spec.rb +67 -0
- data/spec/socky/options/parser_spec.rb +59 -0
- data/spec/socky/options_spec.rb +65 -0
- data/spec/socky/runner_spec.rb +73 -0
- data/spec/socky/server_spec.rb +35 -0
- data/spec/socky_spec.rb +82 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/stallion.rb +96 -0
- metadata +39 -7
- data/README +0 -10
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
require 'spec/stallion'
|
3
|
+
|
4
|
+
describe Socky::NetRequest do
|
5
|
+
|
6
|
+
context "class" do
|
7
|
+
context "#post" do
|
8
|
+
it "should send EventMachine::HttpRequest to url" do
|
9
|
+
EventMachine::HttpRequest.should_receive(:new).with("some url")
|
10
|
+
described_class.post("some url")
|
11
|
+
end
|
12
|
+
it "should send EventMachine::HttpRequest post request with specified params" do
|
13
|
+
request = mock(:request)
|
14
|
+
EventMachine::HttpRequest.stub!(:new).and_return(request)
|
15
|
+
request.should_receive(:post).with({:body => {:test => true}, :timeout => 3})
|
16
|
+
described_class.post("some url", :test => true)
|
17
|
+
end
|
18
|
+
it "should rescue from EM::HttpRequest and return false" do
|
19
|
+
EM.run do
|
20
|
+
described_class.post("inexistent").should be_false
|
21
|
+
EM.stop
|
22
|
+
end
|
23
|
+
end
|
24
|
+
it "should call block with false if request return status other than 200" do
|
25
|
+
EM.run do
|
26
|
+
described_class.post("http://127.0.0.1:8080/fail") do |response|
|
27
|
+
response.should be_false
|
28
|
+
EM.stop
|
29
|
+
end.should be_true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
it "should call block with true if request return status 200" do
|
33
|
+
EM.run do
|
34
|
+
described_class.post("http://127.0.0.1:8080/") do |response|
|
35
|
+
response.should be_true
|
36
|
+
EM.stop
|
37
|
+
end.should be_true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
FILES_DIR = File.join(File.dirname(__FILE__), '..', '..', 'files')
|
4
|
+
|
5
|
+
describe Socky::Options::Config do
|
6
|
+
|
7
|
+
context "class" do
|
8
|
+
before(:each) do
|
9
|
+
described_class.stub!(:puts)
|
10
|
+
end
|
11
|
+
|
12
|
+
context "#read" do
|
13
|
+
it "should raise error if file doesn't exists" do
|
14
|
+
described_class.should_receive(:puts).with("You must generate a config file (socky -g filename.yml)")
|
15
|
+
lambda { described_class.read("abstract") }.should raise_error SystemExit
|
16
|
+
end
|
17
|
+
it "should raise error if file is corrupted" do
|
18
|
+
described_class.should_receive(:puts).with("Provided config file is invalid.")
|
19
|
+
lambda { described_class.read(FILES_DIR + "/invalid.yml") }.should raise_error SystemExit
|
20
|
+
end
|
21
|
+
it "should return valid options if file is valid" do
|
22
|
+
lambda { described_class.read(FILES_DIR + "/default.yml") }.should_not raise_error SystemExit
|
23
|
+
described_class.read(FILES_DIR + "/default.yml").should eql(default_options)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "#generate" do
|
28
|
+
it "should raise error if file exists" do
|
29
|
+
described_class.should_receive(:puts).with("Config file already exists. You must remove it before generating a new one.")
|
30
|
+
lambda { described_class.generate(FILES_DIR + "/invalid.yml") }.should raise_error SystemExit
|
31
|
+
end
|
32
|
+
it "should raise error if path is not valid" do
|
33
|
+
described_class.should_receive(:puts).with("Config file is unavailable - please choose another.")
|
34
|
+
lambda { described_class.generate("/proc/inexistent") }.should raise_error SystemExit
|
35
|
+
end
|
36
|
+
it "should create file and exit if path is valid" do
|
37
|
+
path = FILES_DIR + "/inexistent.yml"
|
38
|
+
begin
|
39
|
+
described_class.should_receive(:puts).with("Config file generated at #{path}")
|
40
|
+
lambda { described_class.generate(path) }.should raise_error SystemExit
|
41
|
+
ensure
|
42
|
+
FileUtils.rm(path, :force => true)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
it "should generate file that after parsing will equal default config" do
|
46
|
+
path = FILES_DIR + "/inexistent.yml"
|
47
|
+
begin
|
48
|
+
described_class.should_receive(:puts).with("Config file generated at #{path}")
|
49
|
+
lambda { described_class.generate(path) }.should raise_error SystemExit
|
50
|
+
lambda { described_class.read(path) }.should_not raise_error SystemExit
|
51
|
+
described_class.read(path).should eql(default_options)
|
52
|
+
ensure
|
53
|
+
FileUtils.rm(path, :force => true)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def default_options
|
61
|
+
{ :port => 8080,
|
62
|
+
:debug => false,
|
63
|
+
:subscribe_url => "http://localhost:3000/socky/subscribe",
|
64
|
+
:unsubscribe_url => "http://localhost:3000/socky/unsubscribe",
|
65
|
+
:secret => "my_secret_key"
|
66
|
+
}
|
67
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe Socky::Options::Parser do
|
4
|
+
|
5
|
+
context "class" do
|
6
|
+
context "#parse" do
|
7
|
+
before(:each) do
|
8
|
+
described_class.stub!(:puts)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should return empty hash on empty array" do
|
12
|
+
described_class.parse([]).should eql({})
|
13
|
+
end
|
14
|
+
it "should inform about inexistent option and exit" do
|
15
|
+
described_class.should_receive(:puts).with("invalid option: -z")
|
16
|
+
lambda { described_class.parse(["-z"]) }.should raise_error SystemExit
|
17
|
+
end
|
18
|
+
it "on -g or --generate should set config_path and generate default config file in specified destination" do
|
19
|
+
Socky::Options::Config.stub!(:generate)
|
20
|
+
["-g","--generate"].each do |function|
|
21
|
+
Socky::Options::Config.should_receive(:generate).with("/tmp/socky.yml")
|
22
|
+
described_class.parse([function,"/tmp/socky.yml"]).should eql({:config_path => "/tmp/socky.yml"})
|
23
|
+
end
|
24
|
+
end
|
25
|
+
it "on -c or --config should set config_path to provided path" do
|
26
|
+
["-c","--config"].each do |function|
|
27
|
+
described_class.parse([function,"/tmp/socky.yml"]).should eql({:config_path => "/tmp/socky.yml"})
|
28
|
+
end
|
29
|
+
end
|
30
|
+
it "on -p or --port should set port" do
|
31
|
+
described_class.parse(["-p","222"]).should eql({:port => 222})
|
32
|
+
end
|
33
|
+
it "on -l or --log should set log_path to provided path" do
|
34
|
+
["-l","--log"].each do |function|
|
35
|
+
described_class.parse([function,"/tmp/socky.log"]).should eql({:log_path => "/tmp/socky.log"})
|
36
|
+
end
|
37
|
+
end
|
38
|
+
it "on --debug should set debug to true" do
|
39
|
+
described_class.parse(["--debug"]).should eql({:debug => true})
|
40
|
+
end
|
41
|
+
it "on --deep-debug should set debug and deep_debug to true" do
|
42
|
+
described_class.parse(["--deep-debug"]).should eql({:debug => true, :deep_debug => true})
|
43
|
+
end
|
44
|
+
it "on -? or --help should display usage" do
|
45
|
+
["-?","--help"].each do |function|
|
46
|
+
described_class.should_receive(:puts).with(/Usage: socky \[options\]/)
|
47
|
+
lambda { described_class.parse([function]) }.should raise_error SystemExit
|
48
|
+
end
|
49
|
+
end
|
50
|
+
it "on -v or --version should dosplay current version" do
|
51
|
+
["-v","--version"].each do |function|
|
52
|
+
described_class.should_receive(:puts).with("Socky #{Socky::VERSION}")
|
53
|
+
lambda { described_class.parse([function]) }.should raise_error SystemExit
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe Socky::Options do
|
4
|
+
|
5
|
+
context "class" do
|
6
|
+
before(:all) do
|
7
|
+
@default_options = Socky.options
|
8
|
+
end
|
9
|
+
after(:each) do
|
10
|
+
Socky.options = @default_options
|
11
|
+
end
|
12
|
+
|
13
|
+
context "#prepare" do
|
14
|
+
before(:each) do
|
15
|
+
Socky::Options::Parser.stub!(:parse).and_return({})
|
16
|
+
Socky::Options::Config.stub!(:read).and_return({})
|
17
|
+
end
|
18
|
+
it "should call parser with self option" do
|
19
|
+
Socky::Options::Parser.should_receive(:parse).with([:a,:b,:c])
|
20
|
+
Socky::Options.prepare([:a,:b,:c])
|
21
|
+
end
|
22
|
+
it "should call read_config with patch" do
|
23
|
+
Socky::Options::Config.should_receive(:read).with("/var/run/socky.yml")
|
24
|
+
Socky::Options.prepare([])
|
25
|
+
end
|
26
|
+
it "should set Socky options to default hash when parse_options and read_config don't do anything" do
|
27
|
+
Socky::Options.prepare([])
|
28
|
+
Socky.options.should eql({:port=>8080,
|
29
|
+
:log_path=>"/var/run/socky.log",
|
30
|
+
:debug=>false,
|
31
|
+
:deep_debug=>false,
|
32
|
+
:config_path=>"/var/run/socky.yml"})
|
33
|
+
end
|
34
|
+
it "should value parse_options over default values" do
|
35
|
+
Socky::Options::Parser.stub!(:parse).and_return(:log_path => "parsed")
|
36
|
+
Socky::Options.prepare([])
|
37
|
+
Socky.options.should eql({:port=>8080,
|
38
|
+
:log_path=>"parsed",
|
39
|
+
:debug=>false,
|
40
|
+
:deep_debug=>false,
|
41
|
+
:config_path=>"/var/run/socky.yml"})
|
42
|
+
end
|
43
|
+
it "should value read_config over default values" do
|
44
|
+
Socky::Options::Config.stub!(:read).and_return(:log_path => "from config")
|
45
|
+
Socky::Options.prepare([])
|
46
|
+
Socky.options.should eql({:port=>8080,
|
47
|
+
:log_path=>"from config",
|
48
|
+
:debug=>false,
|
49
|
+
:deep_debug=>false,
|
50
|
+
:config_path=>"/var/run/socky.yml"})
|
51
|
+
end
|
52
|
+
it "should value parse_options over read_config" do
|
53
|
+
Socky::Options::Config.stub!(:read).and_return(:log_path => "from config")
|
54
|
+
Socky::Options::Parser.stub!(:parse).and_return(:log_path => "parsed")
|
55
|
+
Socky::Options.prepare([])
|
56
|
+
Socky.options.should eql({:port=>8080,
|
57
|
+
:log_path=>"parsed",
|
58
|
+
:debug=>false,
|
59
|
+
:deep_debug=>false,
|
60
|
+
:config_path=>"/var/run/socky.yml"})
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe Socky::Runner do
|
4
|
+
|
5
|
+
context "#class" do
|
6
|
+
context "#run" do
|
7
|
+
before(:each) do
|
8
|
+
@server = mock(:server, :start => nil)
|
9
|
+
described_class.stub!(:new).and_return(@server)
|
10
|
+
end
|
11
|
+
it "should create new instance of self" do
|
12
|
+
described_class.should_receive(:new).with("some args")
|
13
|
+
described_class.run("some args")
|
14
|
+
end
|
15
|
+
it "should call #start on new instance of self" do
|
16
|
+
@server.should_receive(:start)
|
17
|
+
described_class.run
|
18
|
+
end
|
19
|
+
end
|
20
|
+
context "#new" do
|
21
|
+
it "should prepare options from args" do
|
22
|
+
Socky::Options.stub!(:prepare)
|
23
|
+
Socky::Options.should_receive(:prepare).with("some args")
|
24
|
+
described_class.new("some args")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "#instance" do
|
30
|
+
before(:each) do
|
31
|
+
Socky::Options.stub!(:prepare)
|
32
|
+
@runner = described_class.new
|
33
|
+
end
|
34
|
+
|
35
|
+
context "#start" do
|
36
|
+
it "should create valid websocket server" do
|
37
|
+
begin
|
38
|
+
EM.run do
|
39
|
+
MSG = "Hello World!"
|
40
|
+
EventMachine.add_timer(0.1) do
|
41
|
+
http = EventMachine::HttpRequest.new('ws://127.0.0.1:12345/').get :timeout => 0
|
42
|
+
http.errback {
|
43
|
+
EM.stop
|
44
|
+
fail
|
45
|
+
}
|
46
|
+
http.callback {
|
47
|
+
http.response_header.status.should == 101
|
48
|
+
EM.stop
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
Socky.stub!(:options).and_return({:port => 12345})
|
53
|
+
Socky.logger = mock(:logger, :info => nil, :debug => nil)
|
54
|
+
@runner.start
|
55
|
+
end
|
56
|
+
ensure
|
57
|
+
Socky.logger = nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it "#stop should call EM.stop" do
|
63
|
+
begin
|
64
|
+
Socky.logger = mock(:logger, :info => nil, :debug => nil)
|
65
|
+
EM.should_receive(:stop)
|
66
|
+
@runner.stop
|
67
|
+
ensure
|
68
|
+
Socky.logger = nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe Socky::Server do
|
4
|
+
|
5
|
+
context "class" do
|
6
|
+
it "#send_data should call send_message on each of provided connections" do
|
7
|
+
connections = []
|
8
|
+
3.times {|i| connections << mock("connection#{i}", :send_message => nil)}
|
9
|
+
connections.each{|connection| connection.should_receive(:send_message).with("abstract")}
|
10
|
+
described_class.send_data("abstract",connections)
|
11
|
+
end
|
12
|
+
it "#send_to_clients should find connections by clients and call #send_data on them" do
|
13
|
+
Socky::Connection.stub!(:find_by_clients).and_return(["first","second","third"])
|
14
|
+
described_class.stub!(:send_data)
|
15
|
+
Socky::Connection.should_receive(:find_by_clients).with("abstract")
|
16
|
+
described_class.should_receive(:send_data).with("message", ["first","second","third"])
|
17
|
+
described_class.send_to_clients("message","abstract")
|
18
|
+
end
|
19
|
+
it "#send_to_channels should find connections by channels and call #send_data on them" do
|
20
|
+
Socky::Connection.stub!(:find_by_channels).and_return(["first","second","third"])
|
21
|
+
described_class.stub!(:send_data)
|
22
|
+
Socky::Connection.should_receive(:find_by_channels).with("abstract")
|
23
|
+
described_class.should_receive(:send_data).with("message", ["first","second","third"])
|
24
|
+
described_class.send_to_channels("message","abstract")
|
25
|
+
end
|
26
|
+
it "#send_to_clients_on_channels should find connections by clients and channels and call #send_data on them" do
|
27
|
+
Socky::Connection.stub!(:find_by_clients_and_channels).and_return(["first","second","third"])
|
28
|
+
described_class.stub!(:send_data)
|
29
|
+
Socky::Connection.should_receive(:find_by_clients_and_channels).with("abstract1","abstract2")
|
30
|
+
described_class.should_receive(:send_data).with("message", ["first","second","third"])
|
31
|
+
described_class.send_to_clients_on_channels("message","abstract1","abstract2")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/spec/socky_spec.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe Socky do
|
4
|
+
|
5
|
+
context "class" do
|
6
|
+
|
7
|
+
it "should have non-blank version" do
|
8
|
+
Socky::VERSION.should_not be_nil
|
9
|
+
end
|
10
|
+
it "should have options in hash form" do
|
11
|
+
Socky.options.should_not be_nil
|
12
|
+
Socky.options.class.should eql(Hash)
|
13
|
+
end
|
14
|
+
it "should allow to set options" do
|
15
|
+
Socky.options.should eql(Hash.new)
|
16
|
+
begin
|
17
|
+
Socky.options = {:key => :value}
|
18
|
+
Socky.options.should eql({:key => :value})
|
19
|
+
ensure
|
20
|
+
Socky.options = Hash.new
|
21
|
+
end
|
22
|
+
end
|
23
|
+
it "should have logger" do
|
24
|
+
Socky.logger.should_not be_nil
|
25
|
+
Socky.logger.class.should eql(Logger)
|
26
|
+
end
|
27
|
+
it "should have logger with STDOUT at default" do
|
28
|
+
Socky.logger.instance_variable_get('@logdev').dev.class.should eql(IO)
|
29
|
+
end
|
30
|
+
it "should be able to set logger" do
|
31
|
+
begin
|
32
|
+
logger = Logger.new(STDOUT)
|
33
|
+
Socky.logger.should_not equal(logger)
|
34
|
+
Socky.logger = logger
|
35
|
+
Socky.logger.should equal(logger)
|
36
|
+
ensure
|
37
|
+
Socky.logger = nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
it "should be able to change verbosity of logger by setting debug option" do
|
41
|
+
begin
|
42
|
+
Socky.logger.level.should eql(Logger::INFO)
|
43
|
+
Socky.logger = nil
|
44
|
+
Socky.stub!(:options).and_return({:debug => true})
|
45
|
+
Socky.logger.level.should eql(Logger::DEBUG)
|
46
|
+
Socky.logger = nil
|
47
|
+
Socky.stub!(:options).and_return({:debug => false})
|
48
|
+
Socky.logger.level.should eql(Logger::INFO)
|
49
|
+
ensure
|
50
|
+
Socky.logger = nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
it "should have default log path" do
|
54
|
+
Socky.log_path.should_not be_nil
|
55
|
+
Socky.log_path.should eql("/var/run/socky.log")
|
56
|
+
end
|
57
|
+
it "should be able to change log path by settion log_path option" do
|
58
|
+
Socky.stub!(:options).and_return({:log_path => "abstract"})
|
59
|
+
Socky.log_path.should eql("abstract")
|
60
|
+
end
|
61
|
+
it "should be able to change logger write place" do
|
62
|
+
begin
|
63
|
+
Socky.options = {:log_path => File.join(File.dirname(__FILE__), 'files', 'socky.log')}
|
64
|
+
Socky.logger.should_not be_nil
|
65
|
+
Socky.logger.instance_variable_get('@logdev').dev.class.should eql(File)
|
66
|
+
ensure
|
67
|
+
Socky.logger = nil
|
68
|
+
Socky.options = {}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
it "should have default config path" do
|
72
|
+
Socky.config_path.should_not be_nil
|
73
|
+
Socky.config_path.should eql("/var/run/socky.yml")
|
74
|
+
end
|
75
|
+
it "should be able to change config path by settion config_path option" do
|
76
|
+
Socky.stub!(:options).and_return({:config_path => "abstract"})
|
77
|
+
Socky.config_path.should eql("abstract")
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/spec/stallion.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
# #--
|
2
|
+
# Includes portion originally Copyright (C)2008 Michael Fellinger
|
3
|
+
# license See file LICENSE for details
|
4
|
+
# #--
|
5
|
+
|
6
|
+
require 'rack'
|
7
|
+
|
8
|
+
module Stallion
|
9
|
+
class Mount
|
10
|
+
def initialize(name, *methods, &block)
|
11
|
+
@name, @methods, @block = name, methods, block
|
12
|
+
end
|
13
|
+
|
14
|
+
def ride
|
15
|
+
@block.call
|
16
|
+
end
|
17
|
+
|
18
|
+
def match?(request)
|
19
|
+
method = request['REQUEST_METHOD']
|
20
|
+
right_method = @methods.empty? or @methods.include?(method)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Stable
|
25
|
+
attr_reader :request, :response
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@boxes = {}
|
29
|
+
end
|
30
|
+
|
31
|
+
def in(path, *methods, &block)
|
32
|
+
mount = Mount.new(path, *methods, &block)
|
33
|
+
@boxes[[path, methods]] = mount
|
34
|
+
mount
|
35
|
+
end
|
36
|
+
|
37
|
+
def call(request, response)
|
38
|
+
@request, @response = request, response
|
39
|
+
@boxes.each do |(path, methods), mount|
|
40
|
+
if mount.match?(request)
|
41
|
+
mount.ride
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
STABLES = {}
|
48
|
+
|
49
|
+
def self.saddle(name = nil)
|
50
|
+
STABLES[name] = stable = Stable.new
|
51
|
+
yield stable
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.run(options = {})
|
55
|
+
options = {:Host => "127.0.0.1", :Port => 8080}.merge(options)
|
56
|
+
Rack::Handler::Mongrel.run(Rack::Lint.new(self), options)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.call(env)
|
60
|
+
request = Rack::Request.new(env)
|
61
|
+
response = Rack::Response.new
|
62
|
+
|
63
|
+
STABLES.each do |name, stable|
|
64
|
+
stable.call(request, response)
|
65
|
+
end
|
66
|
+
|
67
|
+
response.finish
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
Stallion.saddle :spec do |stable|
|
72
|
+
stable.in '/' do
|
73
|
+
|
74
|
+
if stable.request.path_info == '/fail'
|
75
|
+
stable.response.status = 404
|
76
|
+
|
77
|
+
elsif stable.request.path_info == '/timeout'
|
78
|
+
sleep(10)
|
79
|
+
stable.response.write 'timeout'
|
80
|
+
|
81
|
+
elsif
|
82
|
+
stable.response.write 'Hello, World!'
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
Thread.new do
|
89
|
+
begin
|
90
|
+
Stallion.run :Host => '127.0.0.1', :Port => 8080
|
91
|
+
rescue Exception => e
|
92
|
+
print e
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
sleep(1)
|