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.
- checksums.yaml +4 -4
- data/.travis.yml +2 -2
- data/CHANGELOG +9 -0
- data/README.md +12 -7
- data/jars/vertx-core-2.1.1.jar +0 -0
- data/java/src/jubilee/JubileeService.java +3 -3
- data/java/src/org/jruby/jubilee/Const.java +1 -1
- data/java/src/org/jruby/jubilee/JubileeVerticle.java +29 -4
- data/java/src/org/jruby/jubilee/RackApplication.java +38 -35
- data/java/src/org/jruby/jubilee/RackEnvironment.java +57 -23
- data/java/src/org/jruby/jubilee/RackEnvironmentHash.java +64 -11
- data/java/src/org/jruby/jubilee/RackInput.java +13 -10
- data/java/src/org/jruby/jubilee/RubyCallable.java +52 -0
- data/java/src/org/jruby/jubilee/RubyChannel.java +89 -0
- data/java/src/org/jruby/jubilee/RubyHttpServerResponse.java +72 -60
- data/java/src/org/jruby/jubilee/RubyNetSocket.java +169 -0
- data/java/src/org/jruby/jubilee/RubyPlatformManager.java +129 -113
- data/java/src/org/jruby/jubilee/impl/RubyIORackInput.java +9 -9
- data/java/src/org/jruby/jubilee/impl/RubyNullIO.java +1 -1
- data/java/src/org/jruby/jubilee/utils/RubyHelper.java +0 -6
- data/java/src/org/jruby/jubilee/vertx/JubileeVertx.java +12 -11
- data/jubilee.gemspec +43 -20
- data/lib/jubilee.rb +0 -1
- data/lib/jubilee/cli.rb +5 -3
- data/lib/jubilee/configuration.rb +2 -7
- data/lib/jubilee/const.rb +30 -28
- data/lib/jubilee/response.rb +40 -5
- data/lib/jubilee/server.rb +0 -3
- data/lib/jubilee/version.rb +1 -1
- data/spec/apps/rails4/basic/Gemfile +0 -2
- data/spec/apps/rails4/basic/Gemfile.lock +0 -7
- data/spec/integration/basic_rack_spec.rb +4 -3
- data/spec/integration/basic_rails4_spec.rb +4 -3
- data/spec/integration/basic_sinatra_spec.rb +4 -4
- data/spec/spec_helper.rb +1 -0
- data/test/{config → apps}/app.rb +0 -0
- data/test/apps/checker.ru +5 -10
- data/test/apps/chunked.ru +3 -0
- data/test/{config → apps}/config.ru +0 -0
- data/test/apps/content_length.ru +3 -0
- data/test/apps/hex.ru +4 -0
- data/test/apps/hijack.ru +7 -0
- data/test/apps/hijack2.ru +7 -0
- data/test/apps/huge.ru +4 -0
- data/test/apps/method_override.ru +1 -1
- data/test/apps/overwrite_check.ru +3 -2
- data/test/apps/persistent.rb +14 -0
- data/test/apps/persistent.ru +3 -0
- data/test/apps/rack_input.ru +5 -0
- data/test/apps/self_chunked.ru +6 -0
- data/test/apps/sha1.ru +2 -0
- data/test/apps/simple.ru +10 -1
- data/test/jubilee/test_cli.rb +1 -1
- data/test/jubilee/test_configuration.rb +1 -3
- data/test/jubilee/test_hijack.rb +27 -0
- data/test/jubilee/test_persistent.rb +208 -0
- data/test/jubilee/test_rack_server.rb +29 -68
- data/test/jubilee/test_server.rb +49 -15
- data/test/jubilee/test_upload.rb +13 -60
- data/test/test_helper.rb +2 -2
- metadata +19 -9
- data/java/src/org/jruby/jubilee/RubyServer.java +0 -159
- data/lib/jubilee/jubilee.jar +0 -0
- data/lib/rack/chunked.rb +0 -38
- data/test/config/app.ru +0 -3
- data/test/jubilee/test_response.rb +0 -270
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 865bcd4759e0b52c639ae642a749f1885da1025c
|
4
|
+
data.tar.gz: 7a13f948d9e4a4a75ee039b1765b74ea9333c3b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba572a6a03c0c8c593d6f183375c8aa42fa69c10fe5c41b9d50fd9f0d7360f7ad3a71201ee7dd695a4ee5c1ddfac98b77d5ed3727cec2e68c7e4a8d63c1d3757
|
7
|
+
data.tar.gz: 7e209e4e8a9d0e24599078aa550b2a74c57e1a4f7a8d1961d9fcb67faf1c403301d29436dcfb0c582402a69fc6bff6883c50a6e61482f01f6f947e23efa3a2ae
|
data/.travis.yml
CHANGED
data/CHANGELOG
CHANGED
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
|
-
|
57
|
+
gem 'jubilee', '~> 2.0.0'
|
59
58
|
|
60
|
-
|
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
|
-
$
|
67
|
+
$ export JAVA_OPTS="-Xms1024m -Xmx2048m -XX:PermSize=512m -XX:MaxPermSize=512m"
|
63
68
|
|
64
|
-
|
69
|
+
If your OS memory is quite limited, please run jubilee with
|
65
70
|
|
66
|
-
$
|
71
|
+
$ jubilee -n 1
|
67
72
|
|
68
73
|
Event Bus
|
69
74
|
=========
|
data/jars/vertx-core-2.1.1.jar
CHANGED
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
|
-
|
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.
|
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,
|
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
|
-
|
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.
|
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,
|
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
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
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
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
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
|
-
|
98
|
-
|
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
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
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
|
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
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
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
|
5
|
-
import org.jruby.
|
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 (!
|
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
|
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
|
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();
|