opal-up 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +0 -1
- data/ext/up_ext/up_ext.c +76 -44
- data/lib/up/bun/server.rb +10 -3
- data/lib/up/u_web_socket/server.rb +28 -11
- data/lib/up/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 46fd760653d3303f32429a4dfd767c4d93ac56817393785d7da35632ab2d4ad2
|
4
|
+
data.tar.gz: a809d96c97f31441dd51c8e5c87aeaee47059835718f62de3217b38348d7d111
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6cd09583959a4340bafda2c118a570df793884fc2813e2b93a251f26220e243910263093c3ff24ac8f9dcc337af5cf1c152f5c9a491e58a5dcc32d035ef5c545
|
7
|
+
data.tar.gz: 7e45708e9f770ea45dd463dd5bf39075d7d241fe73d0ea60d638e6d80369dec4ae16661b9187525b522440133fa0272df62ca1c982bb132737807c9e05dae6f3
|
data/README.md
CHANGED
@@ -99,7 +99,6 @@ When using secure sockets, the -a, -c and -k options must be provided
|
|
99
99
|
|
100
100
|
Up! implements the [Rack Spec as of Rack 3.0](https://github.com/rack/rack/blob/main/SPEC.rdoc) with the following differences:
|
101
101
|
- `rack.hijack` is not implemented, but `rack.upgrade` instead is, see "Websockets" below
|
102
|
-
- `rack.input` is currently still missing
|
103
102
|
- Tempfile support is currently incomplete, affecting a few keys in the Rack Env ('tempfile' missing in Opal).
|
104
103
|
- Some Rack modules/classes still have issues when run in Opal and may not work as expected
|
105
104
|
|
data/ext/up_ext/up_ext.c
CHANGED
@@ -37,6 +37,7 @@ static ID id_close;
|
|
37
37
|
static ID id_each;
|
38
38
|
static ID id_host;
|
39
39
|
static ID id_logger;
|
40
|
+
static ID id_new;
|
40
41
|
static ID id_on_close;
|
41
42
|
static ID id_on_drained;
|
42
43
|
static ID id_on_message;
|
@@ -122,6 +123,8 @@ typedef struct server_s {
|
|
122
123
|
VALUE port;
|
123
124
|
VALUE logger;
|
124
125
|
VALUE env_template;
|
126
|
+
VALUE body;
|
127
|
+
VALUE env;
|
125
128
|
int workers;
|
126
129
|
int member_id;
|
127
130
|
char secret[37];
|
@@ -283,6 +286,43 @@ typedef struct publish_data_s {
|
|
283
286
|
server_s *s;
|
284
287
|
} publish_data_s;
|
285
288
|
|
289
|
+
static void up_internal_call_app(server_s *s, uws_res_t *res, VALUE env) {
|
290
|
+
// call app
|
291
|
+
VALUE rres = rb_funcall(s->rapp, id_call, 1, env);
|
292
|
+
|
293
|
+
if (TYPE(rres) != T_ARRAY)
|
294
|
+
goto response_error;
|
295
|
+
|
296
|
+
// response status
|
297
|
+
VALUE rstatus = rb_ary_entry(rres, 0);
|
298
|
+
if (!up_internal_set_response_status(res, rstatus))
|
299
|
+
goto response_error;
|
300
|
+
|
301
|
+
// collect headers
|
302
|
+
VALUE rheaders = rb_ary_entry(rres, 1);
|
303
|
+
if (TYPE(rheaders) != T_HASH)
|
304
|
+
goto response_error;
|
305
|
+
rb_hash_foreach(rheaders, up_internal_res_header_handler, (VALUE)res);
|
306
|
+
|
307
|
+
// collect response body
|
308
|
+
VALUE rparts = rb_ary_entry(rres, 2);
|
309
|
+
up_internal_collect_response_body(res, rparts);
|
310
|
+
|
311
|
+
// end response
|
312
|
+
uws_res_end_without_body(USE_SSL, res, false);
|
313
|
+
|
314
|
+
// close resources if necessary
|
315
|
+
if (rb_respond_to(rparts, id_close))
|
316
|
+
rb_funcall(rparts, id_close, 0);
|
317
|
+
|
318
|
+
return;
|
319
|
+
response_error:
|
320
|
+
fprintf(stderr, "response error\n");
|
321
|
+
uws_res_end_without_body(USE_SSL, res, false);
|
322
|
+
}
|
323
|
+
|
324
|
+
static void up_internal_abort_data(uws_res_t *res, void *arg) {}
|
325
|
+
|
286
326
|
static void up_internal_process_publish_post_data(uws_res_t *res,
|
287
327
|
const char *chunk,
|
288
328
|
size_t chunk_length,
|
@@ -299,9 +339,22 @@ static void up_internal_process_publish_post_data(uws_res_t *res,
|
|
299
339
|
break;
|
300
340
|
}
|
301
341
|
}
|
302
|
-
if (channel_length > 0 && message_length > 0)
|
342
|
+
if (channel_length > 0 && message_length > 0)
|
303
343
|
uws_publish(USE_SSL, s->app, channel_start, channel_length, message_start,
|
304
344
|
message_length, TEXT, false);
|
345
|
+
}
|
346
|
+
|
347
|
+
static void up_internal_process_post_data(uws_res_t *res, const char *chunk,
|
348
|
+
size_t chunk_length, bool is_end,
|
349
|
+
void *arg) {
|
350
|
+
server_s *s = (server_s *)arg;
|
351
|
+
rb_str_cat(s->body, chunk, chunk_length);
|
352
|
+
if (is_end) {
|
353
|
+
// set rack.input
|
354
|
+
rb_hash_aset(s->env, rack_input, rb_funcall(cStringIO, id_new, 1, s->body));
|
355
|
+
up_internal_call_app(s, res, s->env);
|
356
|
+
s->body = Qnil;
|
357
|
+
s->env = Qnil;
|
305
358
|
}
|
306
359
|
}
|
307
360
|
|
@@ -322,48 +375,25 @@ static void up_internal_publish_handler(uws_res_t *res, uws_req_t *req,
|
|
322
375
|
}
|
323
376
|
}
|
324
377
|
|
325
|
-
static void
|
326
|
-
void *arg) {
|
378
|
+
static void up_server_any_handler(uws_res_t *res, uws_req_t *req, void *arg) {
|
327
379
|
// prepare rack env
|
328
380
|
server_s *s = (server_s *)arg;
|
329
|
-
VALUE
|
330
|
-
up_server_prepare_env(
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
if (TYPE(rres) != T_ARRAY)
|
335
|
-
goto response_error;
|
336
|
-
|
337
|
-
// response status
|
338
|
-
VALUE rstatus = rb_ary_entry(rres, 0);
|
339
|
-
if (!up_internal_set_response_status(res, rstatus))
|
340
|
-
goto response_error;
|
341
|
-
|
342
|
-
// collect headers
|
343
|
-
VALUE rheaders = rb_ary_entry(rres, 1);
|
344
|
-
if (TYPE(rheaders) != T_HASH)
|
345
|
-
goto response_error;
|
346
|
-
rb_hash_foreach(rheaders, up_internal_res_header_handler, (VALUE)res);
|
347
|
-
|
348
|
-
// collect response body
|
349
|
-
VALUE rparts = rb_ary_entry(rres, 2);
|
350
|
-
up_internal_collect_response_body(res, rparts);
|
351
|
-
|
352
|
-
// end response
|
353
|
-
uws_res_end_without_body(USE_SSL, res, false);
|
381
|
+
VALUE env = rb_hash_dup(s->env_template);
|
382
|
+
up_server_prepare_env(env, req);
|
383
|
+
up_internal_call_app(s, res, env);
|
384
|
+
RB_GC_GUARD(env);
|
385
|
+
}
|
354
386
|
|
355
|
-
|
356
|
-
|
357
|
-
|
387
|
+
static void up_server_post_handler(uws_res_t *res, uws_req_t *req, void *arg) {
|
388
|
+
// prepare rack env
|
389
|
+
server_s *s = (server_s *)arg;
|
390
|
+
s->env = rb_hash_dup(s->env_template);
|
391
|
+
up_server_prepare_env(s->env, req);
|
358
392
|
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
RB_GC_GUARD(renv);
|
364
|
-
response_error:
|
365
|
-
fprintf(stderr, "response error\n");
|
366
|
-
uws_res_end_without_body(USE_SSL, res, false);
|
393
|
+
// receive POST data
|
394
|
+
s->body = rb_enc_str_new("", 0, utf8_encoding);
|
395
|
+
uws_res_on_data(USE_SSL, res, up_internal_process_post_data, (void *)s);
|
396
|
+
uws_res_on_aborted(USE_SSL, res, up_internal_abort_data, NULL);
|
367
397
|
}
|
368
398
|
|
369
399
|
static void
|
@@ -613,8 +643,8 @@ void up_ws_drain_handler(uws_websocket_t *ws, void *user_data) {
|
|
613
643
|
|
614
644
|
void up_ws_ping_handler(uws_websocket_t *ws, const char *message, size_t length,
|
615
645
|
void *user_data) {
|
616
|
-
/* You don't need to handle this one, we automatically respond to pings as
|
617
|
-
* standard */
|
646
|
+
/* You don't need to handle this one, we automatically respond to pings as
|
647
|
+
* per standard */
|
618
648
|
}
|
619
649
|
|
620
650
|
void up_ws_pong_handler(uws_websocket_t *ws, const char *message, size_t length,
|
@@ -807,7 +837,8 @@ static VALUE up_server_listen(VALUE self) {
|
|
807
837
|
sigemptyset(&upclcl.sa_mask);
|
808
838
|
sigaction(SIGINT, &upclcl, NULL);
|
809
839
|
}
|
810
|
-
|
840
|
+
uws_app_post(USE_SSL, s->app, "/*", up_server_post_handler, (void *)s);
|
841
|
+
uws_app_any(USE_SSL, s->app, "/*", up_server_any_handler, (void *)s);
|
811
842
|
uws_ws(USE_SSL, s->app, "/*",
|
812
843
|
(uws_socket_behavior_t){.compression = DISABLED,
|
813
844
|
.maxPayloadLength = 5 * 1024 * 1024,
|
@@ -949,6 +980,7 @@ void Init_up_ext(void) {
|
|
949
980
|
id_each = rb_intern("each");
|
950
981
|
id_host = rb_intern("host");
|
951
982
|
id_logger = rb_intern("logger");
|
983
|
+
id_new = rb_intern("new");
|
952
984
|
id_on_close = rb_intern("on_close");
|
953
985
|
id_on_drained = rb_intern("on_drained");
|
954
986
|
id_on_message = rb_intern("on_message");
|
@@ -980,14 +1012,14 @@ void Init_up_ext(void) {
|
|
980
1012
|
rb_gc_register_address(&cLogger);
|
981
1013
|
cLogger = rb_const_get(rb_cObject, rb_intern("Logger"));
|
982
1014
|
rb_gc_register_address(&default_logger);
|
983
|
-
default_logger = rb_funcall(cLogger,
|
1015
|
+
default_logger = rb_funcall(cLogger, id_new, 1, rb_stderr);
|
984
1016
|
|
985
1017
|
rb_require("stringio");
|
986
1018
|
|
987
1019
|
rb_gc_register_address(&cStringIO);
|
988
1020
|
cStringIO = rb_const_get(rb_cObject, rb_intern("StringIO"));
|
989
1021
|
rb_gc_register_address(&default_input);
|
990
|
-
default_input = rb_funcall(cStringIO,
|
1022
|
+
default_input = rb_funcall(cStringIO, id_new, 1, empty_string);
|
991
1023
|
|
992
1024
|
up_setup_rack_env_template();
|
993
1025
|
|
data/lib/up/bun/server.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# backtick_javascript: true
|
2
2
|
require 'logger'
|
3
|
+
require 'stringio'
|
3
4
|
require 'up/cli'
|
4
5
|
require 'up/client'
|
5
6
|
|
@@ -23,7 +24,7 @@ module Up
|
|
23
24
|
@ca_file = ca_file
|
24
25
|
@cert_file = cert_file
|
25
26
|
@key_file = key_file
|
26
|
-
@default_input =
|
27
|
+
@default_input = StringIO.new('', 'r')
|
27
28
|
@server = nil
|
28
29
|
@logger = logger
|
29
30
|
@t_factory = proc { |filename, _content_type| File.new(filename, 'a+') }
|
@@ -65,11 +66,17 @@ module Up
|
|
65
66
|
port: #@port,
|
66
67
|
hostname: #@host,
|
67
68
|
development: false,
|
68
|
-
fetch(req, server) {
|
69
|
+
async fetch(req, server) {
|
69
70
|
const upgrade = req.headers.get('Upgrade');
|
70
71
|
const env = new Map();
|
71
72
|
env.set('rack.errors',#{STDERR});
|
72
|
-
|
73
|
+
if (req.method === 'POST') {
|
74
|
+
let body = await req.text();
|
75
|
+
console.log('received: ', body);
|
76
|
+
env.set('rack.input', #{StringIO.new(`body`)});
|
77
|
+
} else {
|
78
|
+
env.set('rack.input', #@default_input);
|
79
|
+
}
|
73
80
|
env.set('rack.logger', #@logger);
|
74
81
|
env.set('rack.multipart.buffer_size', 4096);
|
75
82
|
env.set('rack.multipart.tempfile_factory', #@t_factory);
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# backtick_javascript: true
|
2
2
|
require 'logger'
|
3
|
+
require 'stringio'
|
3
4
|
require 'up/cli'
|
4
5
|
require 'up/client'
|
5
6
|
|
@@ -29,7 +30,7 @@ module Up
|
|
29
30
|
@ca_file = ca_file
|
30
31
|
@cert_file = cert_file
|
31
32
|
@key_file = key_file
|
32
|
-
@default_input =
|
33
|
+
@default_input = StringIO.new('', 'r')
|
33
34
|
@server = nil
|
34
35
|
@logger = logger
|
35
36
|
@t_factory = proc { |filename, _content_type| File.new(filename, 'a+') }
|
@@ -58,20 +59,20 @@ module Up
|
|
58
59
|
#{`parts`.close if `parts`.respond_to?(:close)}
|
59
60
|
}
|
60
61
|
|
61
|
-
self.prepare_env = function(req) {
|
62
|
+
self.prepare_env = function(req, ins) {
|
62
63
|
const env = new Map();
|
63
64
|
env.set('rack.errors',#{STDERR});
|
64
|
-
env.set('rack.input',
|
65
|
-
env.set('rack.logger',
|
65
|
+
env.set('rack.input', ins.default_input);
|
66
|
+
env.set('rack.logger', ins.logger);
|
66
67
|
env.set('rack.multipart.buffer_size', 4096);
|
67
|
-
env.set('rack.multipart.tempfile_factory',
|
68
|
-
env.set('rack.url_scheme',
|
68
|
+
env.set('rack.multipart.tempfile_factory', ins.t_factory);
|
69
|
+
env.set('rack.url_scheme', ins.scheme);
|
69
70
|
env.set('SCRIPT_NAME', "");
|
70
71
|
env.set('SERVER_PROTOCOL', 'HTTP/1.1');
|
71
72
|
env.set('HTTP_VERSION', 'HTTP/1.1');
|
72
|
-
env.set('SERVER_NAME',
|
73
|
-
env.set('SERVER_PORT',
|
74
|
-
env.set('QUERY_STRING', req.getQuery());
|
73
|
+
env.set('SERVER_NAME', ins.host);
|
74
|
+
env.set('SERVER_PORT', ins.port);
|
75
|
+
env.set('QUERY_STRING', req.getQuery() || '');
|
75
76
|
env.set('REQUEST_METHOD', req.getMethod().toUpperCase());
|
76
77
|
env.set('PATH_INFO', req.getUrl());
|
77
78
|
req.forEach((k, v) => { env.set('HTTP_' + k.toUpperCase().replaceAll('-', '_'), v) });
|
@@ -91,8 +92,24 @@ module Up
|
|
91
92
|
} else {
|
92
93
|
#@server = uws.App();
|
93
94
|
}
|
95
|
+
#@server.post('/*', (res, req) => {
|
96
|
+
const env = ouws.prepare_env(req, self);
|
97
|
+
let buffer = Buffer.from('');
|
98
|
+
res.onData((chunk, is_last) => {
|
99
|
+
buffer = Buffer.concat([buffer, Buffer.from(chunk)]);
|
100
|
+
if (is_last === true) {
|
101
|
+
env.set('rack.input', #{StringIO.new(`buffer.toString()`)});
|
102
|
+
const rack_res = #@app.$call(env);
|
103
|
+
res.writeStatus(rack_res[0].toString() + ' OK');
|
104
|
+
ouws.handle_headers(rack_res[1], res);
|
105
|
+
ouws.handle_response(rack_res[2], res);
|
106
|
+
res.end();
|
107
|
+
}
|
108
|
+
});
|
109
|
+
res.onAborted(() => {});
|
110
|
+
});
|
94
111
|
#@server.any('/*', (res, req) => {
|
95
|
-
const rack_res = #@app.$call(ouws.prepare_env(req));
|
112
|
+
const rack_res = #@app.$call(ouws.prepare_env(req, self));
|
96
113
|
res.writeStatus(rack_res[0].toString() + ' OK');
|
97
114
|
ouws.handle_headers(rack_res[1], res);
|
98
115
|
ouws.handle_response(rack_res[2], res);
|
@@ -136,7 +153,7 @@ module Up
|
|
136
153
|
},
|
137
154
|
sendPingsAutomatically: true,
|
138
155
|
upgrade: (res, req, context) => {
|
139
|
-
const env = ouws.prepare_env(req);
|
156
|
+
const env = ouws.prepare_env(req, self);
|
140
157
|
env.set('rack.upgrade?', #{:websocket});
|
141
158
|
const rack_res = #@app.$call(env);
|
142
159
|
const handler = env.get('rack.upgrade');
|
data/lib/up/version.rb
CHANGED