opal-up 0.0.6 → 0.0.7
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/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