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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 683724968b6ea7ae25e8fcb25f3684bc65df6a47
4
- data.tar.gz: 92f9f51d3833a0b228bc22f49cdcd07a4d2a02f2
3
+ metadata.gz: 865bcd4759e0b52c639ae642a749f1885da1025c
4
+ data.tar.gz: 7a13f948d9e4a4a75ee039b1765b74ea9333c3b6
5
5
  SHA512:
6
- metadata.gz: e9a114e152bc837ab4ce9d8ab2759cf7edcc9f2f79e40871c3e8c8b4d0489d08b29eb8bfcafc74318e13025a4d5d6c60a2350cdc4e3670096f90c96842b84a70
7
- data.tar.gz: 9de31bb5904dc1ff30d37bb2f081bb451dd024819f1a758594514839e68d0cf1d47f836d35438ade2993126dd655a00d8f5f8effbc077cb0ee935afde57f09e0
6
+ metadata.gz: ba572a6a03c0c8c593d6f183375c8aa42fa69c10fe5c41b9d50fd9f0d7360f7ad3a71201ee7dd695a4ee5c1ddfac98b77d5ed3727cec2e68c7e4a8d63c1d3757
7
+ data.tar.gz: 7e209e4e8a9d0e24599078aa550b2a74c57e1a4f7a8d1961d9fcb67faf1c403301d29436dcfb0c582402a69fc6bff6883c50a6e61482f01f6f947e23efa3a2ae
@@ -1,5 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
- - jruby-19mode # JRuby in 1.9 mode
3
+ - jruby-19mode
4
4
 
5
- script: "bundle exec rake spec"
5
+ script: "bundle exec rake test spec"
data/CHANGELOG CHANGED
@@ -1,3 +1,12 @@
1
+ Release 2.1.0
2
+ =============
3
+
4
+ #4 rack.hijack support
5
+
6
+ Release 2.0.0
7
+ =============
8
+ support multiple instances of web servers
9
+
1
10
  Release 1.1.1
2
11
  =============
3
12
 
data/README.md CHANGED
@@ -52,18 +52,23 @@ Get started
52
52
  Setup
53
53
  -----
54
54
 
55
- If you use bundler, you might want to add `jubilee` to your Gemfile,
56
- this is also required if you want use rails http streaming,
55
+ If you use bundler, you might want to add `jubilee` to your Gemfile
57
56
 
58
- $ jubilee
57
+ gem 'jubilee', '~> 2.0.0'
59
58
 
60
- or if you prefer to use the rack handler(e.g. development) use:
59
+ Rails
60
+ -----
61
+
62
+ Under the default setup, jubilee runs 4 instances of web
63
+ servers, each with it's own jruby runtime, if you find that jubilee
64
+ crashes or hangs with OutOfMemeoryError, please tune your JVM OPTS
65
+ like this:
61
66
 
62
- $ rails s jubilee
67
+ $ export JAVA_OPTS="-Xms1024m -Xmx2048m -XX:PermSize=512m -XX:MaxPermSize=512m"
63
68
 
64
- or
69
+ If your OS memory is quite limited, please run jubilee with
65
70
 
66
- $ rackup -s jubilee
71
+ $ jubilee -n 1
67
72
 
68
73
  Event Bus
69
74
  =========
Binary file
@@ -2,8 +2,8 @@ package jubilee;
2
2
 
3
3
  import org.jruby.Ruby;
4
4
  import org.jruby.jubilee.RubyHttpServerResponse;
5
+ import org.jruby.jubilee.RubyNetSocket;
5
6
  import org.jruby.jubilee.RubyPlatformManager;
6
- import org.jruby.jubilee.RubyServer;
7
7
  import org.jruby.jubilee.impl.RubyIORackInput;
8
8
  import org.jruby.jubilee.impl.RubyNullIO;
9
9
  import org.jruby.runtime.load.BasicLibraryService;
@@ -12,11 +12,11 @@ import java.io.IOException;
12
12
 
13
13
  public class JubileeService implements BasicLibraryService {
14
14
  public boolean basicLoad(final Ruby ruby) throws IOException {
15
- RubyServer.createServerClass(ruby);
16
15
  RubyHttpServerResponse.createHttpServerResponseClass(ruby);
17
16
  RubyIORackInput.createIORackInputClass(ruby);
18
17
  RubyNullIO.createNullIOClass(ruby);
19
- RubyPlatformManager.createPlatformManagerClass(ruby);
18
+ RubyNetSocket.createNetSocketClass(ruby);
19
+ RubyPlatformManager.createPlatformManagerClass(ruby);
20
20
  return true;
21
21
  }
22
22
  }
@@ -8,7 +8,7 @@ package org.jruby.jubilee;
8
8
  */
9
9
  public final class Const {
10
10
 
11
- public static final String JUBILEE_VERSION = "Jubilee(2.0.0)";
11
+ public static final String JUBILEE_VERSION = "Jubilee(2.1.0)";
12
12
  public static final String HTTP_11 = "HTTP/1.1";
13
13
  public static final String HTTP_10 = "HTTP/1.0";
14
14
 
@@ -1,7 +1,9 @@
1
1
  package org.jruby.jubilee;
2
2
 
3
3
  import org.jruby.Ruby;
4
+ import org.jruby.RubyArray;
4
5
  import org.jruby.RubyInstanceConfig;
6
+ import org.jruby.RubyString;
5
7
  import org.jruby.runtime.builtin.IRubyObject;
6
8
  import org.vertx.java.core.Handler;
7
9
  import org.vertx.java.core.http.HttpServer;
@@ -12,13 +14,14 @@ import org.vertx.java.platform.Verticle;
12
14
  import org.vertx.java.platform.impl.WrappedVertx;
13
15
 
14
16
  import java.io.IOException;
17
+ import java.util.ArrayList;
15
18
  import java.util.Arrays;
19
+ import java.util.List;
16
20
 
17
21
  /**
18
22
  * Created by isaiah on 23/01/2014.
19
23
  */
20
24
  public class JubileeVerticle extends Verticle {
21
- private Ruby runtime;
22
25
 
23
26
  @Override
24
27
  public void start() {
@@ -32,7 +35,7 @@ public class JubileeVerticle extends Verticle {
32
35
  final RackApplication app;
33
36
  boolean ssl = config.getBoolean("ssl");
34
37
  try {
35
- app = new RackApplication((WrappedVertx) vertx, runtime.getCurrentContext(), rackApplication, ssl);
38
+ app = new RackApplication((WrappedVertx) vertx, runtime.getCurrentContext(), rackApplication, config);
36
39
  httpServer.setAcceptBacklog(10000);
37
40
  httpServer.requestHandler(new Handler<HttpServerRequest>() {
38
41
  public void handle(final HttpServerRequest req) {
@@ -59,6 +62,10 @@ public class JubileeVerticle extends Verticle {
59
62
  this.runtime.tearDown();
60
63
  }
61
64
 
65
+ public void setClassLoader(ClassLoader classLoader) {
66
+ this.classLoader = classLoader;
67
+ }
68
+
62
69
  private Ruby createRuntime(String root, JsonObject options) {
63
70
  Ruby runtime;
64
71
  // if (Ruby.isGlobalRuntimeReady()) {
@@ -71,9 +78,17 @@ public class JubileeVerticle extends Verticle {
71
78
  }
72
79
  Object[] argv = options.getArray("argv", new JsonArray(new String[]{})).toArray();
73
80
  instanceConfig.setArgv(Arrays.copyOf(argv, argv.length, String[].class));
74
- runtime = Ruby.newInstance(instanceConfig);
75
81
  // }
76
- runtime.getLoadService().addPaths(root);
82
+ RubyArray globalLoadPaths = (RubyArray) Ruby.getGlobalRuntime().getLoadService().getLoadPath();
83
+ List<String> loadPaths = new ArrayList<>();
84
+ for (int i = 0; i < globalLoadPaths.size(); i++) {
85
+ IRubyObject entry = globalLoadPaths.eltInternal(i);
86
+ loadPaths.add(entry.asJavaString());
87
+ }
88
+ instanceConfig.setLoadPaths(loadPaths);
89
+
90
+ instanceConfig.setLoader(getClassLoader());
91
+ runtime = Ruby.newInstance(instanceConfig);
77
92
  return runtime;
78
93
  }
79
94
 
@@ -89,4 +104,14 @@ public class JubileeVerticle extends Verticle {
89
104
  rackScript += "Jubilee::Application.new(app)\n";
90
105
  return runtime.evalScriptlet(rackScript);
91
106
  }
107
+
108
+ private ClassLoader getClassLoader() {
109
+ if (this.classLoader != null) return this.classLoader;
110
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
111
+ if (cl != null) return cl;
112
+ return getClass().getClassLoader();
113
+ }
114
+
115
+ private Ruby runtime;
116
+ private ClassLoader classLoader;
92
117
  }
@@ -6,18 +6,16 @@ import org.jruby.Ruby;
6
6
  import org.jruby.RubyArray;
7
7
  import org.jruby.RubyClass;
8
8
  import org.jruby.RubyFixnum;
9
- import org.jruby.exceptions.RaiseException;
10
9
  import org.jruby.javasupport.JavaEmbedUtils;
11
10
  import org.jruby.jubilee.impl.RubyIORackInput;
12
11
  import org.jruby.jubilee.impl.RubyNullIO;
13
12
  import org.jruby.runtime.ThreadContext;
14
13
  import org.jruby.runtime.builtin.IRubyObject;
15
14
  import org.vertx.java.core.Handler;
16
- import org.vertx.java.core.Vertx;
17
15
  import org.vertx.java.core.VoidHandler;
18
16
  import org.vertx.java.core.buffer.Buffer;
19
17
  import org.vertx.java.core.http.HttpServerRequest;
20
- import org.vertx.java.core.impl.DefaultVertx;
18
+ import org.vertx.java.core.json.JsonObject;
21
19
  import org.vertx.java.platform.impl.WrappedVertx;
22
20
 
23
21
  import java.io.IOException;
@@ -34,24 +32,22 @@ import java.util.concurrent.atomic.AtomicBoolean;
34
32
  public class RackApplication {
35
33
  private IRubyObject app;
36
34
  private boolean ssl;
35
+ private boolean hideErrorStack;
37
36
  private Ruby runtime;
38
37
  private WrappedVertx vertx;
39
38
  private RubyClass rackIOInputClass;
40
39
  private RubyClass httpServerResponseClass;
41
- private RubyArray rackVersion;
42
- private RubyNullIO nullio;
43
40
  private RackEnvironment rackEnv;
44
41
 
45
- public RackApplication(WrappedVertx vertx, ThreadContext context, IRubyObject app, boolean ssl) throws IOException {
42
+ public RackApplication(WrappedVertx vertx, ThreadContext context, IRubyObject app, JsonObject config) throws IOException {
46
43
  this.app = app;
47
- this.ssl = ssl;
44
+ this.ssl = config.getBoolean("ssl");
45
+ this.hideErrorStack = config.getBoolean("hide_error_stack", false);
48
46
  this.vertx = vertx;
49
47
  this.runtime = context.runtime;
50
- this.rackVersion = RubyArray.newArrayLight(runtime, RubyFixnum.one(runtime), RubyFixnum.four(runtime));
51
48
  // Memorize the ruby classes
52
49
  this.rackIOInputClass = (RubyClass) runtime.getClassFromPath("Jubilee::IORackInput");
53
50
  this.httpServerResponseClass = (RubyClass) runtime.getClassFromPath("Jubilee::HttpServerResponse");
54
- this.nullio = new RubyNullIO(runtime, (RubyClass) runtime.getClassFromPath("Jubilee::NullIO"));
55
51
 
56
52
  this.rackEnv = new RackEnvironment(runtime);
57
53
  }
@@ -64,23 +60,23 @@ public class RackApplication {
64
60
  // it set the empty content flag when passing the header
65
61
  // if ((te != null && te.equals("chunked")) ||
66
62
  // ((contentLength = request.headers().get(Const.Vertx.CONTENT_LENGTH)) != null && !contentLength.equals("0"))) {
67
- final ByteBuf bodyBuf = Unpooled.buffer(0, Integer.MAX_VALUE);
68
- final AtomicBoolean eof = new AtomicBoolean(false);
69
- input = new RubyIORackInput(runtime, rackIOInputClass, request, bodyBuf, eof);
63
+ final ByteBuf bodyBuf = Unpooled.buffer(0, Integer.MAX_VALUE);
64
+ final AtomicBoolean eof = new AtomicBoolean(false);
65
+ input = new RubyIORackInput(runtime, rackIOInputClass, request, bodyBuf, eof);
70
66
 
71
- request.dataHandler(new Handler<Buffer>() {
72
- @Override
73
- public void handle(Buffer buffer) {
74
- bodyBuf.writeBytes(buffer.getByteBuf());
75
- }
76
- });
67
+ request.dataHandler(new Handler<Buffer>() {
68
+ @Override
69
+ public void handle(Buffer buffer) {
70
+ bodyBuf.writeBytes(buffer.getByteBuf());
71
+ }
72
+ });
77
73
 
78
- request.endHandler(new VoidHandler() {
79
- @Override
80
- protected void handle() {
81
- eof.set(true);
82
- }
83
- });
74
+ request.endHandler(new VoidHandler() {
75
+ @Override
76
+ protected void handle() {
77
+ eof.set(true);
78
+ }
79
+ });
84
80
  request.exceptionHandler(new Handler<Throwable>() {
85
81
  @Override
86
82
  public void handle(Throwable ignore) {
@@ -94,21 +90,28 @@ public class RackApplication {
94
90
  @Override
95
91
  public void run() {
96
92
  try {
97
- // This is a different context, do NOT replace runtime.getCurrentContext()
98
- IRubyObject result = app.callMethod(runtime.getCurrentContext(), "call", rackEnv.getEnv(request, input, ssl));
93
+ // This is a different context, do NOT replace runtime.getCurrentContext()
94
+ IRubyObject result = app.callMethod(runtime.getCurrentContext(), "call", rackEnv.getEnv(request, input, ssl));
95
+ if (request.isHijacked()) {
96
+ // It's the hijacker's response to close the socket.
97
+ return;
98
+ }
99
99
  RackResponse response = (RackResponse) JavaEmbedUtils.rubyToJava(runtime, result, RackResponse.class);
100
100
  RubyHttpServerResponse resp = new RubyHttpServerResponse(runtime,
101
- httpServerResponseClass,
102
- request.response());
101
+ httpServerResponseClass, request);
103
102
  response.respond(resp);
104
103
  } catch (Exception e) {
105
- request.response().setStatusCode(500);
106
- String message = "Jubilee caught this error: " + e.getMessage() + "\n";
107
- StringWriter stringWriter = new StringWriter();
108
- PrintWriter printWriter = new PrintWriter(stringWriter);
109
- e.printStackTrace(printWriter);
110
- request.response().end(message + stringWriter.toString());
111
- e.printStackTrace(runtime.getErrorStream());
104
+ request.response().setStatusCode(500);
105
+ String message = "Jubilee caught this error: " + e.getMessage() + "\n";
106
+ StringWriter stringWriter = new StringWriter();
107
+ PrintWriter printWriter = new PrintWriter(stringWriter);
108
+ e.printStackTrace(printWriter);
109
+ if (hideErrorStack) {
110
+ request.response().end("Internal error.");
111
+ } else {
112
+ request.response().end(message + stringWriter.toString());
113
+ }
114
+ e.printStackTrace(runtime.getErrorStream());
112
115
  }
113
116
  }
114
117
  };
@@ -1,17 +1,14 @@
1
1
  package org.jruby.jubilee;
2
2
 
3
3
  import io.netty.handler.codec.http.HttpHeaders;
4
- import org.jruby.Ruby;
5
- import org.jruby.RubyArray;
6
- import org.jruby.RubyFixnum;
7
- import org.jruby.RubyHash;
8
- import org.jruby.RubyIO;
9
- import org.jruby.RubyString;
10
-
4
+ import org.jruby.*;
11
5
  import org.jruby.jubilee.utils.RubyHelper;
6
+ import org.jruby.runtime.*;
7
+ import org.jruby.runtime.builtin.IRubyObject;
12
8
  import org.vertx.java.core.MultiMap;
13
9
  import org.vertx.java.core.http.HttpServerRequest;
14
10
  import org.vertx.java.core.http.HttpVersion;
11
+ import org.vertx.java.core.net.NetSocket;
15
12
 
16
13
  import java.io.IOException;
17
14
  import java.net.InetSocketAddress;
@@ -27,12 +24,14 @@ public class RackEnvironment {
27
24
  PATH_INFO, QUERY_STRING, SERVER_NAME, SERVER_PORT,
28
25
  CONTENT_TYPE, REQUEST_URI, REMOTE_ADDR, URL_SCHEME,
29
26
  VERSION, MULTITHREAD, MULTIPROCESS, RUN_ONCE, CONTENT_LENGTH,
30
- HTTPS, HTTP_VERSION
27
+ HTTPS, HTTP_VERSION, HIJACK_P, HIJACK//, HIJACK_IO
31
28
  }
29
+
32
30
  static final int NUM_RACK_KEYS = RACK_KEY.values().length;
33
31
 
34
32
  public RackEnvironment(final Ruby runtime) throws IOException {
35
33
  this.runtime = runtime;
34
+ this.netSocketClass = (RubyClass) runtime.getClassFromPath("Jubilee::NetSocket");
36
35
  rackVersion = RubyArray.newArray(runtime, RubyFixnum.one(runtime), RubyFixnum.four(runtime));
37
36
  errors = new RubyIO(runtime, runtime.getErr());
38
37
  errors.setAutoclose(false);
@@ -58,6 +57,10 @@ public class RackEnvironment {
58
57
  putRack("rack.multithread", RACK_KEY.MULTITHREAD);
59
58
  putRack("rack.multiprocess", RACK_KEY.MULTIPROCESS);
60
59
  putRack("rack.run_once", RACK_KEY.RUN_ONCE);
60
+ putRack("rack.hijack?", RACK_KEY.HIJACK_P);
61
+ putRack("rack.hijack", RACK_KEY.HIJACK);
62
+ // putRack("rack.hijack_io", RACK_KEY.HIJACK_IO); Don't have to be lazy, since once rack.hijack is called, the io
63
+ // object has to be required by the caller.
61
64
  putRack("CONTENT_LENGTH", RACK_KEY.CONTENT_LENGTH);
62
65
  putRack("HTTPS", RACK_KEY.HTTPS);
63
66
  }
@@ -90,12 +93,17 @@ public class RackEnvironment {
90
93
  env.lazyPut(RACK_KEY.CONTENT_TYPE, headers.get(HttpHeaders.Names.CONTENT_TYPE), true);
91
94
  env.lazyPut(RACK_KEY.REQUEST_URI, request.uri(), false);
92
95
  env.lazyPut(RACK_KEY.REMOTE_ADDR, getRemoteAddr(request), true);
93
- env.lazyPut(RACK_KEY.URL_SCHEME, isSSL? Const.HTTPS : Const.HTTP, true);
96
+ env.lazyPut(RACK_KEY.URL_SCHEME, isSSL ? Const.HTTPS : Const.HTTP, true);
94
97
  env.lazyPut(RACK_KEY.VERSION, rackVersion, false);
95
98
  env.lazyPut(RACK_KEY.MULTITHREAD, runtime.getTrue(), false);
96
99
  env.lazyPut(RACK_KEY.MULTIPROCESS, runtime.getFalse(), false);
97
100
  env.lazyPut(RACK_KEY.RUN_ONCE, runtime.getFalse(), false);
98
101
 
102
+ // Hijack handling
103
+ env.lazyPut(RACK_KEY.HIJACK_P, runtime.getTrue(), false);
104
+ env.lazyPut(RACK_KEY.HIJACK, hijackProc(env, request), false);
105
+
106
+
99
107
  final int contentLength = getContentLength(headers);
100
108
  if (contentLength >= 0) {
101
109
  env.lazyPut(RACK_KEY.CONTENT_LENGTH, contentLength + "", true);
@@ -108,24 +116,49 @@ public class RackEnvironment {
108
116
  return env;
109
117
  }
110
118
 
119
+ private IRubyObject hijackProc(final RackEnvironmentHash env, final HttpServerRequest req) {
120
+ CompiledBlockCallback19 callback = new CompiledBlockCallback19() {
121
+ @Override
122
+ public IRubyObject call(ThreadContext context, IRubyObject self, IRubyObject[] args, Block block) {
123
+ RubyNetSocket rubyNetSocket = new RubyNetSocket(context.runtime, netSocketClass, req.netSocket());
124
+ env.put("rack.hijack_io", rubyNetSocket);
125
+ return rubyNetSocket;
126
+ }
127
+
128
+ @Override
129
+ public String getFile() {
130
+ return null;
131
+ }
132
+
133
+ @Override
134
+ public int getLine() {
135
+ return 0;
136
+ }
137
+ };
138
+ BlockBody body = CompiledBlockLight19.newCompiledBlockLight(Arity.NO_ARGUMENTS, runtime.getStaticScopeFactory().getDummyScope(), callback, false, 0, new String[]{});
139
+ Block b = new Block(body, runtime.newBinding().getBinding());
140
+
141
+ return RubyProc.newProc(runtime, b, Block.Type.LAMBDA);
142
+ }
143
+
111
144
  public String[] getHostInfo(String host) {
112
- String[] hostInfo;
113
- if (host != null) {
114
- int colon = host.indexOf(":");
115
- if (colon > 0)
116
- hostInfo = new String[]{host.substring(0, colon), host.substring(colon + 1)};
117
- else
118
- hostInfo = new String[]{host, Const.PORT_80};
119
-
120
- } else {
121
- hostInfo = new String[]{Const.LOCALHOST, Const.PORT_80};
122
- }
123
- return hostInfo;
145
+ String[] hostInfo;
146
+ if (host != null) {
147
+ int colon = host.indexOf(":");
148
+ if (colon > 0)
149
+ hostInfo = new String[]{host.substring(0, colon), host.substring(colon + 1)};
150
+ else
151
+ hostInfo = new String[]{host, Const.PORT_80};
152
+
153
+ } else {
154
+ hostInfo = new String[]{Const.LOCALHOST, Const.PORT_80};
155
+ }
156
+ return hostInfo;
124
157
  }
125
158
 
126
159
  private static String getRemoteAddr(final HttpServerRequest request) {
127
160
  InetSocketAddress sourceAddress = request.remoteAddress();
128
- if(sourceAddress == null) {
161
+ if (sourceAddress == null) {
129
162
  return "";
130
163
  }
131
164
  return sourceAddress.getHostString();
@@ -147,4 +180,5 @@ public class RackEnvironment {
147
180
  private final RubyArray rackVersion;
148
181
  private final RubyIO errors;
149
182
  private final Map<RubyString, RACK_KEY> rackKeyMap = new HashMap<>();
150
- }
183
+ private final RubyClass netSocketClass;
184
+ }
@@ -1,16 +1,11 @@
1
1
  package org.jruby.jubilee;
2
2
 
3
3
  import io.netty.handler.codec.http.HttpHeaders;
4
- import org.jruby.Ruby;
5
- import org.jruby.RubyArray;
6
- import org.jruby.RubyBoolean;
7
- import org.jruby.RubyFixnum;
8
- import org.jruby.RubyHash;
9
- import org.jruby.RubyString;
4
+ import org.jruby.*;
5
+ import org.jruby.jubilee.utils.RubyHelper;
10
6
  import org.jruby.runtime.Block;
11
7
  import org.jruby.runtime.ThreadContext;
12
8
  import org.jruby.runtime.builtin.IRubyObject;
13
- import org.jruby.jubilee.utils.RubyHelper;
14
9
  import org.vertx.java.core.MultiMap;
15
10
 
16
11
  import java.util.HashMap;
@@ -38,7 +33,7 @@ public class RackEnvironmentHash extends RubyHash {
38
33
  private synchronized void fillKey(final IRubyObject rubyKey) {
39
34
  if (!filledEntireHash) {
40
35
  if (rubyKey instanceof RubyString && !containsKey(rubyKey)) {
41
- if (! filledHeaderKeyMap) populateHeaderKeyMap();
36
+ if (!filledHeaderKeyMap) populateHeaderKeyMap();
42
37
  byte[] keyBytes = ((RubyString) rubyKey).getBytes();
43
38
  if (keyBytes.length > 5 && keyBytes[0] == 'H'
44
39
  && keyBytes[1] == 'T' && keyBytes[2] == 'T'
@@ -51,6 +46,7 @@ public class RackEnvironmentHash extends RubyHash {
51
46
  }
52
47
  }
53
48
  }
49
+
54
50
  private synchronized void fillEntireHash() {
55
51
  if (!filledEntireHash) {
56
52
  for (RubyString key : rackKeyMap.keySet()) {
@@ -65,6 +61,7 @@ public class RackEnvironmentHash extends RubyHash {
65
61
  filledEntireHash = true;
66
62
  }
67
63
  }
64
+
68
65
  private synchronized void fillRackKey(final RubyString key) {
69
66
  RackEnvironment.RACK_KEY rackKey = rackKeyMap.get(key);
70
67
  if (rackKey != null) {
@@ -83,7 +80,7 @@ public class RackEnvironmentHash extends RubyHash {
83
80
  }
84
81
  }
85
82
 
86
- private synchronized void populateHeaderKeyMap() {
83
+ private synchronized void populateHeaderKeyMap() {
87
84
  for (String key : headers.names()) {
88
85
  byte[] rubyKeyBytes = rackHeaderNameToBytes(key);
89
86
  RubyString rubyKey = RubyHelper.toUsAsciiRubyString(getRuntime(), rubyKeyBytes);
@@ -95,10 +92,12 @@ public class RackEnvironmentHash extends RubyHash {
95
92
  private void putHeaderKey(RubyString rubyKey, String key) {
96
93
  this.headerKeyMap.put(rubyKey, key);
97
94
  }
95
+
98
96
  private synchronized void fillHeaderKey(final RubyString rubyKey) {
99
97
  String headerKey = this.headerKeyMap.get(rubyKey);
100
98
  if (headerKey != null) fillHeaderKey(rubyKey, headerKey);
101
99
  }
100
+
102
101
  private synchronized void fillHeaderKey(final RubyString rubyKey, String key) {
103
102
  // RACK spec says not to create HTTP_CONTENT_TYPE or HTTP_CONTENT_LENGTH headers
104
103
  if (!key.equals(HttpHeaders.Names.CONTENT_TYPE) && !key.equals(HttpHeaders.Names.CONTENT_LENGTH)) {
@@ -152,7 +151,6 @@ public class RackEnvironmentHash extends RubyHash {
152
151
  private boolean filledHeaderKeyMap = false;
153
152
 
154
153
 
155
-
156
154
  //
157
155
  // Overridden RubyHash methods that operate on individual keys
158
156
  //
@@ -161,26 +159,31 @@ public class RackEnvironmentHash extends RubyHash {
161
159
  fillKey(key);
162
160
  return super.op_aref(context, key);
163
161
  }
162
+
164
163
  @Override
165
164
  public IRubyObject fetch(ThreadContext context, IRubyObject key, Block block) {
166
165
  fillKey(key);
167
166
  return super.fetch(context, key, block);
168
167
  }
168
+
169
169
  @Override
170
170
  public IRubyObject fetch(ThreadContext context, IRubyObject key, IRubyObject _default, Block block) {
171
171
  fillKey(key);
172
- return super.fetch(context, key ,_default, block);
172
+ return super.fetch(context, key, _default, block);
173
173
  }
174
+
174
175
  @Override
175
176
  public RubyBoolean has_key_p(IRubyObject key) {
176
177
  fillKey(key);
177
178
  return super.has_key_p(key);
178
179
  }
180
+
179
181
  @Override
180
182
  public IRubyObject op_aset(ThreadContext context, IRubyObject key, IRubyObject value) {
181
183
  fillKey(key);
182
184
  return super.op_aset(context, key, value);
183
185
  }
186
+
184
187
  @Override
185
188
  public IRubyObject delete(ThreadContext context, IRubyObject key, Block block) {
186
189
  fillKey(key);
@@ -196,251 +199,301 @@ public class RackEnvironmentHash extends RubyHash {
196
199
  fillEntireHash();
197
200
  return super.inspect(context);
198
201
  }
202
+
199
203
  @Override
200
204
  public IRubyObject inspect19(ThreadContext context) {
201
205
  fillEntireHash();
202
206
  return super.inspect19(context);
203
207
  }
208
+
204
209
  @Override
205
210
  public RubyFixnum rb_size() {
206
211
  fillEntireHash();
207
212
  return super.rb_size();
208
213
  }
214
+
209
215
  @Override
210
216
  public RubyBoolean empty_p() {
211
217
  fillEntireHash();
212
218
  return super.empty_p();
213
219
  }
220
+
214
221
  @Override
215
222
  public RubyArray to_a() {
216
223
  fillEntireHash();
217
224
  return super.to_a();
218
225
  }
226
+
219
227
  @Override
220
228
  public IRubyObject to_s(ThreadContext context) {
221
229
  fillEntireHash();
222
230
  return super.to_s(context);
223
231
  }
232
+
224
233
  @Override
225
234
  public IRubyObject to_s19(ThreadContext context) {
226
235
  fillEntireHash();
227
236
  return super.to_s19(context);
228
237
  }
238
+
229
239
  @Override
230
240
  public RubyHash rehash() {
231
241
  fillEntireHash();
232
242
  return super.rehash();
233
243
  }
244
+
234
245
  @Override
235
246
  public IRubyObject op_equal(final ThreadContext context, IRubyObject other) {
236
247
  fillEntireHash();
237
248
  return super.op_equal(context, other);
238
249
  }
250
+
239
251
  @Override
240
252
  public IRubyObject op_eql19(final ThreadContext context, IRubyObject other) {
241
253
  fillEntireHash();
242
254
  return super.op_eql19(context, other);
243
255
  }
256
+
244
257
  @Override
245
258
  public RubyFixnum hash() {
246
259
  fillEntireHash();
247
260
  return super.hash();
248
261
  }
262
+
249
263
  @Override
250
264
  public RubyFixnum hash19() {
251
265
  fillEntireHash();
252
266
  return super.hash19();
253
267
  }
268
+
254
269
  @Override
255
270
  public IRubyObject fetch(ThreadContext context, IRubyObject[] args, Block block) {
256
271
  fillEntireHash();
257
272
  return super.fetch(context, args, block);
258
273
  }
274
+
259
275
  @Override
260
276
  public RubyBoolean has_value_p(ThreadContext context, IRubyObject expected) {
261
277
  fillEntireHash();
262
278
  return super.has_value_p(context, expected);
263
279
  }
280
+
264
281
  @Override
265
282
  public IRubyObject each(final ThreadContext context, final Block block) {
266
283
  fillEntireHash();
267
284
  return super.each(context, block);
268
285
  }
286
+
269
287
  @Override
270
288
  public IRubyObject each19(final ThreadContext context, final Block block) {
271
289
  fillEntireHash();
272
290
  return super.each19(context, block);
273
291
  }
292
+
274
293
  @Override
275
294
  public IRubyObject each_value(final ThreadContext context, final Block block) {
276
295
  fillEntireHash();
277
296
  return super.each_value(context, block);
278
297
  }
298
+
279
299
  @Override
280
300
  public IRubyObject each_key(final ThreadContext context, final Block block) {
281
301
  fillEntireHash();
282
302
  return super.each_key(context, block);
283
303
  }
304
+
284
305
  @Override
285
306
  public IRubyObject select_bang(final ThreadContext context, final Block block) {
286
307
  fillEntireHash();
287
308
  return super.select_bang(context, block);
288
309
  }
310
+
289
311
  @Override
290
312
  public IRubyObject keep_if(final ThreadContext context, final Block block) {
291
313
  fillEntireHash();
292
314
  return super.keep_if(context, block);
293
315
  }
316
+
294
317
  @Override
295
318
  public IRubyObject sort(ThreadContext context, Block block) {
296
319
  fillEntireHash();
297
320
  return super.sort(context, block);
298
321
  }
322
+
299
323
  @Override
300
324
  public IRubyObject index(ThreadContext context, IRubyObject expected) {
301
325
  fillEntireHash();
302
326
  return super.index(context, expected);
303
327
  }
328
+
304
329
  @Override
305
330
  public IRubyObject index19(ThreadContext context, IRubyObject expected) {
306
331
  fillEntireHash();
307
332
  return super.index19(context, expected);
308
333
  }
334
+
309
335
  @Override
310
336
  public IRubyObject key(ThreadContext context, IRubyObject expected) {
311
337
  fillEntireHash();
312
338
  return super.key(context, expected);
313
339
  }
340
+
314
341
  @Override
315
342
  public RubyArray indices(ThreadContext context, IRubyObject[] indices) {
316
343
  fillEntireHash();
317
344
  return super.indices(context, indices);
318
345
  }
346
+
319
347
  @Override
320
348
  public RubyArray keys() {
321
349
  fillEntireHash();
322
350
  return super.keys();
323
351
  }
352
+
324
353
  @Override
325
354
  public RubyArray rb_values() {
326
355
  fillEntireHash();
327
356
  return super.rb_values();
328
357
  }
358
+
329
359
  @Override
330
360
  public IRubyObject shift(ThreadContext context) {
331
361
  fillEntireHash();
332
362
  return super.shift(context);
333
363
  }
364
+
334
365
  @Override
335
366
  public IRubyObject select(final ThreadContext context, final Block block) {
336
367
  fillEntireHash();
337
368
  return super.select(context, block);
338
369
  }
370
+
339
371
  @Override
340
372
  public IRubyObject select19(final ThreadContext context, final Block block) {
341
373
  fillEntireHash();
342
374
  return super.select19(context, block);
343
375
  }
376
+
344
377
  @Override
345
378
  public IRubyObject delete_if(final ThreadContext context, final Block block) {
346
379
  fillEntireHash();
347
380
  return super.delete_if(context, block);
348
381
  }
382
+
349
383
  @Override
350
384
  public IRubyObject reject(final ThreadContext context, final Block block) {
351
385
  fillEntireHash();
352
386
  return super.reject(context, block);
353
387
  }
388
+
354
389
  @Override
355
390
  public IRubyObject reject_bang(final ThreadContext context, final Block block) {
356
391
  fillEntireHash();
357
392
  return super.reject_bang(context, block);
358
393
  }
394
+
359
395
  @Override
360
396
  public RubyHash rb_clear() {
361
397
  fillEntireHash();
362
398
  return super.rb_clear();
363
399
  }
400
+
364
401
  @Override
365
402
  public RubyHash invert(final ThreadContext context) {
366
403
  fillEntireHash();
367
404
  return super.invert(context);
368
405
  }
406
+
369
407
  @Override
370
408
  public RubyHash merge_bang(final ThreadContext context, final IRubyObject other, final Block block) {
371
409
  fillEntireHash();
372
410
  return super.merge_bang(context, other, block);
373
411
  }
412
+
374
413
  @Override
375
414
  public RubyHash merge_bang19(final ThreadContext context, final IRubyObject other, final Block block) {
376
415
  fillEntireHash();
377
416
  return super.merge_bang19(context, other, block);
378
417
  }
418
+
379
419
  @Override
380
420
  public RubyHash merge(ThreadContext context, IRubyObject other, Block block) {
381
421
  fillEntireHash();
382
422
  return super.merge(context, other, block);
383
423
  }
424
+
384
425
  @Override
385
426
  public RubyHash initialize_copy(ThreadContext context, IRubyObject other) {
386
427
  fillEntireHash();
387
428
  return super.initialize_copy(context, other);
388
429
  }
430
+
389
431
  @Override
390
432
  public RubyHash initialize_copy19(ThreadContext context, IRubyObject other) {
391
433
  fillEntireHash();
392
434
  return super.initialize_copy19(context, other);
393
435
  }
436
+
394
437
  @Override
395
438
  public RubyHash replace(final ThreadContext context, IRubyObject other) {
396
439
  fillEntireHash();
397
440
  return super.replace(context, other);
398
441
  }
442
+
399
443
  @Override
400
444
  public RubyHash replace19(final ThreadContext context, IRubyObject other) {
401
445
  fillEntireHash();
402
446
  return super.replace19(context, other);
403
447
  }
448
+
404
449
  @Override
405
450
  public RubyArray values_at(ThreadContext context, IRubyObject[] args) {
406
451
  fillEntireHash();
407
452
  return super.values_at(context, args);
408
453
  }
454
+
409
455
  @Override
410
456
  public IRubyObject assoc(final ThreadContext context, final IRubyObject obj) {
411
457
  fillEntireHash();
412
458
  return super.assoc(context, obj);
413
459
  }
460
+
414
461
  @Override
415
462
  public IRubyObject rassoc(final ThreadContext context, final IRubyObject obj) {
416
463
  fillEntireHash();
417
464
  return super.rassoc(context, obj);
418
465
  }
466
+
419
467
  @Override
420
468
  public IRubyObject flatten(ThreadContext context) {
421
469
  fillEntireHash();
422
470
  return super.flatten(context);
423
471
  }
472
+
424
473
  @Override
425
474
  public IRubyObject flatten(ThreadContext context, IRubyObject level) {
426
475
  fillEntireHash();
427
476
  return super.flatten(context, level);
428
477
  }
478
+
429
479
  @Override
430
480
  public IRubyObject getCompareByIdentity(ThreadContext context) {
431
481
  fillEntireHash();
432
482
  return super.getCompareByIdentity(context);
433
483
  }
484
+
434
485
  @Override
435
486
  public IRubyObject getCompareByIdentity_p(ThreadContext context) {
436
487
  fillEntireHash();
437
488
  return super.getCompareByIdentity_p(context);
438
489
  }
490
+
439
491
  @Override
440
492
  public IRubyObject dup(ThreadContext context) {
441
493
  fillEntireHash();
442
494
  return super.dup(context);
443
495
  }
496
+
444
497
  @Override
445
498
  public IRubyObject rbClone(ThreadContext context) {
446
499
  fillEntireHash();