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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e47b86e6f54cbdb8ecf23cf5b6c759127ac30a8f4f00764e39eeca57ca94e52d
4
- data.tar.gz: 6d93f3b96474fb1c18fadeb5a46083241947691470a0c3f7d36dc7025e1116de
3
+ metadata.gz: 46fd760653d3303f32429a4dfd767c4d93ac56817393785d7da35632ab2d4ad2
4
+ data.tar.gz: a809d96c97f31441dd51c8e5c87aeaee47059835718f62de3217b38348d7d111
5
5
  SHA512:
6
- metadata.gz: 25d3c86c354d50656b266995a0d235460e6d9c45b1853d33d363636e1bead3b4539b8a068fee0cbfd58b27d2160759b2f1823ae039c2ce0c15793f6a95fd0541
7
- data.tar.gz: d3a6dd3a8e854a1ba75cfc297ecb5b4153c04b3814185add67424bcfd7574538d4365aebbd1006967e798d7af155ad0b98582955eb4f8c2e1f5633448d474433
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 up_server_request_handler(uws_res_t *res, uws_req_t *req,
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 renv = rb_hash_dup(s->env_template);
330
- up_server_prepare_env(renv, req);
331
-
332
- // call app
333
- VALUE rres = rb_funcall(s->rapp, id_call, 1, renv);
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
- // close resources if necessary
356
- if (rb_respond_to(rparts, id_close))
357
- rb_funcall(rparts, id_close, 0);
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
- return;
360
- RB_GC_GUARD(rstatus);
361
- RB_GC_GUARD(rheaders);
362
- RB_GC_GUARD(rres);
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 per
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
- uws_app_any(USE_SSL, s->app, "/*", up_server_request_handler, (void *)s);
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, rb_intern("new"), 1, rb_stderr);
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, rb_intern("new"), 1, empty_string);
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 = IO.new
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
- env.set('rack.input', #@default_input);
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 = IO.new
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', #@default_input);
65
- env.set('rack.logger', #@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', #@t_factory);
68
- env.set('rack.url_scheme', #@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', #@host);
73
- env.set('SERVER_PORT', #@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
@@ -1,3 +1,3 @@
1
1
  module Up
2
- VERSION = '0.0.6'.freeze
2
+ VERSION = '0.0.7'.freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opal-up
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Biedermann