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.
- 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();
|