thin 0.7.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of thin might be problematic. Click here for more details.
- data/CHANGELOG +15 -0
- data/README +10 -4
- data/benchmark/abc +0 -0
- data/benchmark/runner +0 -0
- data/bin/thin +0 -0
- data/example/thin_solaris_smf.erb +36 -0
- data/example/thin_solaris_smf.readme.txt +150 -0
- data/ext/thin_parser/common.rl +3 -2
- data/ext/thin_parser/parser.c +15 -38
- data/lib/rack/adapter/loader.rb +69 -0
- data/lib/rack/adapter/rails.rb +17 -8
- data/lib/thin.rb +1 -0
- data/lib/thin/backends/base.rb +17 -0
- data/lib/thin/backends/swiftiply_client.rb +3 -2
- data/lib/thin/backends/tcp_server.rb +1 -1
- data/lib/thin/connection.rb +38 -6
- data/lib/thin/controllers/controller.rb +43 -17
- data/lib/thin/logging.rb +1 -1
- data/lib/thin/request.rb +8 -1
- data/lib/thin/runner.rb +29 -7
- data/lib/thin/server.rb +58 -28
- data/lib/thin/version.rb +3 -3
- data/lib/thin_backend.bundle +0 -0
- data/lib/thin_parser.bundle +0 -0
- data/spec/connection_spec.rb +7 -0
- data/spec/controllers/controller_spec.rb +9 -1
- data/spec/rack/loader_spec.rb +29 -0
- data/spec/{rack_rails_spec.rb → rack/rails_adapter_spec.rb} +15 -3
- data/spec/rails_app/public/dispatch.cgi +0 -0
- data/spec/rails_app/public/dispatch.fcgi +0 -0
- data/spec/rails_app/public/dispatch.rb +0 -0
- data/spec/rails_app/script/about +0 -0
- data/spec/rails_app/script/console +0 -0
- data/spec/rails_app/script/destroy +0 -0
- data/spec/rails_app/script/generate +0 -0
- data/spec/rails_app/script/performance/benchmarker +0 -0
- data/spec/rails_app/script/performance/profiler +0 -0
- data/spec/rails_app/script/performance/request +0 -0
- data/spec/rails_app/script/plugin +0 -0
- data/spec/rails_app/script/process/inspector +0 -0
- data/spec/rails_app/script/process/reaper +0 -0
- data/spec/rails_app/script/process/spawner +0 -0
- data/spec/rails_app/script/runner +0 -0
- data/spec/rails_app/script/server +0 -0
- data/spec/request/parser_spec.rb +22 -0
- data/spec/request/processing_spec.rb +9 -10
- data/spec/runner_spec.rb +14 -1
- data/spec/server/builder_spec.rb +3 -2
- data/spec/server/robustness_spec.rb +34 -0
- data/spec/server/swiftiply_spec.rb +1 -1
- data/spec/server/threaded_spec.rb +27 -0
- data/spec/server_spec.rb +69 -0
- data/spec/spec_helper.rb +10 -5
- data/tasks/gem.rake +2 -2
- data/tasks/spec.rake +24 -16
- metadata +13 -5
- data/doc/benchmarks.txt +0 -86
data/CHANGELOG
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
== 0.8.0 Dodgy Dentist release
|
2
|
+
* Fix server crash when header too large.
|
3
|
+
* Add --require (-r) option to require a library, before executing your script.
|
4
|
+
* Rename --rackup short option to -R, warn and load as rackup when file ends with .ru.
|
5
|
+
* List supported adapters in command usage.
|
6
|
+
* Add file adapter to built-in adapter, serve static files in current directory.
|
7
|
+
* Allow disabling signal handling in Server with :signals => false
|
8
|
+
* Make Server.new arguments more flexible, can now specify any of host, port, app or hash options.
|
9
|
+
* Add --backend option to specified which backend to use, closes #55
|
10
|
+
* Serve static file only on GET and HEAD requests in Rails adapter, fixes #58
|
11
|
+
* Add threaded option to run server in threaded mode, calling the application in a
|
12
|
+
thread allowing for concurrency in the Rack adapter, closes #46
|
13
|
+
* Guess which adapter to use from directory (chdir option)
|
14
|
+
or use specified one in 'adapter' option, re #47.
|
15
|
+
|
1
16
|
== 0.7.1 Fancy Pants release
|
2
17
|
* Clean stale PID files when starting as daemon, fixes #53 [Chu Yeow]
|
3
18
|
* Require EventMachine 0.11.0 for UNIX domain sockets. Until it's released, install from:
|
data/README
CHANGED
@@ -9,11 +9,13 @@ Thin is a Ruby web server that glues together 3 of the best Ruby libraries in we
|
|
9
9
|
Which makes it, with all humility, the most secure, stable, fast and extensible Ruby web server
|
10
10
|
bundled in an easy to use gem for your own pleasure.
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
Site: http://code.macournoyer.com/thin/
|
13
|
+
Group: http://groups.google.com/group/thin-ruby/topics
|
14
|
+
Bugs: http://thin.lighthouseapp.com/projects/7212-thin
|
15
|
+
Code: http://github.com/macournoyer/thin
|
16
|
+
IRC: #thin on freenode
|
16
17
|
|
18
|
+
=== Installation
|
17
19
|
For the latest stable version:
|
18
20
|
|
19
21
|
sudo gem install thin
|
@@ -28,6 +30,10 @@ Or from source:
|
|
28
30
|
cd thin
|
29
31
|
rake install
|
30
32
|
|
33
|
+
To use Thin with UNIX domain sockets you need EventMachine 0.11.0 from my gem server:
|
34
|
+
|
35
|
+
gem install eventmachine --source http://code.macournoyer.com
|
36
|
+
|
31
37
|
=== Usage
|
32
38
|
A +thin+ script offers an easy way to start your Rails application:
|
33
39
|
|
data/benchmark/abc
CHANGED
File without changes
|
data/benchmark/runner
CHANGED
File without changes
|
data/bin/thin
CHANGED
File without changes
|
@@ -0,0 +1,36 @@
|
|
1
|
+
<?xml version='1.0'?>
|
2
|
+
<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
|
3
|
+
<service_bundle type='manifest' name='thin/<%= service_name %>-production'>
|
4
|
+
<service name='network/thin/<%= service_name %>-production' type='service' version='0'>
|
5
|
+
<!-- Dependancies for all Thin servers. -->
|
6
|
+
<dependency name='fs' grouping='require_all' restart_on='none' type='service'>
|
7
|
+
<service_fmri value='svc:/system/filesystem/local'/>
|
8
|
+
</dependency>
|
9
|
+
<dependency name='net' grouping='require_all' restart_on='none' type='service'>
|
10
|
+
<service_fmri value='svc:/network/loopback'/>
|
11
|
+
<!-- uncomment the following line if you are on an L+ Accelerator since /home is mounted through nfs -->
|
12
|
+
<!--<service_fmri value='svc:/network/nfs/client'/>-->
|
13
|
+
</dependency>
|
14
|
+
<% 0.upto(thin_max_instances - 1) do |instance| %>
|
15
|
+
<!-- instance names can't start with digits. Bummer. -->
|
16
|
+
<instance name='i_<%= instance.to_s %>' enabled='false'>
|
17
|
+
<!-- Cause the multi-user milestone to bring these services up -->
|
18
|
+
<dependent name='<%= service_name %>_<%= instance.to_s %>_multi-user' restart_on='none' grouping='optional_all'>
|
19
|
+
<service_fmri value='svc:/milestone/multi-user'/>
|
20
|
+
</dependent>
|
21
|
+
<exec_method name='start' type='method'
|
22
|
+
exec='/opt/csw/bin/thin -C config/thin.yml --only <%= instance.to_s %> start'
|
23
|
+
timeout_seconds='10'>
|
24
|
+
<method_context working_directory='<%= working_directory %>'>
|
25
|
+
<method_credential user='<%= user %>' group='<%= group %>' />
|
26
|
+
<method_environment>
|
27
|
+
<envvar name='PATH' value='/usr/bin:/bin:/opt/csw/bin' />
|
28
|
+
</method_environment>
|
29
|
+
</method_context>
|
30
|
+
</exec_method>
|
31
|
+
<exec_method name='stop' type='method' exec=':kill' timeout_seconds='10' />
|
32
|
+
</instance>
|
33
|
+
<% end %>
|
34
|
+
</service>
|
35
|
+
</service_bundle>
|
36
|
+
|
@@ -0,0 +1,150 @@
|
|
1
|
+
Using Thin with Solaris' SMF Monitoring Framework
|
2
|
+
- - - - - - - - - - - - - - - - - - - - - - - - -
|
3
|
+
|
4
|
+
Solaris uses the Service Management Framework (SMF) at the OS level to manage, monitor, and restart long running processes. This replaces init scripts, and tools like monit and god.
|
5
|
+
|
6
|
+
The sample XML file (thin_solaris_smf.erb) is an example SMF manifest which I use on a Joyent accelerator which runs on OpenSolaris.
|
7
|
+
|
8
|
+
This setup will:
|
9
|
+
|
10
|
+
- ensure the right dependencies are loaded
|
11
|
+
- start n instances of Thin, and monitor each individually. If any single one dies it will be restarted instantly (test it by killing a single thin instance and it will be back alive before you can type 'ps -ef').
|
12
|
+
|
13
|
+
This is better than using clustering since if you start the cluster with SMF it will only notice a problem and restart individual Thin's if ALL of them are dead, at which point it will restart the whole cluster. This approach makes sure that all of your Thins start together and are monitored and managed independant of each other. This problem likely exists if you are using god or monit to monitor only the start of the master cluster, and don't then monitor the individual processes started.
|
14
|
+
|
15
|
+
This example is in .erb format instead of plain XML since I dynamically generate this file as part of a Capistrano deployment. In my deploy.rb file I define the variables found in this erb. Of course you don't need to use this with Capistrano. Just replace the few ERB variables from the xml file, change its extension, and load that directly in Solaris if you prefer.
|
16
|
+
|
17
|
+
Here are some examples for usage to get you started with Capistrano, and Thin:
|
18
|
+
|
19
|
+
FILE : config/deploy.rb
|
20
|
+
--
|
21
|
+
|
22
|
+
require 'config/accelerator/accelerator_tasks'
|
23
|
+
|
24
|
+
set :application, "yourapp"
|
25
|
+
set :svcadm_bin, "/usr/sbin/svcadm"
|
26
|
+
set :svccfg_bin, "/usr/sbin/svccfg"
|
27
|
+
set :svcs_bin, "/usr/bin/svcs"
|
28
|
+
|
29
|
+
# gets the list of remote service SMF names that we need to start
|
30
|
+
# like (depending on thin_max_instances settings):
|
31
|
+
# svc:/network/thin/yourapp-production:i_0
|
32
|
+
# svc:/network/thin/yourapp-production:i_1
|
33
|
+
# svc:/network/thin/yourapp-production:i_2
|
34
|
+
set :service_list, "`svcs -H -o FMRI svc:network/thin/#{application}-production`"
|
35
|
+
|
36
|
+
# how many Thin instances should be setup to run?
|
37
|
+
# this affects the generated thin smf file, and the nginx vhost conf
|
38
|
+
# need to re-run setup for thin smf and nginx vhost conf when changed
|
39
|
+
set :thin_max_instances, 3
|
40
|
+
|
41
|
+
# OVERRIDE STANDARD TASKS
|
42
|
+
desc "Restart the entire application"
|
43
|
+
deploy.task :restart do
|
44
|
+
accelerator.thin.restart
|
45
|
+
accelerator.nginx.restart
|
46
|
+
end
|
47
|
+
|
48
|
+
desc "Start the entire application"
|
49
|
+
deploy.task :start do
|
50
|
+
accelerator.thin.restart
|
51
|
+
accelerator.nginx.restart
|
52
|
+
end
|
53
|
+
|
54
|
+
desc "Stop the entire application"
|
55
|
+
deploy.task :stop do
|
56
|
+
accelerator.thin.disable
|
57
|
+
accelerator.nginx.disable
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
FILE : config/accelerator/accelerator_tasks.rb
|
62
|
+
--
|
63
|
+
|
64
|
+
desc "Create and deploy Thin SMF config"
|
65
|
+
task :create_thin_smf, :roles => :app do
|
66
|
+
service_name = application
|
67
|
+
working_directory = current_path
|
68
|
+
template = File.read("config/accelerator/thin_solaris_smf.erb")
|
69
|
+
buffer = ERB.new(template).result(binding)
|
70
|
+
put buffer, "#{shared_path}/#{application}-thin-smf.xml"
|
71
|
+
sudo "#{svccfg_bin} import #{shared_path}/#{application}-thin-smf.xml"
|
72
|
+
end
|
73
|
+
|
74
|
+
desc "Delete Thin SMF config"
|
75
|
+
task :delete_thin_smf, :roles => :app do
|
76
|
+
accelerator.thin.disable
|
77
|
+
sudo "#{svccfg_bin} delete /network/thin/#{application}-production"
|
78
|
+
end
|
79
|
+
|
80
|
+
desc "Show all SMF services"
|
81
|
+
task :svcs do
|
82
|
+
run "#{svcs_bin} -a" do |ch, st, data|
|
83
|
+
puts data
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
desc "Shows all non-functional SMF services"
|
88
|
+
task :svcs_broken do
|
89
|
+
run "#{svcs_bin} -vx" do |ch, st, data|
|
90
|
+
puts data
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
namespace :thin do
|
96
|
+
|
97
|
+
desc "Disable all Thin servers"
|
98
|
+
task :disable, :roles => :app do
|
99
|
+
# temporarily disable, until next reboot (-t)
|
100
|
+
sudo "#{svcadm_bin} disable -t #{service_list}"
|
101
|
+
end
|
102
|
+
|
103
|
+
desc "Enable all Thin servers"
|
104
|
+
task :enable, :roles => :app do
|
105
|
+
# start the app with all recursive dependencies
|
106
|
+
sudo "#{svcadm_bin} enable -r #{service_list}"
|
107
|
+
end
|
108
|
+
|
109
|
+
desc "Restart all Thin servers"
|
110
|
+
task :restart, :roles => :app do
|
111
|
+
# svcadm restart doesn't seem to work right, so we'll brute force it
|
112
|
+
disable
|
113
|
+
enable
|
114
|
+
end
|
115
|
+
|
116
|
+
end # namespace thin
|
117
|
+
|
118
|
+
|
119
|
+
FILE : config/thin.yml
|
120
|
+
--
|
121
|
+
|
122
|
+
---
|
123
|
+
pid: tmp/pids/thin.pid
|
124
|
+
socket: /tmp/thin.sock
|
125
|
+
log: log/thin.log
|
126
|
+
max_conns: 1024
|
127
|
+
timeout: 30
|
128
|
+
chdir: /your/app/dir/rails/root
|
129
|
+
environment: production
|
130
|
+
max_persistent_conns: 512
|
131
|
+
daemonize: true
|
132
|
+
servers: 3
|
133
|
+
|
134
|
+
|
135
|
+
FILE : config/accelerator/thin_solaris_smf.erb
|
136
|
+
--
|
137
|
+
This is of course an example. It works for me, but YMMV
|
138
|
+
|
139
|
+
You may need to change this line to match your environment and config:
|
140
|
+
exec='/opt/csw/bin/thin -C config/thin.yml --only <%= instance.to_s %> start'
|
141
|
+
|
142
|
+
|
143
|
+
CONTRIBUTE:
|
144
|
+
|
145
|
+
If you see problems or enhancements for this approach please send me an email at glenn [at] rempe dot us. Sadly, I won't be able to provide support for this example as time and my limited Solaris admin skills won't allow.
|
146
|
+
|
147
|
+
Cheers,
|
148
|
+
|
149
|
+
Glenn Rempe
|
150
|
+
2008/03/20
|
data/ext/thin_parser/common.rl
CHANGED
@@ -11,11 +11,12 @@
|
|
11
11
|
safe = ("$" | "-" | "_" | ".");
|
12
12
|
extra = ("!" | "*" | "'" | "(" | ")" | ",");
|
13
13
|
reserved = (";" | "/" | "?" | ":" | "@" | "&" | "=" | "+");
|
14
|
-
|
14
|
+
sorta_safe = ("\"" | "<" | ">");
|
15
|
+
unsafe = (CTL | " " | "#" | "%" | sorta_safe);
|
15
16
|
national = any -- (alpha | digit | reserved | extra | safe | unsafe);
|
16
17
|
unreserved = (alpha | digit | safe | extra | national);
|
17
18
|
escape = ("%" xdigit xdigit);
|
18
|
-
uchar = (unreserved | escape);
|
19
|
+
uchar = (unreserved | escape | sorta_safe);
|
19
20
|
pchar = (uchar | ":" | "@" | "&" | "=" | "+");
|
20
21
|
tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
|
21
22
|
|
data/ext/thin_parser/parser.c
CHANGED
@@ -484,15 +484,11 @@ case 20:
|
|
484
484
|
#line 485 "parser.c"
|
485
485
|
switch( (*p) ) {
|
486
486
|
case 32: goto tr30;
|
487
|
+
case 35: goto st0;
|
487
488
|
case 37: goto tr31;
|
488
|
-
case 60: goto st0;
|
489
|
-
case 62: goto st0;
|
490
489
|
case 127: goto st0;
|
491
490
|
}
|
492
|
-
if ( (*p)
|
493
|
-
if ( 34 <= (*p) && (*p) <= 35 )
|
494
|
-
goto st0;
|
495
|
-
} else if ( (*p) >= 0 )
|
491
|
+
if ( 0 <= (*p) && (*p) <= 31 )
|
496
492
|
goto st0;
|
497
493
|
goto tr29;
|
498
494
|
tr29:
|
@@ -503,18 +499,14 @@ st21:
|
|
503
499
|
if ( ++p == pe )
|
504
500
|
goto _out21;
|
505
501
|
case 21:
|
506
|
-
#line
|
502
|
+
#line 503 "parser.c"
|
507
503
|
switch( (*p) ) {
|
508
504
|
case 32: goto tr30;
|
505
|
+
case 35: goto st0;
|
509
506
|
case 37: goto st22;
|
510
|
-
case 60: goto st0;
|
511
|
-
case 62: goto st0;
|
512
507
|
case 127: goto st0;
|
513
508
|
}
|
514
|
-
if ( (*p)
|
515
|
-
if ( 34 <= (*p) && (*p) <= 35 )
|
516
|
-
goto st0;
|
517
|
-
} else if ( (*p) >= 0 )
|
509
|
+
if ( 0 <= (*p) && (*p) <= 31 )
|
518
510
|
goto st0;
|
519
511
|
goto st21;
|
520
512
|
tr31:
|
@@ -525,7 +517,7 @@ st22:
|
|
525
517
|
if ( ++p == pe )
|
526
518
|
goto _out22;
|
527
519
|
case 22:
|
528
|
-
#line
|
520
|
+
#line 521 "parser.c"
|
529
521
|
if ( (*p) < 65 ) {
|
530
522
|
if ( 48 <= (*p) && (*p) <= 57 )
|
531
523
|
goto st23;
|
@@ -556,7 +548,7 @@ st24:
|
|
556
548
|
if ( ++p == pe )
|
557
549
|
goto _out24;
|
558
550
|
case 24:
|
559
|
-
#line
|
551
|
+
#line 552 "parser.c"
|
560
552
|
switch( (*p) ) {
|
561
553
|
case 43: goto st24;
|
562
554
|
case 58: goto st25;
|
@@ -581,14 +573,11 @@ st25:
|
|
581
573
|
if ( ++p == pe )
|
582
574
|
goto _out25;
|
583
575
|
case 25:
|
584
|
-
#line
|
576
|
+
#line 577 "parser.c"
|
585
577
|
switch( (*p) ) {
|
586
578
|
case 32: goto tr8;
|
587
|
-
case 34: goto st0;
|
588
579
|
case 35: goto tr9;
|
589
580
|
case 37: goto st26;
|
590
|
-
case 60: goto st0;
|
591
|
-
case 62: goto st0;
|
592
581
|
case 127: goto st0;
|
593
582
|
}
|
594
583
|
if ( 0 <= (*p) && (*p) <= 31 )
|
@@ -628,15 +617,12 @@ st28:
|
|
628
617
|
if ( ++p == pe )
|
629
618
|
goto _out28;
|
630
619
|
case 28:
|
631
|
-
#line
|
620
|
+
#line 621 "parser.c"
|
632
621
|
switch( (*p) ) {
|
633
622
|
case 32: goto tr40;
|
634
|
-
case 34: goto st0;
|
635
623
|
case 35: goto tr41;
|
636
624
|
case 37: goto st29;
|
637
625
|
case 59: goto tr43;
|
638
|
-
case 60: goto st0;
|
639
|
-
case 62: goto st0;
|
640
626
|
case 63: goto tr44;
|
641
627
|
case 127: goto st0;
|
642
628
|
}
|
@@ -681,14 +667,11 @@ st31:
|
|
681
667
|
if ( ++p == pe )
|
682
668
|
goto _out31;
|
683
669
|
case 31:
|
684
|
-
#line
|
670
|
+
#line 671 "parser.c"
|
685
671
|
switch( (*p) ) {
|
686
672
|
case 32: goto tr8;
|
687
|
-
case 34: goto st0;
|
688
673
|
case 35: goto tr9;
|
689
674
|
case 37: goto st32;
|
690
|
-
case 60: goto st0;
|
691
|
-
case 62: goto st0;
|
692
675
|
case 63: goto st34;
|
693
676
|
case 127: goto st0;
|
694
677
|
}
|
@@ -733,14 +716,11 @@ st34:
|
|
733
716
|
if ( ++p == pe )
|
734
717
|
goto _out34;
|
735
718
|
case 34:
|
736
|
-
#line
|
719
|
+
#line 720 "parser.c"
|
737
720
|
switch( (*p) ) {
|
738
721
|
case 32: goto tr51;
|
739
|
-
case 34: goto st0;
|
740
722
|
case 35: goto tr52;
|
741
723
|
case 37: goto tr53;
|
742
|
-
case 60: goto st0;
|
743
|
-
case 62: goto st0;
|
744
724
|
case 127: goto st0;
|
745
725
|
}
|
746
726
|
if ( 0 <= (*p) && (*p) <= 31 )
|
@@ -754,14 +734,11 @@ st35:
|
|
754
734
|
if ( ++p == pe )
|
755
735
|
goto _out35;
|
756
736
|
case 35:
|
757
|
-
#line
|
737
|
+
#line 738 "parser.c"
|
758
738
|
switch( (*p) ) {
|
759
739
|
case 32: goto tr55;
|
760
|
-
case 34: goto st0;
|
761
740
|
case 35: goto tr56;
|
762
741
|
case 37: goto st36;
|
763
|
-
case 60: goto st0;
|
764
|
-
case 62: goto st0;
|
765
742
|
case 127: goto st0;
|
766
743
|
}
|
767
744
|
if ( 0 <= (*p) && (*p) <= 31 )
|
@@ -775,7 +752,7 @@ st36:
|
|
775
752
|
if ( ++p == pe )
|
776
753
|
goto _out36;
|
777
754
|
case 36:
|
778
|
-
#line
|
755
|
+
#line 756 "parser.c"
|
779
756
|
if ( (*p) < 65 ) {
|
780
757
|
if ( 48 <= (*p) && (*p) <= 57 )
|
781
758
|
goto st37;
|
@@ -1205,7 +1182,7 @@ case 56:
|
|
1205
1182
|
if(parser->body_start) {
|
1206
1183
|
/* final \r\n combo encountered so stop right here */
|
1207
1184
|
|
1208
|
-
#line
|
1185
|
+
#line 1186 "parser.c"
|
1209
1186
|
#line 130 "parser.rl"
|
1210
1187
|
parser->nread++;
|
1211
1188
|
}
|
@@ -1218,7 +1195,7 @@ int http_parser_finish(http_parser *parser)
|
|
1218
1195
|
int cs = parser->cs;
|
1219
1196
|
|
1220
1197
|
|
1221
|
-
#line
|
1198
|
+
#line 1199 "parser.c"
|
1222
1199
|
#line 141 "parser.rl"
|
1223
1200
|
|
1224
1201
|
parser->cs = cs;
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Rack
|
2
|
+
class AdapterNotFound < RuntimeError; end
|
3
|
+
|
4
|
+
# Hash used to guess which adapter to use in <tt>Adapter.for</tt>.
|
5
|
+
# Framework name => file unique to this framework.
|
6
|
+
# +nil+ for value to never guess.
|
7
|
+
ADAPTERS = {
|
8
|
+
:rails => "config/environment.rb",
|
9
|
+
:ramaze => "start.rb",
|
10
|
+
:merb => "config/init.rb",
|
11
|
+
:halcyon => 'runner.ru',
|
12
|
+
:file => nil
|
13
|
+
}
|
14
|
+
|
15
|
+
module Adapter
|
16
|
+
# Guess which adapter to use based on the directory structure
|
17
|
+
# or file content.
|
18
|
+
# Returns a symbol representing the name of the adapter to use
|
19
|
+
# to load the application under <tt>dir/</tt>.
|
20
|
+
def self.guess(dir)
|
21
|
+
ADAPTERS.each_pair do |adapter, file|
|
22
|
+
return adapter if file && ::File.exist?(::File.join(dir, file))
|
23
|
+
end
|
24
|
+
raise AdapterNotFound, "No adapter found for #{dir}"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Loads an adapter identified by +name+ using +options+ hash.
|
28
|
+
def self.for(name, options={})
|
29
|
+
case name.to_sym
|
30
|
+
when :rails
|
31
|
+
return Rails.new(options.merge(:root => options[:chdir]))
|
32
|
+
|
33
|
+
when :ramaze
|
34
|
+
require "#{options[:chdir]}/start"
|
35
|
+
|
36
|
+
Ramaze.trait[:essentials].delete Ramaze::Adapter
|
37
|
+
Ramaze.start :force => true
|
38
|
+
|
39
|
+
return Ramaze::Adapter::Base
|
40
|
+
|
41
|
+
when :merb
|
42
|
+
require 'merb-core'
|
43
|
+
|
44
|
+
Merb::Config.setup(:merb_root => options[:chdir],
|
45
|
+
:environment => options[:environment])
|
46
|
+
Merb.environment = Merb::Config[:environment]
|
47
|
+
Merb.root = Merb::Config[:merb_root]
|
48
|
+
Merb::BootLoader.run
|
49
|
+
|
50
|
+
return Merb::Rack::Application.new
|
51
|
+
|
52
|
+
when :halcyon
|
53
|
+
require 'halcyon'
|
54
|
+
|
55
|
+
$:.unshift(Halcyon.root/'lib')
|
56
|
+
Halcyon::Runner.load_config Halcyon.root/'config'/'config.yml'
|
57
|
+
|
58
|
+
return Halcyon::Runner.new
|
59
|
+
|
60
|
+
when :file
|
61
|
+
return Rack::File.new(options[:chdir])
|
62
|
+
|
63
|
+
else
|
64
|
+
raise AdapterNotFound, "Adapter not found: #{name}"
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|