puma 5.0.0.beta1-java → 5.0.3-java
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.md +1188 -559
- data/README.md +15 -8
- data/bin/puma-wild +3 -9
- data/docs/architecture.md +3 -3
- data/docs/deployment.md +10 -7
- data/docs/jungle/README.md +0 -4
- data/docs/jungle/rc.d/puma +2 -2
- data/docs/nginx.md +1 -1
- data/docs/restart.md +46 -23
- data/docs/signals.md +7 -7
- data/docs/systemd.md +1 -1
- data/ext/puma_http11/ext_help.h +1 -1
- data/ext/puma_http11/http11_parser.c +3 -1
- data/ext/puma_http11/http11_parser.rl +3 -1
- data/ext/puma_http11/mini_ssl.c +53 -38
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +77 -18
- data/ext/puma_http11/puma_http11.c +22 -11
- data/lib/puma.rb +16 -0
- data/lib/puma/app/status.rb +47 -44
- data/lib/puma/binder.rb +40 -12
- data/lib/puma/client.rb +68 -82
- data/lib/puma/cluster.rb +30 -187
- data/lib/puma/cluster/worker.rb +170 -0
- data/lib/puma/cluster/worker_handle.rb +83 -0
- data/lib/puma/commonlogger.rb +2 -2
- data/lib/puma/configuration.rb +9 -7
- data/lib/puma/const.rb +2 -1
- data/lib/puma/control_cli.rb +2 -0
- data/lib/puma/detect.rb +9 -0
- data/lib/puma/dsl.rb +77 -39
- data/lib/puma/error_logger.rb +97 -0
- data/lib/puma/events.rb +37 -31
- data/lib/puma/launcher.rb +20 -10
- data/lib/puma/minissl.rb +55 -10
- data/lib/puma/minissl/context_builder.rb +0 -3
- data/lib/puma/puma_http11.jar +0 -0
- data/lib/puma/queue_close.rb +26 -0
- data/lib/puma/reactor.rb +77 -373
- data/lib/puma/request.rb +438 -0
- data/lib/puma/runner.rb +7 -19
- data/lib/puma/server.rb +229 -506
- data/lib/puma/single.rb +3 -2
- data/lib/puma/state_file.rb +1 -1
- data/lib/puma/thread_pool.rb +32 -5
- data/lib/puma/util.rb +12 -0
- metadata +12 -10
- data/docs/jungle/upstart/README.md +0 -61
- data/docs/jungle/upstart/puma-manager.conf +0 -31
- data/docs/jungle/upstart/puma.conf +0 -69
- data/lib/puma/accept_nonblock.rb +0 -29
@@ -0,0 +1,15 @@
|
|
1
|
+
package puma;
|
2
|
+
|
3
|
+
import java.io.IOException;
|
4
|
+
|
5
|
+
import org.jruby.Ruby;
|
6
|
+
import org.jruby.runtime.load.BasicLibraryService;
|
7
|
+
|
8
|
+
import org.jruby.puma.Http11;
|
9
|
+
|
10
|
+
public class PumaHttp11Service implements BasicLibraryService {
|
11
|
+
public boolean basicLoad(final Ruby runtime) throws IOException {
|
12
|
+
Http11.createHttp11(runtime);
|
13
|
+
return true;
|
14
|
+
}
|
15
|
+
}
|
@@ -22,6 +22,7 @@ import javax.net.ssl.SSLException;
|
|
22
22
|
import javax.net.ssl.SSLPeerUnverifiedException;
|
23
23
|
import javax.net.ssl.SSLSession;
|
24
24
|
import java.io.FileInputStream;
|
25
|
+
import java.io.InputStream;
|
25
26
|
import java.io.IOException;
|
26
27
|
import java.nio.Buffer;
|
27
28
|
import java.nio.ByteBuffer;
|
@@ -32,6 +33,8 @@ import java.security.NoSuchAlgorithmException;
|
|
32
33
|
import java.security.UnrecoverableKeyException;
|
33
34
|
import java.security.cert.CertificateEncodingException;
|
34
35
|
import java.security.cert.CertificateException;
|
36
|
+
import java.util.concurrent.ConcurrentHashMap;
|
37
|
+
import java.util.Map;
|
35
38
|
|
36
39
|
import static javax.net.ssl.SSLEngineResult.Status;
|
37
40
|
import static javax.net.ssl.SSLEngineResult.HandshakeStatus;
|
@@ -120,6 +123,8 @@ public class MiniSSL extends RubyObject {
|
|
120
123
|
}
|
121
124
|
|
122
125
|
private SSLEngine engine;
|
126
|
+
private boolean closed;
|
127
|
+
private boolean handshake;
|
123
128
|
private MiniSSLBuffer inboundNetData;
|
124
129
|
private MiniSSLBuffer outboundAppData;
|
125
130
|
private MiniSSLBuffer outboundNetData;
|
@@ -128,10 +133,39 @@ public class MiniSSL extends RubyObject {
|
|
128
133
|
super(runtime, klass);
|
129
134
|
}
|
130
135
|
|
136
|
+
private static Map<String, KeyManagerFactory> keyManagerFactoryMap = new ConcurrentHashMap<String, KeyManagerFactory>();
|
137
|
+
private static Map<String, TrustManagerFactory> trustManagerFactoryMap = new ConcurrentHashMap<String, TrustManagerFactory>();
|
138
|
+
|
131
139
|
@JRubyMethod(meta = true)
|
132
|
-
public static IRubyObject server(ThreadContext context, IRubyObject recv, IRubyObject miniSSLContext)
|
133
|
-
|
140
|
+
public static synchronized IRubyObject server(ThreadContext context, IRubyObject recv, IRubyObject miniSSLContext)
|
141
|
+
throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException {
|
142
|
+
// Create the KeyManagerFactory and TrustManagerFactory for this server
|
143
|
+
String keystoreFile = miniSSLContext.callMethod(context, "keystore").convertToString().asJavaString();
|
144
|
+
char[] password = miniSSLContext.callMethod(context, "keystore_pass").convertToString().asJavaString().toCharArray();
|
134
145
|
|
146
|
+
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
|
147
|
+
InputStream is = new FileInputStream(keystoreFile);
|
148
|
+
try {
|
149
|
+
ks.load(is, password);
|
150
|
+
} finally {
|
151
|
+
is.close();
|
152
|
+
}
|
153
|
+
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
|
154
|
+
kmf.init(ks, password);
|
155
|
+
keyManagerFactoryMap.put(keystoreFile, kmf);
|
156
|
+
|
157
|
+
KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
|
158
|
+
is = new FileInputStream(keystoreFile);
|
159
|
+
try {
|
160
|
+
ts.load(is, password);
|
161
|
+
} finally {
|
162
|
+
is.close();
|
163
|
+
}
|
164
|
+
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
|
165
|
+
tmf.init(ts);
|
166
|
+
trustManagerFactoryMap.put(keystoreFile, tmf);
|
167
|
+
|
168
|
+
RubyClass klass = (RubyClass) recv;
|
135
169
|
return klass.newInstance(context,
|
136
170
|
new IRubyObject[] { miniSSLContext },
|
137
171
|
Block.NULL_BLOCK);
|
@@ -139,24 +173,22 @@ public class MiniSSL extends RubyObject {
|
|
139
173
|
|
140
174
|
@JRubyMethod
|
141
175
|
public IRubyObject initialize(ThreadContext threadContext, IRubyObject miniSSLContext)
|
142
|
-
throws KeyStoreException,
|
176
|
+
throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
|
143
177
|
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
|
144
178
|
KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
|
145
179
|
|
146
|
-
char[] password = miniSSLContext.callMethod(threadContext, "keystore_pass").convertToString().asJavaString().toCharArray();
|
147
180
|
String keystoreFile = miniSSLContext.callMethod(threadContext, "keystore").convertToString().asJavaString();
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
|
155
|
-
tmf.init(ts);
|
181
|
+
KeyManagerFactory kmf = keyManagerFactoryMap.get(keystoreFile);
|
182
|
+
TrustManagerFactory tmf = trustManagerFactoryMap.get(keystoreFile);
|
183
|
+
if(kmf == null || tmf == null) {
|
184
|
+
throw new KeyStoreException("Could not find KeyManagerFactory/TrustManagerFactory for keystore: " + keystoreFile);
|
185
|
+
}
|
156
186
|
|
157
187
|
SSLContext sslCtx = SSLContext.getInstance("TLS");
|
158
188
|
|
159
189
|
sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
190
|
+
closed = false;
|
191
|
+
handshake = false;
|
160
192
|
engine = sslCtx.createSSLEngine();
|
161
193
|
|
162
194
|
String[] protocols;
|
@@ -173,7 +205,7 @@ public class MiniSSL extends RubyObject {
|
|
173
205
|
engine.setEnabledProtocols(protocols);
|
174
206
|
engine.setUseClientMode(false);
|
175
207
|
|
176
|
-
long verify_mode = miniSSLContext.callMethod(threadContext, "verify_mode").convertToInteger().getLongValue();
|
208
|
+
long verify_mode = miniSSLContext.callMethod(threadContext, "verify_mode").convertToInteger("to_i").getLongValue();
|
177
209
|
if ((verify_mode & 0x1) != 0) { // 'peer'
|
178
210
|
engine.setWantClientAuth(true);
|
179
211
|
}
|
@@ -240,14 +272,21 @@ public class MiniSSL extends RubyObject {
|
|
240
272
|
// need to wait for more data to come in before we retry
|
241
273
|
retryOp = false;
|
242
274
|
break;
|
275
|
+
case CLOSED:
|
276
|
+
closed = true;
|
277
|
+
retryOp = false;
|
278
|
+
break;
|
243
279
|
default:
|
244
|
-
// other
|
280
|
+
// other case is OK. We're done here.
|
245
281
|
retryOp = false;
|
246
282
|
}
|
283
|
+
if (res.getHandshakeStatus() == HandshakeStatus.FINISHED) {
|
284
|
+
handshake = true;
|
285
|
+
}
|
247
286
|
}
|
248
287
|
|
249
288
|
// after each op, run any delegated tasks if needed
|
250
|
-
if(
|
289
|
+
if(res.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
|
251
290
|
Runnable runnable;
|
252
291
|
while ((runnable = engine.getDelegatedTask()) != null) {
|
253
292
|
runnable.run();
|
@@ -271,13 +310,14 @@ public class MiniSSL extends RubyObject {
|
|
271
310
|
|
272
311
|
HandshakeStatus handshakeStatus = engine.getHandshakeStatus();
|
273
312
|
boolean done = false;
|
313
|
+
SSLEngineResult res = null;
|
274
314
|
while (!done) {
|
275
315
|
switch (handshakeStatus) {
|
276
316
|
case NEED_WRAP:
|
277
|
-
doOp(SSLOperation.WRAP, inboundAppData, outboundNetData);
|
317
|
+
res = doOp(SSLOperation.WRAP, inboundAppData, outboundNetData);
|
278
318
|
break;
|
279
319
|
case NEED_UNWRAP:
|
280
|
-
|
320
|
+
res = doOp(SSLOperation.UNWRAP, inboundNetData, inboundAppData);
|
281
321
|
if (res.getStatus() == Status.BUFFER_UNDERFLOW) {
|
282
322
|
// need more data before we can shake more hands
|
283
323
|
done = true;
|
@@ -286,7 +326,9 @@ public class MiniSSL extends RubyObject {
|
|
286
326
|
default:
|
287
327
|
done = true;
|
288
328
|
}
|
289
|
-
|
329
|
+
if (!done) {
|
330
|
+
handshakeStatus = res.getHandshakeStatus();
|
331
|
+
}
|
290
332
|
}
|
291
333
|
|
292
334
|
if (inboundNetData.hasRemaining()) {
|
@@ -360,4 +402,21 @@ public class MiniSSL extends RubyObject {
|
|
360
402
|
return getRuntime().getNil();
|
361
403
|
}
|
362
404
|
}
|
405
|
+
|
406
|
+
@JRubyMethod(name = "init?")
|
407
|
+
public IRubyObject isInit(ThreadContext context) {
|
408
|
+
return handshake ? getRuntime().getFalse() : getRuntime().getTrue();
|
409
|
+
}
|
410
|
+
|
411
|
+
@JRubyMethod
|
412
|
+
public IRubyObject shutdown() {
|
413
|
+
if (closed || engine.isInboundDone() && engine.isOutboundDone()) {
|
414
|
+
if (engine.isOutboundDone()) {
|
415
|
+
engine.closeOutbound();
|
416
|
+
}
|
417
|
+
return getRuntime().getTrue();
|
418
|
+
} else {
|
419
|
+
return getRuntime().getFalse();
|
420
|
+
}
|
421
|
+
}
|
363
422
|
}
|
@@ -54,7 +54,7 @@ DEF_MAX_LENGTH(FIELD_NAME, 256);
|
|
54
54
|
DEF_MAX_LENGTH(FIELD_VALUE, 80 * 1024);
|
55
55
|
DEF_MAX_LENGTH(REQUEST_URI, 1024 * 12);
|
56
56
|
DEF_MAX_LENGTH(FRAGMENT, 1024); /* Don't know if this length is specified somewhere or not */
|
57
|
-
DEF_MAX_LENGTH(REQUEST_PATH,
|
57
|
+
DEF_MAX_LENGTH(REQUEST_PATH, 8192);
|
58
58
|
DEF_MAX_LENGTH(QUERY_STRING, (1024 * 10));
|
59
59
|
DEF_MAX_LENGTH(HEADER, (1024 * (80 + 32)));
|
60
60
|
|
@@ -253,11 +253,18 @@ void HttpParser_free(void *data) {
|
|
253
253
|
}
|
254
254
|
}
|
255
255
|
|
256
|
-
void HttpParser_mark(
|
256
|
+
void HttpParser_mark(void *ptr) {
|
257
|
+
puma_parser *hp = ptr;
|
257
258
|
if(hp->request) rb_gc_mark(hp->request);
|
258
259
|
if(hp->body) rb_gc_mark(hp->body);
|
259
260
|
}
|
260
261
|
|
262
|
+
const rb_data_type_t HttpParser_data_type = {
|
263
|
+
"HttpParser",
|
264
|
+
{ HttpParser_mark, HttpParser_free, 0 },
|
265
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
266
|
+
};
|
267
|
+
|
261
268
|
VALUE HttpParser_alloc(VALUE klass)
|
262
269
|
{
|
263
270
|
puma_parser *hp = ALLOC_N(puma_parser, 1);
|
@@ -274,7 +281,7 @@ VALUE HttpParser_alloc(VALUE klass)
|
|
274
281
|
|
275
282
|
puma_parser_init(hp);
|
276
283
|
|
277
|
-
return
|
284
|
+
return TypedData_Wrap_Struct(klass, &HttpParser_data_type, hp);
|
278
285
|
}
|
279
286
|
|
280
287
|
/**
|
@@ -286,7 +293,7 @@ VALUE HttpParser_alloc(VALUE klass)
|
|
286
293
|
VALUE HttpParser_init(VALUE self)
|
287
294
|
{
|
288
295
|
puma_parser *http = NULL;
|
289
|
-
DATA_GET(self, puma_parser, http);
|
296
|
+
DATA_GET(self, puma_parser, &HttpParser_data_type, http);
|
290
297
|
puma_parser_init(http);
|
291
298
|
|
292
299
|
return self;
|
@@ -303,7 +310,7 @@ VALUE HttpParser_init(VALUE self)
|
|
303
310
|
VALUE HttpParser_reset(VALUE self)
|
304
311
|
{
|
305
312
|
puma_parser *http = NULL;
|
306
|
-
DATA_GET(self, puma_parser, http);
|
313
|
+
DATA_GET(self, puma_parser, &HttpParser_data_type, http);
|
307
314
|
puma_parser_init(http);
|
308
315
|
|
309
316
|
return Qnil;
|
@@ -320,7 +327,7 @@ VALUE HttpParser_reset(VALUE self)
|
|
320
327
|
VALUE HttpParser_finish(VALUE self)
|
321
328
|
{
|
322
329
|
puma_parser *http = NULL;
|
323
|
-
DATA_GET(self, puma_parser, http);
|
330
|
+
DATA_GET(self, puma_parser, &HttpParser_data_type, http);
|
324
331
|
puma_parser_finish(http);
|
325
332
|
|
326
333
|
return puma_parser_is_finished(http) ? Qtrue : Qfalse;
|
@@ -351,7 +358,7 @@ VALUE HttpParser_execute(VALUE self, VALUE req_hash, VALUE data, VALUE start)
|
|
351
358
|
char *dptr = NULL;
|
352
359
|
long dlen = 0;
|
353
360
|
|
354
|
-
DATA_GET(self, puma_parser, http);
|
361
|
+
DATA_GET(self, puma_parser, &HttpParser_data_type, http);
|
355
362
|
|
356
363
|
from = FIX2INT(start);
|
357
364
|
dptr = rb_extract_chars(data, &dlen);
|
@@ -385,7 +392,7 @@ VALUE HttpParser_execute(VALUE self, VALUE req_hash, VALUE data, VALUE start)
|
|
385
392
|
VALUE HttpParser_has_error(VALUE self)
|
386
393
|
{
|
387
394
|
puma_parser *http = NULL;
|
388
|
-
DATA_GET(self, puma_parser, http);
|
395
|
+
DATA_GET(self, puma_parser, &HttpParser_data_type, http);
|
389
396
|
|
390
397
|
return puma_parser_has_error(http) ? Qtrue : Qfalse;
|
391
398
|
}
|
@@ -400,7 +407,7 @@ VALUE HttpParser_has_error(VALUE self)
|
|
400
407
|
VALUE HttpParser_is_finished(VALUE self)
|
401
408
|
{
|
402
409
|
puma_parser *http = NULL;
|
403
|
-
DATA_GET(self, puma_parser, http);
|
410
|
+
DATA_GET(self, puma_parser, &HttpParser_data_type, http);
|
404
411
|
|
405
412
|
return puma_parser_is_finished(http) ? Qtrue : Qfalse;
|
406
413
|
}
|
@@ -416,7 +423,7 @@ VALUE HttpParser_is_finished(VALUE self)
|
|
416
423
|
VALUE HttpParser_nread(VALUE self)
|
417
424
|
{
|
418
425
|
puma_parser *http = NULL;
|
419
|
-
DATA_GET(self, puma_parser, http);
|
426
|
+
DATA_GET(self, puma_parser, &HttpParser_data_type, http);
|
420
427
|
|
421
428
|
return INT2FIX(http->nread);
|
422
429
|
}
|
@@ -429,12 +436,14 @@ VALUE HttpParser_nread(VALUE self)
|
|
429
436
|
*/
|
430
437
|
VALUE HttpParser_body(VALUE self) {
|
431
438
|
puma_parser *http = NULL;
|
432
|
-
DATA_GET(self, puma_parser, http);
|
439
|
+
DATA_GET(self, puma_parser, &HttpParser_data_type, http);
|
433
440
|
|
434
441
|
return http->body;
|
435
442
|
}
|
436
443
|
|
444
|
+
#ifdef HAVE_OPENSSL_BIO_H
|
437
445
|
void Init_mini_ssl(VALUE mod);
|
446
|
+
#endif
|
438
447
|
|
439
448
|
void Init_puma_http11()
|
440
449
|
{
|
@@ -463,5 +472,7 @@ void Init_puma_http11()
|
|
463
472
|
rb_define_method(cHttpParser, "body", HttpParser_body, 0);
|
464
473
|
init_common_fields();
|
465
474
|
|
475
|
+
#ifdef HAVE_OPENSSL_BIO_H
|
466
476
|
Init_mini_ssl(mPuma);
|
477
|
+
#endif
|
467
478
|
}
|
data/lib/puma.rb
CHANGED
@@ -10,19 +10,27 @@ require 'stringio'
|
|
10
10
|
|
11
11
|
require 'thread'
|
12
12
|
|
13
|
+
require 'puma/puma_http11'
|
14
|
+
require 'puma/detect'
|
15
|
+
|
13
16
|
module Puma
|
14
17
|
autoload :Const, 'puma/const'
|
15
18
|
autoload :Server, 'puma/server'
|
16
19
|
autoload :Launcher, 'puma/launcher'
|
17
20
|
|
21
|
+
# @!attribute [rw] stats_object=
|
18
22
|
def self.stats_object=(val)
|
19
23
|
@get_stats = val
|
20
24
|
end
|
21
25
|
|
26
|
+
# @!attribute [rw] stats_object
|
22
27
|
def self.stats
|
28
|
+
require 'json'
|
23
29
|
@get_stats.stats.to_json
|
24
30
|
end
|
25
31
|
|
32
|
+
# @!attribute [r] stats_hash
|
33
|
+
# @version 5.0.0
|
26
34
|
def self.stats_hash
|
27
35
|
@get_stats.stats
|
28
36
|
end
|
@@ -32,4 +40,12 @@ module Puma
|
|
32
40
|
return unless Thread.current.respond_to?(:name=)
|
33
41
|
Thread.current.name = "puma #{name}"
|
34
42
|
end
|
43
|
+
|
44
|
+
unless HAS_SSL
|
45
|
+
module MiniSSL
|
46
|
+
# this class is defined so that it exists when Puma is compiled
|
47
|
+
# without ssl support, as Server and Reactor use it in rescue statements.
|
48
|
+
class SSLError < StandardError ; end
|
49
|
+
end
|
50
|
+
end
|
35
51
|
end
|
data/lib/puma/app/status.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'json'
|
4
|
-
|
5
3
|
module Puma
|
6
4
|
module App
|
7
5
|
# Check out {#call}'s source code to see what actions this web application
|
@@ -9,67 +7,72 @@ module Puma
|
|
9
7
|
class Status
|
10
8
|
OK_STATUS = '{ "status": "ok" }'.freeze
|
11
9
|
|
12
|
-
|
13
|
-
|
10
|
+
# @param launcher [::Puma::Launcher]
|
11
|
+
# @param token [String, nil] the token used for authentication
|
12
|
+
#
|
13
|
+
def initialize(launcher, token = nil)
|
14
|
+
@launcher = launcher
|
14
15
|
@auth_token = token
|
15
16
|
end
|
16
17
|
|
18
|
+
# most commands call methods in `::Puma::Launcher` based on command in
|
19
|
+
# `env['PATH_INFO']`
|
17
20
|
def call(env)
|
18
21
|
unless authenticate(env)
|
19
22
|
return rack_response(403, 'Invalid auth token', 'text/plain')
|
20
23
|
end
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
rack_response(200, OK_STATUS)
|
25
|
+
if env['PATH_INFO'] =~ /\/(gc-stats|stats|thread-backtraces)$/
|
26
|
+
require 'json'
|
27
|
+
end
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
29
|
+
# resp_type is processed by following case statement, return
|
30
|
+
# is a number (status) or a string used as the body of a 200 response
|
31
|
+
resp_type =
|
32
|
+
case env['PATH_INFO'][/\/([^\/]+)$/, 1]
|
33
|
+
when 'stop'
|
34
|
+
@launcher.stop ; 200
|
30
35
|
|
31
|
-
|
32
|
-
|
33
|
-
rack_response(200, OK_STATUS)
|
36
|
+
when 'halt'
|
37
|
+
@launcher.halt ; 200
|
34
38
|
|
35
|
-
|
36
|
-
|
37
|
-
rack_response(404, '{ "error": "phased restart not available" }')
|
38
|
-
else
|
39
|
-
rack_response(200, OK_STATUS)
|
40
|
-
end
|
39
|
+
when 'restart'
|
40
|
+
@launcher.restart ; 200
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
rack_response(404, '{ "error": "reload_worker_directory not available" }')
|
45
|
-
else
|
46
|
-
rack_response(200, OK_STATUS)
|
47
|
-
end
|
42
|
+
when 'phased-restart'
|
43
|
+
@launcher.phased_restart ? 200 : 404
|
48
44
|
|
49
|
-
|
50
|
-
|
51
|
-
rack_response(200, OK_STATUS)
|
45
|
+
when 'reload-worker-directory'
|
46
|
+
@launcher.send(:reload_worker_directory) ? 200 : 404
|
52
47
|
|
53
|
-
|
54
|
-
|
48
|
+
when 'gc'
|
49
|
+
GC.start ; 200
|
55
50
|
|
56
|
-
|
57
|
-
|
51
|
+
when 'gc-stats'
|
52
|
+
GC.stat.to_json
|
58
53
|
|
59
|
-
|
60
|
-
|
61
|
-
@cli.thread_status do |name, backtrace|
|
62
|
-
backtraces << { name: name, backtrace: backtrace }
|
63
|
-
end
|
54
|
+
when 'stats'
|
55
|
+
@launcher.stats.to_json
|
64
56
|
|
65
|
-
|
57
|
+
when 'thread-backtraces'
|
58
|
+
backtraces = []
|
59
|
+
@launcher.thread_status do |name, backtrace|
|
60
|
+
backtraces << { name: name, backtrace: backtrace }
|
61
|
+
end
|
62
|
+
backtraces.to_json
|
66
63
|
|
67
|
-
|
68
|
-
|
69
|
-
|
64
|
+
else
|
65
|
+
return rack_response(404, "Unsupported action", 'text/plain')
|
66
|
+
end
|
70
67
|
|
71
|
-
|
72
|
-
|
68
|
+
case resp_type
|
69
|
+
when String
|
70
|
+
rack_response 200, resp_type
|
71
|
+
when 200
|
72
|
+
rack_response 200, OK_STATUS
|
73
|
+
when 404
|
74
|
+
str = env['PATH_INFO'][/\/(\S+)/, 1].tr '-', '_'
|
75
|
+
rack_response 404, "{ \"error\": \"#{str} not available\" }"
|
73
76
|
end
|
74
77
|
end
|
75
78
|
|