jubilee 2.1.0.Alpha1-java → 2.1.0.beta-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -2
  3. data/CHANGELOG +9 -0
  4. data/README.md +12 -7
  5. data/jars/vertx-core-2.1.1.jar +0 -0
  6. data/java/src/jubilee/JubileeService.java +3 -3
  7. data/java/src/org/jruby/jubilee/Const.java +1 -1
  8. data/java/src/org/jruby/jubilee/JubileeVerticle.java +29 -4
  9. data/java/src/org/jruby/jubilee/RackApplication.java +38 -35
  10. data/java/src/org/jruby/jubilee/RackEnvironment.java +57 -23
  11. data/java/src/org/jruby/jubilee/RackEnvironmentHash.java +64 -11
  12. data/java/src/org/jruby/jubilee/RackInput.java +13 -10
  13. data/java/src/org/jruby/jubilee/RubyCallable.java +52 -0
  14. data/java/src/org/jruby/jubilee/RubyChannel.java +89 -0
  15. data/java/src/org/jruby/jubilee/RubyHttpServerResponse.java +72 -60
  16. data/java/src/org/jruby/jubilee/RubyNetSocket.java +169 -0
  17. data/java/src/org/jruby/jubilee/RubyPlatformManager.java +129 -113
  18. data/java/src/org/jruby/jubilee/impl/RubyIORackInput.java +9 -9
  19. data/java/src/org/jruby/jubilee/impl/RubyNullIO.java +1 -1
  20. data/java/src/org/jruby/jubilee/utils/RubyHelper.java +0 -6
  21. data/java/src/org/jruby/jubilee/vertx/JubileeVertx.java +12 -11
  22. data/jubilee.gemspec +43 -20
  23. data/lib/jubilee.rb +0 -1
  24. data/lib/jubilee/cli.rb +5 -3
  25. data/lib/jubilee/configuration.rb +2 -7
  26. data/lib/jubilee/const.rb +30 -28
  27. data/lib/jubilee/response.rb +40 -5
  28. data/lib/jubilee/server.rb +0 -3
  29. data/lib/jubilee/version.rb +1 -1
  30. data/spec/apps/rails4/basic/Gemfile +0 -2
  31. data/spec/apps/rails4/basic/Gemfile.lock +0 -7
  32. data/spec/integration/basic_rack_spec.rb +4 -3
  33. data/spec/integration/basic_rails4_spec.rb +4 -3
  34. data/spec/integration/basic_sinatra_spec.rb +4 -4
  35. data/spec/spec_helper.rb +1 -0
  36. data/test/{config → apps}/app.rb +0 -0
  37. data/test/apps/checker.ru +5 -10
  38. data/test/apps/chunked.ru +3 -0
  39. data/test/{config → apps}/config.ru +0 -0
  40. data/test/apps/content_length.ru +3 -0
  41. data/test/apps/hex.ru +4 -0
  42. data/test/apps/hijack.ru +7 -0
  43. data/test/apps/hijack2.ru +7 -0
  44. data/test/apps/huge.ru +4 -0
  45. data/test/apps/method_override.ru +1 -1
  46. data/test/apps/overwrite_check.ru +3 -2
  47. data/test/apps/persistent.rb +14 -0
  48. data/test/apps/persistent.ru +3 -0
  49. data/test/apps/rack_input.ru +5 -0
  50. data/test/apps/self_chunked.ru +6 -0
  51. data/test/apps/sha1.ru +2 -0
  52. data/test/apps/simple.ru +10 -1
  53. data/test/jubilee/test_cli.rb +1 -1
  54. data/test/jubilee/test_configuration.rb +1 -3
  55. data/test/jubilee/test_hijack.rb +27 -0
  56. data/test/jubilee/test_persistent.rb +208 -0
  57. data/test/jubilee/test_rack_server.rb +29 -68
  58. data/test/jubilee/test_server.rb +49 -15
  59. data/test/jubilee/test_upload.rb +13 -60
  60. data/test/test_helper.rb +2 -2
  61. metadata +19 -9
  62. data/java/src/org/jruby/jubilee/RubyServer.java +0 -159
  63. data/lib/jubilee/jubilee.jar +0 -0
  64. data/lib/rack/chunked.rb +0 -38
  65. data/test/config/app.ru +0 -3
  66. data/test/jubilee/test_response.rb +0 -270
@@ -0,0 +1,5 @@
1
+ app = lambda do |env|
2
+ data = env['rack.input'].read
3
+ [200, {}, [data]]
4
+ end
5
+ run app
@@ -0,0 +1,6 @@
1
+ require_relative './persistent'
2
+ body = ["5\r\nhello\r\n", "0\r\n\r\n"]
3
+ headers= {"X-Header" => "Works", 'Transfer-Encoding' => "chunked"}
4
+
5
+ run Persistent.new(body, headers)
6
+
@@ -1,3 +1,4 @@
1
+ require 'digest'
1
2
  bs = 4096
2
3
  hdr = {'Content-Type' => 'text/plain', 'Content-Length' => '0'}
3
4
  sha1_app = lambda do |env|
@@ -31,6 +32,7 @@ sha1_app = lambda do |env|
31
32
  end
32
33
  resp[:size] = i
33
34
  resp[:expect_size] = expect_size
35
+ resp[:content_md5] = env['HTTP_X_CONTENT_MD5']
34
36
 
35
37
  [ 200, hdr.merge({'X-Resp' => resp.inspect}), [] ]
36
38
  end
@@ -1 +1,10 @@
1
- run lambda { |env| [200, { "X-Header" => "Works" }, ["Hello"]] }
1
+ require 'rack/request'
2
+ require 'json'
3
+
4
+ app = lambda do |env|
5
+ req = Rack::Request.new(env)
6
+ body = JSON.dump(req.params.merge({"QUERY_STRING" => env["QUERY_STRING"], "PATH_INFO" => env["PATH_INFO"]}))
7
+ [200, { "X-Header" => "Works" }, [body]]
8
+ end
9
+
10
+ run app
@@ -11,7 +11,7 @@ class TestJubileeCLI < MiniTest::Unit::TestCase
11
11
  def test_chdir
12
12
  cli = Jubilee::CLI.new(["--dir", "test", "app.ru"])
13
13
  cli.parse_options
14
- assert_equal "test", cli.options[:chdir]
14
+ assert_equal "test", cli.options[:root]
15
15
  end
16
16
 
17
17
  def test_eventbus_prefix
@@ -5,13 +5,11 @@ class TestConfig < MiniTest::Unit::TestCase
5
5
 
6
6
  def setup
7
7
  @tmp = Tempfile.new("jubilee_config")
8
- @dir = Dir.getwd
9
8
  end
10
9
 
11
10
  def teardown
12
11
  @tmp.close
13
12
  @tmp.unlink
14
- Dir.chdir(@dir)
15
13
  end
16
14
 
17
15
  def test_config_invalid
@@ -67,7 +65,7 @@ class TestConfig < MiniTest::Unit::TestCase
67
65
  def test_config_file_working_directory
68
66
  @tmp.syswrite(%q(working_directory "examples/chatapp"))
69
67
  options = Jubilee::Configuration.new(config_file: @tmp.path).options
70
- assert_match(/chatapp/, options[:chdir])
68
+ assert_match(/chatapp/, options[:root])
71
69
  end
72
70
 
73
71
  def test_config_file_environment
@@ -0,0 +1,27 @@
1
+ require 'test_helper'
2
+ require 'socket'
3
+
4
+ class TestJubileeServer < MiniTest::Unit::TestCase
5
+ def setup
6
+ end
7
+
8
+ def teardown
9
+ @client.close
10
+ sleep 0.1
11
+ @server.stop
12
+ end
13
+
14
+ def test_hijack_supported
15
+ skip "not valid"
16
+ @valid_post = "POST / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\nContent-Length: 5\r\n\r\nhello"
17
+ @host, @port = "localhost", 8080
18
+
19
+ config = Jubilee::Configuration.new(rackup: File.expand_path("../../apps/hijack.ru", __FILE__), instances: 1)
20
+ @server = Jubilee::Server.new(config.options)
21
+ @server.start
22
+ @client = TCPSocket.new @host, @port
23
+
24
+ @client << @valid_post
25
+ assert @jijack
26
+ end
27
+ end
@@ -0,0 +1,208 @@
1
+ require 'test_helper'
2
+ require 'timeout'
3
+ require 'socket'
4
+ class TestResponse < MiniTest::Unit::TestCase
5
+ def setup
6
+ @valid_request = "GET / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
7
+ @close_request = "GET / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\nConnection: Close\r\n\r\n"
8
+ @http10_request = "GET / HTTP/1.0\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
9
+ @keep_request = "GET / HTTP/1.0\r\nHost: test.com\r\nContent-Type: text/plain\r\nConnection: Keep-Alive\r\n\r\n"
10
+
11
+ @valid_post = "POST / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\nContent-Length: 5\r\n\r\nhello"
12
+ @valid_no_body = "GET / HTTP/1.1\r\nHost: test.com\r\nX-Status: 204\r\nContent-Type: text/plain\r\n\r\n"
13
+
14
+ @headers = { "X-Header" => "Works" }
15
+ @body = ["Hello"]
16
+ @sz = @body[0].size.to_s
17
+
18
+ @host = "127.0.0.1"
19
+ @port = 8080
20
+
21
+ end
22
+
23
+ def teardown
24
+ @client.close if @client
25
+ @server.stop if @server
26
+ sleep 0.1
27
+ end
28
+
29
+ def lines(count, s=@client)
30
+ str = ""
31
+ timeout(5) do
32
+ count.times { str << s.gets }
33
+ end
34
+ str
35
+ end
36
+
37
+ def valid_response(size = @sz, close = false)
38
+ conn = close ? "close" : "keep-alive"
39
+ %r{HTTP/1.1 200 OK\r\nX-Header: Works\r\nServer: Jubilee\(\d\.\d\.\d\)\r\nContent-Length: #{size}\r\nConnection: #{conn}\r\nDate: (.*?)\r\n\r\n}
40
+ end
41
+
42
+ def test_one_with_content_length
43
+ start_server
44
+ @client << @valid_request
45
+ sz = @body[0].size.to_s
46
+
47
+ assert_match valid_response(sz), lines(7)
48
+ assert_equal "Hello", @client.read(5)
49
+ end
50
+
51
+ def test_two_back_to_back
52
+ start_server
53
+ @client << @valid_request
54
+ sz = @body[0].size.to_s
55
+
56
+ assert_match valid_response(sz), lines(7)
57
+ assert_equal "Hello", @client.read(5)
58
+
59
+ @client << @valid_request
60
+ sz = @body[0].size.to_s
61
+
62
+ assert_match valid_response(sz), lines(7)
63
+ assert_equal "Hello", @client.read(5)
64
+ end
65
+
66
+ def test_post_then_get
67
+ start_server
68
+ @client << @valid_post
69
+ sz = @body[0].size.to_s
70
+
71
+ assert_match valid_response(sz), lines(7)
72
+ assert_equal "Hello", @client.read(5)
73
+
74
+ @client << @valid_request
75
+ sz = @body[0].size.to_s
76
+
77
+ assert_match valid_response(sz), lines(7)
78
+ assert_equal "Hello", @client.read(5)
79
+ end
80
+
81
+ def test_no_body_then_get
82
+ start_server
83
+ @client << @valid_no_body
84
+ assert_match %r{HTTP/1.1 204 No Content\r\nX-Header: Works\r\nConnection: keep-alive\r\n(.*?\r\n)*?\r\n}, lines(6)
85
+
86
+ @client << @valid_request
87
+ sz = @body[0].size.to_s
88
+
89
+ assert_match %r{HTTP/1.1 200 OK\r\nX-Header: Works\r\nServer: Jubilee\(\d\.\d\.\d\)\r\nContent-Length: #{sz}\r\nConnection: keep-alive\r\n(.*?\r\n)*?\r\n}, lines(7)
90
+ assert_equal "Hello", @client.read(5)
91
+ end
92
+
93
+ def test_chunked
94
+ start_server("chunked")
95
+
96
+ @client << @valid_request
97
+
98
+ assert_match %r{HTTP/1.1 200 OK\r\nX-Header: Works\r\nServer: Jubilee\(\d\.\d\.\d\)\r\nConnection: keep-alive\r\nTransfer-Encoding: chunked\r\nDate(.*?)\r\n\r\n5\r\nHello\r\n7\r\nChunked\r\n0\r\n\r\n}, lines(13)
99
+ end
100
+
101
+ def test_no_chunked_in_http10
102
+ start_server("chunked")
103
+
104
+ @client << @http10_request
105
+
106
+ assert_match %r{HTTP/1.0 200 OK\r\nX-Header: Works\r\nServer: Jubilee\(\d\.\d\.\d\)\r\nConnection: close\r\nDate: (.*?)\r\n\r\n}, lines(6)
107
+ assert_equal "HelloChunked", @client.read
108
+ end
109
+
110
+ def test_hex
111
+ start_server("hex")
112
+ str = "This is longer and will be in hex"
113
+
114
+ @client << @valid_request
115
+
116
+ assert_match %r{HTTP/1.1 200 OK\r\nX-Header: Works\r\nServer: Jubilee(.*?)\r\nConnection: keep-alive\r\nTransfer-Encoding: chunked\r\nDate: (.*?)\r\n\r\n5\r\nHello\r\n#{str.size.to_s(16)}\r\n#{str}\r\n0\r\n\r\n}, lines(13)
117
+
118
+ end
119
+
120
+ def test_client11_close
121
+ start_server
122
+ @client << @close_request
123
+ sz = @body[0].size.to_s
124
+
125
+ assert_match valid_response(sz, true), lines(7)
126
+ assert_equal "Hello", @client.read(5)
127
+ end
128
+
129
+ def test_app_sets_content_length
130
+ start_server("content_length")
131
+ @client << @valid_request
132
+
133
+ assert_match valid_response(11), lines(7)
134
+ assert_equal "hello world", @client.read(11)
135
+ end
136
+
137
+ def test_allow_app_to_chunk_itself
138
+ start_server("self_chunked")
139
+ @client << @valid_request
140
+
141
+ assert_match %r{HTTP/1.1 200 OK\r\nX-Header: Works\r\nServer: Jubilee(.*?)\r\nConnection: keep-alive\r\nTransfer-Encoding: chunked\r\nDate: (.*?)\r\n\r\n5\r\nhello\r\n0\r\n\r\n}, lines(11)
142
+ end
143
+
144
+
145
+ def test_two_requests_in_one_chunk
146
+ start_server
147
+ req = @valid_request.to_s
148
+ req << "GET /second HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
149
+
150
+ @client << req
151
+
152
+ sz = @body[0].size.to_s
153
+
154
+ assert_match valid_response(sz), lines(7)
155
+ assert_equal "Hello", @client.read(5)
156
+
157
+ assert_match valid_response(sz), lines(7)
158
+ assert_equal "Hello", @client.read(5)
159
+ end
160
+
161
+ def test_second_request_not_in_first_req_body
162
+ start_server
163
+
164
+ req = @valid_request.to_s
165
+ req << "GET /second HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
166
+
167
+ @client << req
168
+
169
+ sz = @body[0].size.to_s
170
+
171
+ assert_match valid_response(sz), lines(7)
172
+ assert_equal "Hello", @client.read(5)
173
+
174
+ assert_match valid_response(sz), lines(7)
175
+ assert_equal "Hello", @client.read(5)
176
+
177
+ #assert_kind_of Jubilee::IORackInput, @inputs[0]
178
+ #assert_kind_of Jubilee::IORackInput, @inputs[1]
179
+ end
180
+
181
+ def test_keepalive_doesnt_starve_clients
182
+ start_server
183
+ sz = @body[0].size.to_s
184
+
185
+ @client << @valid_request
186
+
187
+ c2 = TCPSocket.new @host, @port
188
+ c2 << @valid_request
189
+
190
+ out = IO.select([c2], nil, nil, 1)
191
+
192
+ assert out, "select returned nil"
193
+ assert_equal c2, out.first.first
194
+
195
+ assert_match valid_response(sz), lines(7, c2)
196
+ assert_equal "Hello", c2.read(5)
197
+ end
198
+
199
+ def start_server(ru='persistent')
200
+ config = Jubilee::Configuration.new(rackup: File.expand_path("../../apps/#{ru}.ru", __FILE__), instances: 1)
201
+ @server = Jubilee::Server.new(config.options)
202
+ q = Queue.new
203
+ @server.start{ q << 1 }
204
+ q.pop
205
+ sleep 0.1
206
+ @client = TCPSocket.new @host, @port
207
+ end
208
+ end
@@ -1,115 +1,76 @@
1
1
  require 'test_helper'
2
- require 'rack/lint'
3
- require 'rack/commonlogger'
2
+ require 'json'
4
3
 
5
4
  class TestRackServer < MiniTest::Unit::TestCase
6
5
  include Helpers
7
6
 
8
- def setup
9
- @valid_request = "GET / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
10
- @checker = "checker.ru"
11
- @host = "localhost"
12
- @port = 8080
13
- end
14
-
15
7
  def teardown
16
- @server.stop if @server
8
+ @server.stop
17
9
  sleep 0.1
18
10
  end
19
11
 
20
12
  def test_lint
21
- @server = Jubilee::Server.new @checker
22
-
23
- @server.start
13
+ start_server("checker")
14
+ resp = hit(['http://127.0.0.1:8080/test']).first
24
15
 
25
- hit(['http://127.0.0.1:8080/test'])
26
-
27
- if exc = @checker.exception
16
+ if exc = JSON.parse(resp.body)["exception"]
28
17
  raise exc
29
18
  end
30
19
  end
31
20
 
32
21
  def test_large_post_body
33
- @checker = ErrorChecker.new ServerLint.new(@simple)
34
- @server = Jubilee::Server.new @checker
35
-
36
- @server.start
37
- sleep 0.5
38
-
22
+ start_server("checker")
39
23
  big = "x" * (1024 * 16)
40
-
41
- Net::HTTP.post_form URI.parse('http://127.0.0.1:8080/test'),
42
- { "big" => big }
43
-
44
- if exc = @checker.exception
24
+ resp = POST('/test', { "big" => big })
25
+ if exc = JSON.parse(resp.body)["exception"]
45
26
  raise exc
46
27
  end
47
28
  end
48
29
 
49
30
  def test_path_info
50
- input = nil
51
- @server = Jubilee::Server.new(lambda { |env| input = env; @simple.call(env) })
52
- @server.start
53
-
54
- hit(['http://127.0.0.1:8080/test/a/b/c'])
55
-
56
- assert_equal "/test/a/b/c", input['PATH_INFO']
31
+ start_server("simple")
32
+ resp = hit(['http://127.0.0.1:8080/test/a/b/c']).first
33
+ assert_equal "/test/a/b/c", JSON.parse(resp.body)['PATH_INFO']
57
34
  end
58
35
 
59
36
  def test_request_method
60
- input = nil
61
- @server = Jubilee::Server.new(Rack::MethodOverride.new(lambda { |env| input = env; @simple.call(env) }))
62
- @server.start
63
-
64
- POST('/test/a/b/c', {"_method" => "delete", "user" => 1})
65
- assert_equal "DELETE", input['REQUEST_METHOD']
37
+ start_server("method_override")
38
+ resp = POST('/test/a/b/c', {"_method" => "delete", "user" => 1})
39
+ assert_equal "DELETE", resp.body
66
40
 
67
41
  # it should not memorize env
68
- POST('/test/a/b/c', {"foo" => "bar"})
69
- assert_equal "POST", input['REQUEST_METHOD']
70
-
42
+ resp = POST('/test/a/b/c', {"foo" => "bar"})
43
+ assert_equal "POST", resp.body
71
44
  end
72
45
 
73
46
  def test_query_string
74
- input = nil
75
- @server = Jubilee::Server.new(lambda { |env| input = env; @simple.call(env) })
76
- @server.start
77
- sleep 0.1
78
-
79
- hit(['http://127.0.0.1:8080/test/a/b/c?foo=bar'])
80
-
81
- assert_equal "foo=bar", input['QUERY_STRING']
47
+ start_server("simple")
48
+ resp = hit(['http://127.0.0.1:8080/test/a/b/c?foo=bar']).first
49
+ assert_equal "foo=bar", JSON.parse(resp.body)['QUERY_STRING']
82
50
  end
83
51
 
84
52
  def test_post_data
85
53
  require 'rack/request'
86
- input = nil
87
- @server = Jubilee::Server.new(lambda { |env| input = env; @simple.call(env) })
88
- @server.start
89
- sleep 0.1
90
-
54
+ start_server("simple")
91
55
  req = Net::HTTP::Post::Multipart.new("/", "foo" => "bar")
92
- Net::HTTP.start('localhost', 8080) do |http|
56
+ resp = Net::HTTP.start('localhost', 8080) do |http|
93
57
  http.request req
94
58
  end
95
59
 
96
- #Net::HTTP.post_form URI.parse('http://127.0.0.1:8080/test'), { "foo" => "bar" }
97
-
98
- request = Rack::Request.new input
99
- assert_equal "bar", request.params["foo"]
60
+ assert_equal "bar", JSON.parse(resp.body)["foo"]
100
61
  end
101
62
 
102
63
  def test_end_request_when_rack_crashes
103
- @server = Jubilee::Server.new(RackCrasher.new(@simple))
104
- @server.start
64
+ start_server("rack_crasher")
105
65
  res = hit(['http://127.0.0.1:8080/test'])
106
66
  assert_kind_of Net::HTTPServerError, res[0]
107
67
  end
108
68
 
109
- # GH_9
110
- def test_string_port_value
111
- @server = Jubilee::Server.new(@simple, {Port: "3000"})
112
- # assert_wont_raise_anything
113
- @server.start
69
+ def start_server(ru)
70
+ config = Jubilee::Configuration.new(rackup: File.expand_path("../../apps/#{ru}.ru", __FILE__), instances: 1)
71
+ @server = Jubilee::Server.new(config.options)
72
+ q = Queue.new
73
+ @server.start{ q << 1 }
74
+ q.pop
114
75
  end
115
76
  end