jubilee 1.0.2 → 1.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/CHANGELOG +17 -0
  4. data/Gemfile +19 -1
  5. data/Gemfile.lock +189 -31
  6. data/LICENSE.txt +20 -0
  7. data/README.md +44 -5
  8. data/ROADMAP +5 -0
  9. data/Rakefile +6 -5
  10. data/examples/chatapp/Gemfile +2 -1
  11. data/examples/chatapp/Gemfile.lock +8 -6
  12. data/examples/chatapp/README.md +5 -2
  13. data/examples/chatapp/app.rb +24 -0
  14. data/examples/chatapp/public/assets/javascripts/application.js +59 -6
  15. data/examples/chatapp/public/assets/stylesheets/application.css +25 -0
  16. data/examples/jubilee.conf.rb +0 -3
  17. data/jars/{hazelcast-2.6.jar → hazelcast-2.6.3.jar} +0 -0
  18. data/jars/{netty-all-4.0.4.Final.jar → netty-all-4.0.13.Final.jar} +0 -0
  19. data/jars/vertx-core-2.1M3-SNAPSHOT.jar +0 -0
  20. data/jars/vertx-hazelcast-2.1M3-SNAPSHOT.jar +0 -0
  21. data/java/src/jubilee/JubileeService.java +7 -7
  22. data/java/src/org/jruby/jubilee/Const.java +10 -35
  23. data/java/src/org/jruby/jubilee/RackApplication.java +77 -46
  24. data/java/src/org/jruby/jubilee/RackResponse.java +1 -3
  25. data/java/src/org/jruby/jubilee/RubyHttpServerResponse.java +88 -0
  26. data/java/src/org/jruby/jubilee/{Server.java → RubyServer.java} +17 -14
  27. data/java/src/org/jruby/jubilee/impl/RackEnvironment.java +157 -0
  28. data/java/src/org/jruby/jubilee/impl/RackEnvironmentHash.java +449 -0
  29. data/java/src/org/jruby/jubilee/impl/RubyIORackInput.java +5 -5
  30. data/java/src/org/jruby/jubilee/impl/{NullIO.java → RubyNullIO.java} +5 -9
  31. data/java/src/org/jruby/jubilee/utils/RubyHelper.java +37 -0
  32. data/jubilee.gemspec +101 -14
  33. data/lib/jubilee.rb +4 -3
  34. data/lib/jubilee/cli.rb +2 -1
  35. data/lib/jubilee/configuration.rb +4 -9
  36. data/lib/jubilee/const.rb +2 -2
  37. data/lib/jubilee/jubilee.jar +0 -0
  38. data/lib/jubilee/response.rb +9 -8
  39. data/lib/jubilee/server.rb +1 -1
  40. data/lib/jubilee/version.rb +8 -1
  41. data/lib/rack/chunked.rb +38 -0
  42. data/spec/apps/rack/basic/config.ru +50 -0
  43. data/spec/apps/rails4/basic/.gitignore +16 -0
  44. data/spec/apps/rails4/basic/Gemfile +41 -0
  45. data/spec/apps/rails4/basic/Gemfile.lock +127 -0
  46. data/spec/apps/rails4/basic/README.rdoc +28 -0
  47. data/spec/apps/rails4/basic/Rakefile +6 -0
  48. data/spec/apps/rails4/basic/app/assets/images/.keep +0 -0
  49. data/spec/apps/rails4/basic/app/assets/images/rails.png +0 -0
  50. data/spec/apps/rails4/basic/app/assets/javascripts/application.js +16 -0
  51. data/spec/apps/rails4/basic/app/assets/stylesheets/application.css +13 -0
  52. data/spec/apps/rails4/basic/app/controllers/application_controller.rb +5 -0
  53. data/spec/apps/rails4/basic/app/controllers/concerns/.keep +0 -0
  54. data/spec/apps/rails4/basic/app/controllers/reloader_controller.rb +11 -0
  55. data/spec/apps/rails4/basic/app/controllers/reloader_controller.rb.erb +11 -0
  56. data/spec/apps/rails4/basic/app/controllers/root_controller.rb +14 -0
  57. data/spec/apps/rails4/basic/app/helpers/application_helper.rb +2 -0
  58. data/spec/apps/rails4/basic/app/mailers/.keep +0 -0
  59. data/spec/apps/rails4/basic/app/models/.keep +0 -0
  60. data/spec/apps/rails4/basic/app/models/concerns/.keep +0 -0
  61. data/spec/apps/rails4/basic/app/views/layouts/application.html.erb +14 -0
  62. data/spec/apps/rails4/basic/app/views/reloader/index.html.erb +1 -0
  63. data/spec/apps/rails4/basic/app/views/root/index.html.erb +8 -0
  64. data/spec/apps/rails4/basic/app/views/root/streaming.html.erb +6 -0
  65. data/spec/apps/rails4/basic/bin/bundle +3 -0
  66. data/spec/apps/rails4/basic/bin/rails +4 -0
  67. data/spec/apps/rails4/basic/bin/rake +4 -0
  68. data/spec/apps/rails4/basic/config.ru +4 -0
  69. data/spec/apps/rails4/basic/config/application.rb +23 -0
  70. data/spec/apps/rails4/basic/config/boot.rb +4 -0
  71. data/spec/apps/rails4/basic/config/database.yml +20 -0
  72. data/spec/apps/rails4/basic/config/environment.rb +5 -0
  73. data/spec/apps/rails4/basic/config/environments/development.rb +29 -0
  74. data/spec/apps/rails4/basic/config/environments/production.rb +80 -0
  75. data/spec/apps/rails4/basic/config/environments/test.rb +36 -0
  76. data/spec/apps/rails4/basic/config/initializers/backtrace_silencers.rb +7 -0
  77. data/spec/apps/rails4/basic/config/initializers/filter_parameter_logging.rb +4 -0
  78. data/spec/apps/rails4/basic/config/initializers/inflections.rb +16 -0
  79. data/spec/apps/rails4/basic/config/initializers/mime_types.rb +5 -0
  80. data/spec/apps/rails4/basic/config/initializers/secret_token.rb +12 -0
  81. data/spec/apps/rails4/basic/config/initializers/session_store.rb +2 -0
  82. data/spec/apps/rails4/basic/config/initializers/wrap_parameters.rb +14 -0
  83. data/spec/apps/rails4/basic/config/locales/en.yml +23 -0
  84. data/spec/apps/rails4/basic/config/routes.rb +5 -0
  85. data/spec/apps/rails4/basic/db/seeds.rb +7 -0
  86. data/spec/apps/rails4/basic/lib/assets/.keep +0 -0
  87. data/spec/apps/rails4/basic/lib/tasks/.keep +0 -0
  88. data/spec/apps/rails4/basic/public/404.html +58 -0
  89. data/spec/apps/rails4/basic/public/422.html +58 -0
  90. data/spec/apps/rails4/basic/public/500.html +57 -0
  91. data/spec/apps/rails4/basic/public/favicon.ico +0 -0
  92. data/spec/apps/rails4/basic/public/robots.txt +5 -0
  93. data/spec/apps/rails4/basic/public/some_page.html +7 -0
  94. data/spec/apps/rails4/basic/test/controllers/.keep +0 -0
  95. data/spec/apps/rails4/basic/test/fixtures/.keep +0 -0
  96. data/spec/apps/rails4/basic/test/helpers/.keep +0 -0
  97. data/spec/apps/rails4/basic/test/integration/.keep +0 -0
  98. data/spec/apps/rails4/basic/test/mailers/.keep +0 -0
  99. data/spec/apps/rails4/basic/test/models/.keep +0 -0
  100. data/spec/apps/rails4/basic/test/test_helper.rb +15 -0
  101. data/spec/apps/rails4/basic/vendor/assets/javascripts/.keep +0 -0
  102. data/spec/apps/rails4/basic/vendor/assets/stylesheets/.keep +0 -0
  103. data/spec/apps/sinatra/basic/Gemfile +4 -0
  104. data/spec/apps/sinatra/basic/Gemfile.lock +20 -0
  105. data/spec/apps/sinatra/basic/basic.rb +27 -0
  106. data/spec/apps/sinatra/basic/config.ru +7 -0
  107. data/spec/apps/sinatra/basic/public/some_page.html +7 -0
  108. data/spec/apps/sinatra/basic/views/index.erb +4 -0
  109. data/spec/apps/sinatra/basic/views/posted.haml +2 -0
  110. data/spec/apps/sinatra/basic/views/poster.haml +4 -0
  111. data/spec/apps/sinatra/basic/views/request_mapping.haml +4 -0
  112. data/spec/integration/basic_rack_spec.rb +89 -0
  113. data/spec/integration/basic_rails4_spec.rb +64 -0
  114. data/spec/integration/basic_sinatra_spec.rb +80 -0
  115. data/spec/spec_helper.rb +13 -0
  116. data/test/jubilee/test_cli.rb +1 -1
  117. data/test/jubilee/test_configuration.rb +18 -1
  118. data/test/jubilee/test_rack_server.rb +7 -7
  119. data/test/jubilee/test_response.rb +35 -36
  120. data/test/jubilee/test_server.rb +1 -1
  121. data/test/jubilee/test_upload.rb +14 -11
  122. data/test/test_helper.rb +1 -0
  123. metadata +97 -18
  124. data/VERSION +0 -1
  125. data/jars/vertx-core-2.1.0-SNAPSHOT.jar +0 -0
  126. data/java/src/org/jruby/jubilee/RackErrors.java +0 -44
  127. data/java/src/org/jruby/jubilee/impl/DefaultRackEnvironment.java +0 -99
  128. data/java/src/org/jruby/jubilee/impl/RubyIORackErrors.java +0 -68
data/Rakefile CHANGED
@@ -28,16 +28,17 @@ Jeweler::Tasks.new do |gem|
28
28
  gem.homepage = "http://github.com/isaiah/jubilee"
29
29
  gem.license = "MIT"
30
30
  gem.summary = %Q{More than a server for rack applications.}
31
- gem.description = %Q{Jubilee is a experimental webserver built for speed, it's based on Vertx.}
31
+ gem.description = %Q{Jubilee is a jruby webserver built upon Vertx.}
32
32
  gem.email = "issaria@gmail.com"
33
33
  gem.authors = ["Isaiah Peng"]
34
+ gem.version = Jubilee::Version::STRING
34
35
  # dependencies defined in Gemfile
35
36
  end
36
37
  Jeweler::RubygemsDotOrgTasks.new
37
38
 
38
39
  require 'rake/testtask'
39
40
  Rake::TestTask.new(:test) do |test|
40
- test.libs << 'lib' << 'test'
41
+ test.libs << 'lib' << 'test' << 'spec'
41
42
  test.pattern = 'test/**/test_*.rb'
42
43
  test.verbose = true
43
44
  end
@@ -56,7 +57,7 @@ task :default => :test
56
57
 
57
58
  require 'rdoc/task'
58
59
  Rake::RDocTask.new do |rdoc|
59
- version = Jubilee::VERSION
60
+ version = Jubilee::Version::STRING
60
61
 
61
62
  rdoc.rdoc_dir = 'rdoc'
62
63
  rdoc.title = "jubilee #{version}"
@@ -80,7 +81,7 @@ desc "Compile the extension, need jdk7 because vertx relies on it"
80
81
  task :compile => "pkg/classes" do |t|
81
82
  ant.javac :srcdir => "java", :destdir => t.prerequisites.first,
82
83
  :source => "1.7", :target => "1.7", :debug => true,
83
- :classpath => "${java.class.path}:${sun.boot.class.path}:jars/vertx-core-2.1.0-SNAPSHOT.jar:jars/netty-all-4.0.4.Final.jar:jars/jackson-core-2.2.2.jar:jars/jackson-databind-2.2.2.jar:jars/jackson-annotations-2.2.2.jar:jars/hazelcast-2.6.jar"
84
+ :classpath => "${java.class.path}:${sun.boot.class.path}:jars/vertx-core-2.1M3-SNAPSHOT.jar:jars/netty-all-4.0.13.Final.jar:jars/jackson-core-2.2.2.jar:jars/jackson-databind-2.2.2.jar:jars/jackson-annotations-2.2.2.jar:jars/hazelcast-2.6.3.jar"
84
85
  end
85
86
 
86
87
  desc "Build the jar"
@@ -88,7 +89,7 @@ task :jar => [:clean, :compile] do
88
89
  ant.jar :basedir => "pkg/classes", :destfile => "lib/jubilee/jubilee.jar", :includes => "**/*.class"
89
90
  end
90
91
 
91
- task :package => :jar
92
+ task :build => :jar
92
93
 
93
94
  desc "Run the specs"
94
95
  task :spec => :jar do
@@ -1,4 +1,5 @@
1
+ source "https://rubygems.org"
1
2
  gem 'sinatra'
2
3
  gem 'haml'
3
4
 
4
- gem 'jubilee', '1.0.0.beta1'
5
+ gem 'jubilee', '~> 1.0.2'
@@ -1,15 +1,17 @@
1
1
  GEM
2
+ remote: https://rubygems.org/
2
3
  specs:
3
- ffi (1.9.0-java)
4
- haml (4.0.3)
4
+ ffi (1.9.3)
5
+ ffi (1.9.3-java)
6
+ haml (4.0.4)
5
7
  tilt
6
- jubilee (1.0.0.beta1)
8
+ jubilee (1.0.2)
7
9
  rack (>= 1.4.1)
8
10
  spoon (~> 0.0.4)
9
11
  rack (1.5.2)
10
- rack-protection (1.5.0)
12
+ rack-protection (1.5.1)
11
13
  rack
12
- sinatra (1.4.3)
14
+ sinatra (1.4.4)
13
15
  rack (~> 1.4)
14
16
  rack-protection (~> 1.4)
15
17
  tilt (~> 1.3, >= 1.3.4)
@@ -22,5 +24,5 @@ PLATFORMS
22
24
 
23
25
  DEPENDENCIES
24
26
  haml
25
- jubilee (= 1.0.0.beta1)
27
+ jubilee (~> 1.0.2)
26
28
  sinatra
@@ -1,7 +1,10 @@
1
1
  Get started
2
2
  -----------
3
3
 
4
- Make sure you are using jruby 1.7+ and your JDK version is 7+
4
+ There is a [online demo](http://192.241.201.68:8080/) for this
5
+ application.
6
+
7
+ Make sure you are using jruby 1.7+ (jubilee 1.1.0+ require jruby 1.7.5 or later) and your JDK version is 7+
5
8
 
6
9
  To run the application:
7
10
 
@@ -9,6 +12,6 @@ To run the application:
9
12
  bundle && jubilee --eventbus /eventbus
10
13
  ```
11
14
 
12
- Then go to http://localhost:3215 in your browser, if you have the page
15
+ Then go to http://localhost:8080 in your browser, if you have the page
13
16
  opened in multiple tabs or windows you can see the message you sent are
14
17
  broadcasted to all the other tabs.
@@ -1,5 +1,25 @@
1
1
  require 'bundler/setup'
2
2
  Bundler.require(:default)
3
+ require 'vertx'
4
+
5
+ def to_a(shared_set)
6
+ ret = []
7
+ shared_set.each{ |item| ret << item}
8
+ ret
9
+ end
10
+
11
+ Vertx::EventBus.register_handler('logout') do |message|
12
+ Vertx::SharedData.get_set(:users).delete(message.body)
13
+ end
14
+
15
+ # register the user and return the pervious users
16
+ Vertx::EventBus.register_handler('login') do |message|
17
+ user = message.body
18
+ users = Vertx::SharedData.get_set(:users).add(user)
19
+ message.reply(users: to_a(users))
20
+ Vertx::EventBus.publish("new_user", user)
21
+ end
22
+
3
23
 
4
24
  get "/" do
5
25
  haml :index
@@ -24,6 +44,10 @@ __END__
24
44
  @@index
25
45
  #updates
26
46
 
47
+ %p
48
+ %label receiver
49
+ %select#receivers(name="receiver")
50
+ %option all
27
51
  %p
28
52
  %textarea#content(name="content" rows=8 cols=80)
29
53
 
@@ -1,14 +1,67 @@
1
+ // To generate a random id
2
+ function s4() {
3
+ return Math.floor((1 + Math.random()) * 0x10000)
4
+ .toString(16)
5
+ .substring(1);
6
+ };
7
+
1
8
  $(function() {
2
9
  var eb = new vertx.EventBus("/eventbus");
10
+ var updates = $("#updates");
11
+ var uid = "Guest_" + s4();
3
12
 
4
13
  eb.onopen = function() {
5
- eb.registerHandler("chat", function(data) {
6
- $("#updates").append(data + "<br/>");
7
- });
8
- }
14
+ eb.send("login", uid, function(data){
15
+ for(var i = 0; i < data.users.length; i++) {
16
+ if (data.users[i] != uid) $("#receivers").append("<option>" + data.users[i] + "</option>");
17
+ }
18
+ });
19
+ updates.html("<h5>Welcome to the Jubilee chat room!</h5>");
20
+ eb.registerHandler("chat", function(data) {
21
+ if (data.sender != uid)
22
+ updates.append("<div class='public'><span class='sender'>" + data.sender + " said:</span>" + data.message + "</div>");
23
+ else
24
+ updates.append("<div class='public by_you'><span class='sender'>You said:</span>" + data.message + "</div>");
25
+ });
26
+
27
+ eb.registerHandler("new_user", function(data) {
28
+ if (data != uid) {
29
+ $("#receivers").append("<option>" + data + "</option");
30
+ updates.append("<div class='login'>" + data + " joined the room.</div>");
31
+ }
32
+ });
33
+
34
+ eb.registerHandler(uid, function(data) {
35
+ updates.append("<div class='private'><span class='sender'>" + data.sender + " said to you:</span>" + data.message + "</div>");
36
+ });
37
+
38
+ eb.registerHandler("logout", function(data) {
39
+ $('#receivers option:contains("' + data + '")').remove();
40
+ updates.append("<div class='logout'>" + data + " left the room.</div>");
41
+ });
9
42
 
10
- $("#send").click(function() {
11
- eb.publish("chat", $("#content").val());
43
+ window.onbeforeunload = function() {
44
+ eb.publish("logout", uid);
45
+ }
46
+ }
47
+
48
+ var sendMessage = function() {
49
+ var msg = $("#content").val();
50
+ if ((receiver = $("#receivers").val()) === "all") {
51
+ eb.publish("chat", {sender: uid, message: msg});
52
+ } else {
53
+ updates.append("<div class='public by_you'><span class='sender'>You said to " + uid + ":</span>" + msg + "</div>");
54
+ eb.send(receiver, {sender: uid, message: msg});
55
+ }
12
56
  $("#content").val("");
57
+ }
58
+
59
+ $("#send").click(sendMessage);
60
+
61
+ $(document.body).keyup(function(ev) {
62
+ if (ev.which === 13) {
63
+ sendMessage();
64
+ }
13
65
  });
66
+
14
67
  });
@@ -2,3 +2,28 @@
2
2
  min-height: 400px;
3
3
  border: 1px solid #ccc;
4
4
  }
5
+
6
+ .public, .private, .login, .logout {
7
+ border-bottom: 1px solid #CCCCCC;
8
+ line-height: 1.2em;
9
+ }
10
+
11
+ .private {
12
+ color: blue;
13
+ }
14
+
15
+ .login {
16
+ color: green;
17
+ }
18
+ .logout {
19
+ color: red;
20
+ }
21
+ .by_you {
22
+ color: gray;
23
+ }
24
+ .sender {
25
+ display: inline-block;
26
+ width: 168px;
27
+ font-size: 0.8em;
28
+ font-style: italic;
29
+ }
@@ -1,9 +1,6 @@
1
1
  # Listen to port 3000
2
2
  listen 3000
3
3
 
4
- # the number of workers to serve client
5
- worker_threads 4
6
-
7
4
  # the ssl certification path
8
5
  ssl_keystore "jubilee/keystore.jks"
9
6
 
Binary file
@@ -1,20 +1,20 @@
1
1
  package jubilee;
2
2
 
3
3
  import org.jruby.Ruby;
4
- import org.jruby.jubilee.Server;
5
- import org.jruby.jubilee.impl.NullIO;
6
- import org.jruby.jubilee.impl.RubyIORackErrors;
4
+ import org.jruby.jubilee.RubyHttpServerResponse;
5
+ import org.jruby.jubilee.RubyServer;
7
6
  import org.jruby.jubilee.impl.RubyIORackInput;
7
+ import org.jruby.jubilee.impl.RubyNullIO;
8
8
  import org.jruby.runtime.load.BasicLibraryService;
9
9
 
10
10
  import java.io.IOException;
11
11
 
12
12
  public class JubileeService implements BasicLibraryService {
13
13
  public boolean basicLoad(final Ruby ruby) throws IOException {
14
- Server.createServerClass(ruby);
15
- RubyIORackErrors.createRubyIORackErrorsClass(ruby);
16
- RubyIORackInput.createRubyIORackInputClass(ruby);
17
- NullIO.createNullIOClass(ruby);
14
+ RubyServer.createServerClass(ruby);
15
+ RubyHttpServerResponse.createHttpServerResponseClass(ruby);
16
+ RubyIORackInput.createIORackInputClass(ruby);
17
+ RubyNullIO.createNullIOClass(ruby);
18
18
  return true;
19
19
  }
20
20
  }
@@ -14,10 +14,11 @@ import java.util.Map;
14
14
  */
15
15
  public final class Const {
16
16
 
17
- public static final String JUBILEE_VERSION = "Jubilee 0.5.0";
17
+ public static final String JUBILEE_VERSION = "Jubilee(1.1.0)";
18
18
  public static final String HTTP_11 = "HTTP/1.1";
19
19
  public static final String HTTP_10 = "HTTP/1.0";
20
20
 
21
+ public static final String SCRIPT_NAME = "SCRIPT_NAME";
21
22
  public static final String SERVER_SOFTWARE = "SERVER_SOFTWARE";
22
23
  public static final String SERVER_PROTOCOL = "SERVER_PROTOCOL";
23
24
  public static final String GATEWAY_INTERFACE = "GATEWAY_INTERFACE";
@@ -50,7 +51,7 @@ public final class Const {
50
51
  public static final String HTTP_CONTENT_LENGTH = "CONTENT_LENGTH";
51
52
 
52
53
  public static class Rack {
53
- public static final String HTTP_DATE = "HTTP_DATE";
54
+ public static final String HTTP_AUTHORIZATION = "HTTP_AUTHORIZATION";
54
55
  public static final String HTTP_EXPECT = "HTTP_EXPECT";
55
56
  public static final String HTTP_IF_MATCH = "HTTP_IF_MATCH";
56
57
  public static final String HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE";
@@ -78,13 +79,15 @@ public final class Const {
78
79
  public static final String ACCEPT = "accept";
79
80
  public static final String ACCEPT_LANGUAGE = "accept-language";
80
81
  public static final String ACCEPT_ENCODING = "accept-encoding";
82
+ public static final String AUTHORIZATION = "authorization";
81
83
  public static final String CONNECTION = "connection";
82
- public static final String CONTENT_TYPE = "content-type";
83
- public static final String CONTENT_LENGTH = "content-length";
84
+ public static final String CONTENT_TYPE = "Content-Type";
85
+ public static final String CONTENT_LENGTH = "Content-Length";
84
86
  public static final String CONTENT_MD5 = "content-md5";
85
87
  public static final String HOST = "host";
86
88
 
87
- public static final String DATE = "date";
89
+ public static final String TRANSFER_ENCODING = "Transfer-Encoding";
90
+
88
91
  public static final String EXPECT = "expect";
89
92
  public static final String IF_MATCH = "if-match";
90
93
  public static final String IF_MODIFIED_SINCE = "if-modified-since";
@@ -104,35 +107,6 @@ public final class Const {
104
107
  public static final String X_FORWARDED_FOR = "x-forwarded-for"; // original ip
105
108
  }
106
109
 
107
- public static Map<String, String> ADDITIONAL_HEADERS = new HashMap<String, String>();
108
-
109
- static {
110
- ADDITIONAL_HEADERS.put(Vertx.DATE, Rack.HTTP_DATE);
111
- ADDITIONAL_HEADERS.put(Vertx.EXPECT, Rack.HTTP_EXPECT);
112
- ADDITIONAL_HEADERS.put(Vertx.IF_MATCH, Rack.HTTP_IF_MATCH);
113
- ADDITIONAL_HEADERS.put(Vertx.IF_MODIFIED_SINCE, Rack.HTTP_IF_MODIFIED_SINCE);
114
- ADDITIONAL_HEADERS.put(Vertx.IF_NONE_MATCH, Rack.HTTP_IF_NONE_MATCH);
115
- ADDITIONAL_HEADERS.put(Vertx.IF_RANGE, Rack.HTTP_IF_RANGE);
116
- ADDITIONAL_HEADERS.put(Vertx.IF_UNMODIFIED_SINCE, Rack.HTTP_IF_UNMODIFIED_SINCE);
117
- ADDITIONAL_HEADERS.put(Vertx.RANGE, Rack.HTTP_RANGE);
118
- ADDITIONAL_HEADERS.put(Vertx.PRAGMA, Rack.HTTP_PRAGMA);
119
- ADDITIONAL_HEADERS.put(Vertx.MAX_FORWARDS, Rack.HTTP_MAX_FORWARDS);
120
- ADDITIONAL_HEADERS.put(Vertx.REFERER, Rack.HTTP_REFERER);
121
- ADDITIONAL_HEADERS.put(Vertx.VIA, Rack.HTTP_VIA);
122
- ADDITIONAL_HEADERS.put(Vertx.WARNING, Rack.HTTP_WARNING);
123
- ADDITIONAL_HEADERS.put(Vertx.X_REQUESTED_WITH, Rack.HTTP_X_REQUESTED_WITH);
124
- ADDITIONAL_HEADERS.put(Vertx.DNT, Rack.HTTP_DNT);
125
- ADDITIONAL_HEADERS.put(Vertx.X_FORWARDED_FOR, Rack.HTTP_X_FORWARDED_FOR);
126
- ADDITIONAL_HEADERS.put(Vertx.CONTENT_MD5, Rack.HTTP_CONTENT_MD5);
127
- }
128
-
129
- public static RubyArray RackVersion(Ruby runtime) {
130
- RubyArray version = RubyArray.newArray(runtime, 2);
131
- version.add("1");
132
- version.add("4");
133
- return version;
134
- }
135
-
136
110
  public static final String HTTP = "http";
137
111
  public static final String HTTPS = "https";
138
112
  public static final String URL_SCHEME = "rack.url_scheme";
@@ -141,7 +115,8 @@ public final class Const {
141
115
  public static final String RACK_MULTITHREAD = "rack.multithread";
142
116
  public static final String RACK_MULTIPROCESS = "rack.multiprocess";
143
117
  public static final String RACK_RUNONCE = "rack.run_once";
144
- public static final String SCRIPT_NAME = "SCRIPT_NAME";
118
+
119
+ public static final String RACK_HIJACK_P = "rack.hijack?";
145
120
 
146
121
  private Const() {
147
122
  }
@@ -3,17 +3,23 @@ package org.jruby.jubilee;
3
3
  import io.netty.buffer.ByteBuf;
4
4
  import io.netty.buffer.Unpooled;
5
5
  import org.jruby.Ruby;
6
+ import org.jruby.RubyArray;
7
+ import org.jruby.RubyClass;
8
+ import org.jruby.RubyFixnum;
6
9
  import org.jruby.javasupport.JavaEmbedUtils;
7
- import org.jruby.jubilee.impl.DefaultRackEnvironment;
10
+ import org.jruby.jubilee.impl.RackEnvironment;
8
11
  import org.jruby.jubilee.impl.RubyIORackInput;
12
+ import org.jruby.jubilee.impl.RubyNullIO;
13
+ import org.jruby.runtime.ThreadContext;
9
14
  import org.jruby.runtime.builtin.IRubyObject;
10
15
  import org.vertx.java.core.Handler;
16
+ import org.vertx.java.core.Vertx;
11
17
  import org.vertx.java.core.VoidHandler;
12
18
  import org.vertx.java.core.buffer.Buffer;
13
19
  import org.vertx.java.core.http.HttpServerRequest;
20
+ import org.vertx.java.core.impl.DefaultVertx;
14
21
 
15
- import java.util.concurrent.ExecutorService;
16
- import java.util.concurrent.Executors;
22
+ import java.io.IOException;
17
23
  import java.util.concurrent.atomic.AtomicBoolean;
18
24
 
19
25
  /**
@@ -23,51 +29,76 @@ import java.util.concurrent.atomic.AtomicBoolean;
23
29
  * Time: 5:40 PM
24
30
  */
25
31
  public class RackApplication {
26
- private IRubyObject app;
27
- private boolean ssl;
32
+ private IRubyObject app;
33
+ private boolean ssl;
34
+ private Ruby runtime;
35
+ private DefaultVertx vertx;
36
+ private RubyClass rackIOInputClass;
37
+ private RubyClass httpServerResponseClass;
38
+ private RubyArray rackVersion;
39
+ private RubyNullIO nullio;
40
+ private RackEnvironment rackEnv;
28
41
 
29
- private ExecutorService exec;
42
+ public RackApplication(Vertx vertx, ThreadContext context, IRubyObject app, boolean ssl) throws IOException {
43
+ this.app = app;
44
+ this.ssl = ssl;
45
+ this.vertx = (DefaultVertx) vertx;
46
+ this.runtime = context.runtime;
47
+ this.rackVersion = RubyArray.newArrayLight(runtime, RubyFixnum.one(runtime), RubyFixnum.four(runtime));
48
+ // Memorize the ruby classes
49
+ this.rackIOInputClass = (RubyClass) runtime.getClassFromPath("Jubilee::IORackInput");
50
+ this.httpServerResponseClass = (RubyClass) runtime.getClassFromPath("Jubilee::HttpServerResponse");
51
+ this.nullio = new RubyNullIO(runtime, (RubyClass) runtime.getClassFromPath("Jubilee::NullIO"));
30
52
 
31
- public RackApplication(IRubyObject app, boolean ssl, int numberOfWorkers) {
32
- this.app = app;
33
- this.ssl = ssl;
34
- exec = Executors.newFixedThreadPool(numberOfWorkers);
35
- }
53
+ this.rackEnv = new RackEnvironment(runtime);
54
+ }
36
55
 
37
- public void call(final HttpServerRequest request) {
38
- final ByteBuf bodyBuf = Unpooled.unreleasableBuffer(Unpooled.buffer(0, Integer.MAX_VALUE));
39
- final Ruby runtime = app.getRuntime();
40
- final AtomicBoolean eof = new AtomicBoolean(false);
41
- request.dataHandler(new Handler<Buffer>() {
42
- @Override
43
- public void handle(Buffer buffer) {
44
- bodyBuf.writeBytes(buffer.getBytes());
45
- }
46
- });
47
- // TODO optimize by use NullIO when there is no body here.
48
- Runnable task = new Runnable() {
49
- @Override
50
- public void run() {
51
- RackInput input = new RubyIORackInput(runtime, request, bodyBuf, eof);
52
- RackEnvironment env = new DefaultRackEnvironment(runtime, request, input, ssl);
53
- IRubyObject result = app.callMethod(runtime.getCurrentContext(), "call", env.getEnv());
54
- RackResponse response = (RackResponse) JavaEmbedUtils.rubyToJava(runtime, result, RackResponse.class);
55
- response.respond(request.response());
56
- }
57
- };
58
- exec.execute(task);
59
- request.endHandler(new VoidHandler() {
60
- @Override
61
- protected void handle() {
62
- eof.set(true);
63
- }
64
- });
65
- }
56
+ public void call(final HttpServerRequest request) {
57
+ // String te = request.headers().get(Const.Vertx.TRANSFER_ENCODING);
58
+ // String contentLength;
59
+ final RackInput input;
60
+ // This should be handled by Netty (expose a contentLength methods via HttpRequest,
61
+ // it set the empty content flag when passing the header
62
+ // if ((te != null && te.equals("chunked")) ||
63
+ // ((contentLength = request.headers().get(Const.Vertx.CONTENT_LENGTH)) != null && !contentLength.equals("0"))) {
64
+ final ByteBuf bodyBuf = Unpooled.buffer(0, Integer.MAX_VALUE);
65
+ final AtomicBoolean eof = new AtomicBoolean(false);
66
+ input = new RubyIORackInput(runtime, rackIOInputClass, request, bodyBuf, eof);
67
+
68
+ request.dataHandler(new Handler<Buffer>() {
69
+ @Override
70
+ public void handle(Buffer buffer) {
71
+ bodyBuf.writeBytes(buffer.getByteBuf());
72
+ }
73
+ });
74
+
75
+ request.endHandler(new VoidHandler() {
76
+ @Override
77
+ protected void handle() {
78
+ eof.set(true);
79
+ }
80
+ });
81
+ // } else {
82
+ // input = nullio;
83
+ // }
84
+ Runnable task = new Runnable() {
85
+ @Override
86
+ public void run() {
87
+ // This is a different context, do NOT replace runtime.getCurrentContext()
88
+ // IRubyObject result = app.callMethod(runtime.getCurrentContext(), "call", env.getEnv());
89
+ try {
90
+ IRubyObject result = app.callMethod(runtime.getCurrentContext(), "call", rackEnv.getEnv(request, input, ssl));
91
+ RackResponse response = (RackResponse) JavaEmbedUtils.rubyToJava(runtime, result, RackResponse.class);
92
+ RubyHttpServerResponse resp = new RubyHttpServerResponse(runtime,
93
+ httpServerResponseClass,
94
+ request.response());
95
+ response.respond(resp);
96
+ } catch (IOException e) {
97
+ // noop
98
+ }
99
+ }
100
+ };
101
+ vertx.startInBackground(task, false);
102
+ }
66
103
 
67
- public void shutdown(boolean force) {
68
- if (force)
69
- exec.shutdownNow();
70
- else
71
- exec.shutdown();
72
- }
73
104
  }