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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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();