agoo 2.15.8 → 2.15.9

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: 02abdb9101a03fc778a6cac9b0ee843e1ba5d174faf33737dec99953f9950651
4
- data.tar.gz: 2a59de84f142434913db679a6ea0cbe696f7681b5ff748da8f20cbced2f7358b
3
+ metadata.gz: a329302a6e94be7ff5873793bc52c5dd6fe31b3913387ad739ec4313938e7248
4
+ data.tar.gz: 10c1bfbf837b13c1cc40e365dc85b6c2a81a7b7c1fd7006c5042dc6dd1f9103d
5
5
  SHA512:
6
- metadata.gz: f4126df37e2339f76d007c0d96d5929b4ba50dc0ea65e4a50d7a3577403fe641eaf8054cc48e975b18786b321eddfe022a0994556784c5b33dd93504d9981d00
7
- data.tar.gz: 9072e8a005ce5fbc1b033c14cd05990096371d4d885a65a7e1af2684ab5cd13cf745de71ce1b846f1655b7176b179d254aa9369c79200adfe15cfdcc9975e2fc
6
+ metadata.gz: e632b26c5dde2b454214502bb76211682a23ac1d3f6951fb59340e96198279635da2a89872f139686cec4061d50ae11a3cb4c022ea71644de13113cbd91c377a
7
+ data.tar.gz: 454fdd7f38f7c0abe43e68a25ca67ac6adfab3ef2cbc99c5778d24e991fe436470a7e684ecc69ea6b9b0da49ce3de6aaa2bd6732c6c008cf6fb81c25181ad29d
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  All changes to the Agoo gem are documented here. Releases follow semantic versioning.
4
4
 
5
+ ## [2.15.9] - 2024-02-26
6
+
7
+ ### Fixed
8
+
9
+ - Updated to support the most recent version of rack.
10
+
5
11
  ## [2.15.8] - 2023-10-07
6
12
 
7
13
  ### Fixed
data/ext/agoo/con.c CHANGED
@@ -26,9 +26,10 @@
26
26
  #include "upgraded.h"
27
27
  #include "websocket.h"
28
28
 
29
- #define CON_TIMEOUT 10.0
30
29
  #define INITIAL_POLL_SIZE 1024
31
30
 
31
+ double con_timeout = 30.0;
32
+
32
33
  typedef enum {
33
34
  HEAD_AGAIN = 'A',
34
35
  HEAD_ERR = 'E',
@@ -81,7 +82,7 @@ agoo_con_create(agooErr err, int sock, uint64_t id, agooBind b) {
81
82
  }
82
83
  c->sock = sock;
83
84
  c->id = id;
84
- c->timeout = dtime() + CON_TIMEOUT;
85
+ c->timeout = dtime() + con_timeout;
85
86
  c->bind = b;
86
87
  c->loop = NULL;
87
88
  pthread_mutex_init(&c->res_lock, 0);
@@ -289,6 +290,8 @@ con_header_read(agooCon c, size_t *mlenp) {
289
290
  char *query = NULL;
290
291
  char *qend;
291
292
  char *b;
293
+ char *proto;
294
+ char *pend;
292
295
  size_t clen = 0;
293
296
  long mlen;
294
297
  agooHook hook = NULL;
@@ -395,7 +398,12 @@ con_header_read(agooCon c, size_t *mlenp) {
395
398
  }
396
399
  mlen = hend - c->buf + 4 + clen;
397
400
  *mlenp = mlen;
398
-
401
+ proto = qend;
402
+ for (; ' ' == *proto; proto++) {
403
+ }
404
+ pend = proto;
405
+ for (; '\r' != *pend; pend++) {
406
+ }
399
407
  if (AGOO_GET == method) {
400
408
  char root_buf[20148];
401
409
  const char *root = NULL;
@@ -461,6 +469,8 @@ con_header_read(agooCon c, size_t *mlenp) {
461
469
  c->req->query.start = c->req->msg + (query - c->buf);
462
470
  c->req->query.len = (int)(qend - query);
463
471
  c->req->query.start[c->req->query.len] = '\0';
472
+ c->req->protocol.start = proto;
473
+ c->req->protocol.len = (int)(pend - proto);
464
474
  c->req->body.start = c->req->msg + (hend - c->buf + 4);
465
475
  c->req->body.len = (unsigned int)clen;
466
476
  b = strstr(b, "\r\n");
@@ -555,7 +565,7 @@ agoo_con_http_read(agooCon c) {
555
565
  cnt = recv(c->sock, c->buf + c->bcnt, sizeof(c->buf) - c->bcnt - 1, 0);
556
566
  }
557
567
  }
558
- c->timeout = dtime() + CON_TIMEOUT;
568
+ c->timeout = dtime() + con_timeout;
559
569
  if (0 >= cnt) {
560
570
  // If nothing read then no need to complain. Just close.
561
571
  if (0 < c->bcnt) {
@@ -658,7 +668,7 @@ agoo_con_http_write(agooCon c) {
658
668
  if (NULL == message) {
659
669
  return true;
660
670
  }
661
- c->timeout = dtime() + CON_TIMEOUT;
671
+ c->timeout = dtime() + con_timeout;
662
672
  if (0 == c->wcnt) {
663
673
  if (agoo_resp_cat.on) {
664
674
  char buf[4096];
@@ -736,7 +746,7 @@ con_ws_read(agooCon c) {
736
746
  } else {
737
747
  cnt = recv(c->sock, c->buf + c->bcnt, sizeof(c->buf) - c->bcnt - 1, 0);
738
748
  }
739
- c->timeout = dtime() + CON_TIMEOUT;
749
+ c->timeout = dtime() + con_timeout;
740
750
  if (0 >= cnt) {
741
751
  // If nothing read then no need to complain. Just close.
742
752
  if (0 < c->bcnt) {
@@ -883,7 +893,7 @@ con_ws_write(agooCon c) {
883
893
  }
884
894
  return true;
885
895
  }
886
- c->timeout = dtime() + CON_TIMEOUT;
896
+ c->timeout = dtime() + con_timeout;
887
897
  if (0 == c->wcnt) {
888
898
  agooText t;
889
899
 
@@ -943,7 +953,7 @@ con_sse_write(agooCon c) {
943
953
 
944
954
  return false;
945
955
  }
946
- c->timeout = dtime() + CON_TIMEOUT *2;
956
+ c->timeout = dtime() + con_timeout *2;
947
957
  if (0 == c->wcnt) {
948
958
  agooText t;
949
959
 
@@ -1177,7 +1187,7 @@ con_ready_check(void *ctx, double now) {
1177
1187
  return true;
1178
1188
  }
1179
1189
  } else if (AGOO_CON_WS == c->bind->kind || AGOO_CON_SSE == c->bind->kind) {
1180
- c->timeout = dtime() + CON_TIMEOUT;
1190
+ c->timeout = dtime() + con_timeout;
1181
1191
  if (AGOO_CON_WS == c->bind->kind) {
1182
1192
  agoo_ws_ping(c);
1183
1193
  }
data/ext/agoo/con.h CHANGED
@@ -20,6 +20,8 @@
20
20
 
21
21
  #define MAX_HEADER_SIZE 8192
22
22
 
23
+ extern double con_timeout;
24
+
23
25
  struct _agooUpgraded;
24
26
  struct _agooReq;
25
27
  struct _agooRes;
data/ext/agoo/req.c CHANGED
@@ -71,6 +71,13 @@ agoo_req_port(agooReq r) {
71
71
  return (int)strtol(colon + 1, NULL, 10);
72
72
  }
73
73
 
74
+ const char*
75
+ agoo_req_protocol(agooReq r, int *lenp) {
76
+ *lenp = r->protocol.len;
77
+
78
+ return r->protocol.start;
79
+ }
80
+
74
81
  const char*
75
82
  agoo_req_query_value(agooReq r, const char *key, int klen, int *vlenp) {
76
83
  const char *value;
data/ext/agoo/req.h CHANGED
@@ -31,6 +31,7 @@ typedef struct _agooReq {
31
31
  struct _agooUpgraded *up;
32
32
  struct _agooStr path;
33
33
  struct _agooStr query;
34
+ struct _agooStr protocol;
34
35
  struct _agooStr header;
35
36
  struct _agooStr body;
36
37
  char remote[INET6_ADDRSTRLEN];
@@ -43,6 +44,7 @@ typedef struct _agooReq {
43
44
  extern agooReq agoo_req_create(size_t mlen);
44
45
  extern void agoo_req_destroy(agooReq req);
45
46
  extern const char* agoo_req_host(agooReq r, int *lenp);
47
+ extern const char* agoo_req_protocol(agooReq r, int *lenp);
46
48
  extern int agoo_req_port(agooReq r);
47
49
  extern const char* agoo_req_query_value(agooReq r, const char *key, int klen, int *vlenp);
48
50
  extern int agoo_req_query_decode(char *s, int len);
data/ext/agoo/request.c CHANGED
@@ -48,6 +48,7 @@ static VALUE request_method_val = Qundef;
48
48
  static VALUE script_name_val = Qundef;
49
49
  static VALUE server_name_val = Qundef;
50
50
  static VALUE server_port_val = Qundef;
51
+ static VALUE server_protocol_val = Qundef;
51
52
  static VALUE slash_val = Qundef;
52
53
 
53
54
  static VALUE sse_sym;
@@ -218,6 +219,31 @@ server_name(VALUE self) {
218
219
  return req_server_name((agooReq)DATA_PTR(self));
219
220
  }
220
221
 
222
+ static VALUE
223
+ req_server_protocol(agooReq r) {
224
+ int len;
225
+ const char *protocol;
226
+
227
+ if (NULL == r) {
228
+ rb_raise(rb_eArgError, "Request is no longer valid.");
229
+ }
230
+ if (NULL == (protocol = agoo_req_protocol(r, &len))) {
231
+ return rb_str_new2("HTTP/1.1");
232
+ }
233
+ return rb_str_new(protocol, len);
234
+ }
235
+
236
+ /* Document-method: server_protocol
237
+ *
238
+ * call-seq: server_protocol()
239
+ *
240
+ * Returns the server or host protocol.
241
+ */
242
+ static VALUE
243
+ server_protocol(VALUE self) {
244
+ return req_server_protocol((agooReq)DATA_PTR(self));
245
+ }
246
+
221
247
  static VALUE
222
248
  req_server_port(agooReq r) {
223
249
  int len;
@@ -594,6 +620,7 @@ request_env(agooReq req, VALUE self) {
594
620
  rb_hash_aset(env, remote_addr_val, req_remote_addr(req));
595
621
  rb_hash_aset(env, server_port_val, req_server_port(req));
596
622
  rb_hash_aset(env, server_name_val, req_server_name(req));
623
+ rb_hash_aset(env, server_protocol_val, req_server_protocol(req));
597
624
  fill_headers(req, env);
598
625
  rb_hash_aset(env, rack_version_val, rack_version_val_val);
599
626
  rb_hash_aset(env, rack_url_scheme_val, req_rack_url_scheme(req));
@@ -739,6 +766,7 @@ request_init(VALUE mod) {
739
766
  rb_define_method(req_class, "query_string", query_string, 0);
740
767
  rb_define_method(req_class, "server_name", server_name, 0);
741
768
  rb_define_method(req_class, "server_port", server_port, 0);
769
+ rb_define_method(req_class, "server_protocol", server_protocol, 0);
742
770
  rb_define_method(req_class, "remote_addr", remote_addr, 0);
743
771
  rb_define_method(req_class, "rack_version", rack_version, 0);
744
772
  rb_define_method(req_class, "rack_url_scheme", rack_url_scheme, 0);
@@ -796,6 +824,7 @@ request_init(VALUE mod) {
796
824
  script_name_val = rb_str_new_cstr("SCRIPT_NAME"); rb_gc_register_address(&script_name_val);
797
825
  server_name_val = rb_str_new_cstr("SERVER_NAME"); rb_gc_register_address(&server_name_val);
798
826
  server_port_val = rb_str_new_cstr("SERVER_PORT"); rb_gc_register_address(&server_port_val);
827
+ server_protocol_val = rb_str_new_cstr("SERVER_PROTOCOL"); rb_gc_register_address(&server_protocol_val);
799
828
  slash_val = rb_str_new_cstr("/"); rb_gc_register_address(&slash_val);
800
829
 
801
830
  sse_sym = ID2SYM(rb_intern("sse")); rb_gc_register_address(&sse_sym);
data/ext/agoo/rserver.c CHANGED
@@ -104,6 +104,7 @@ configure(agooErr err, int port, const char *root, VALUE options) {
104
104
  }
105
105
  agoo_server.thread_cnt = 0;
106
106
  the_rserver.worker_cnt = 1;
107
+ the_rserver.forker = Qnil;
107
108
  the_rserver.uses = NULL;
108
109
  atomic_init(&agoo_server.running, 0);
109
110
  agoo_server.listen_thread = 0;
@@ -132,6 +133,8 @@ configure(agooErr err, int port, const char *root, VALUE options) {
132
133
  rb_raise(rb_eArgError, "thread_count must be between 1 and %d.", MAX_WORKERS);
133
134
  }
134
135
  }
136
+ the_rserver.forker = rb_hash_lookup(options, ID2SYM(rb_intern("fork_wrap")));
137
+
135
138
  if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("poll_timeout"))))) {
136
139
  double timeout = rb_num2dbl(v);
137
140
 
@@ -141,6 +144,15 @@ configure(agooErr err, int port, const char *root, VALUE options) {
141
144
  rb_raise(rb_eArgError, "poll_timeout must be between 0.0001 and 1.0.");
142
145
  }
143
146
  }
147
+ if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("connection_timeout"))))) {
148
+ double timeout = rb_num2dbl(v);
149
+
150
+ if (0.1 <= timeout) {
151
+ con_timeout = timeout;
152
+ } else {
153
+ rb_raise(rb_eArgError, "connection_timeout must be greater than 0.1 seconds.");
154
+ }
155
+ }
144
156
  if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("max_push_pending"))))) {
145
157
  int mpp = FIX2INT(v);
146
158
 
@@ -295,6 +307,8 @@ configure(agooErr err, int port, const char *root, VALUE options) {
295
307
  *
296
308
  * - *:poll_timeout* [_Float_] timeout seconds when polling. Default is 0.1. Lower gives faster response times but uses more CPU.
297
309
  *
310
+ * - *:connection_timeout* [_Float_] timeout seconds for connections. Default is 30.
311
+ *
298
312
  * - *:bind* [_String_|_Array_] a binding or array of binds. Examples are: "http ://127.0.0.1:6464", "unix:///tmp/agoo.socket", "http ://[::1]:6464, or to not restrict the address "http ://:6464".
299
313
  *
300
314
  * - *:graphql* [_String_] path to GraphQL endpoint if support for GraphQL is desired.
@@ -805,6 +819,7 @@ rserver_start(VALUE self) {
805
819
  struct _agooErr err = AGOO_ERR_INIT;
806
820
  VALUE agoo = rb_const_get_at(rb_cObject, rb_intern("Agoo"));
807
821
  VALUE v = rb_const_get_at(agoo, rb_intern("VERSION"));
822
+ ID after = rb_intern("after");
808
823
 
809
824
  *the_rserver.worker_pids = getpid();
810
825
 
@@ -819,6 +834,13 @@ rserver_start(VALUE self) {
819
834
  if (AGOO_ERR_OK != setup_listen(&err)) {
820
835
  rb_raise(rb_eIOError, "%s", err.msg);
821
836
  }
837
+ if (1 < the_rserver.worker_cnt && the_rserver.forker != Qnil) {
838
+ ID before = rb_intern("before");
839
+
840
+ if (rb_respond_to(the_rserver.forker, before)) {
841
+ rb_funcall(the_rserver.forker, before, 0);
842
+ }
843
+ }
822
844
  for (i = 1; i < the_rserver.worker_cnt; i++) {
823
845
  VALUE rpid = rb_funcall(rb_cObject, rb_intern("fork"), 0);
824
846
 
@@ -839,6 +861,9 @@ rserver_start(VALUE self) {
839
861
  the_rserver.worker_pids[i] = pid;
840
862
  }
841
863
  }
864
+ if (1 < the_rserver.worker_cnt && the_rserver.forker != Qnil && rb_respond_to(the_rserver.forker, after)) {
865
+ rb_funcall(the_rserver.forker, after, 0);
866
+ }
842
867
  if (AGOO_ERR_OK != agoo_server_start(&err, "Agoo", StringValuePtr(v))) {
843
868
  rb_raise(rb_eStandardError, "%s", err.msg);
844
869
  }
data/ext/agoo/rserver.h CHANGED
@@ -18,6 +18,7 @@ typedef struct _rServer {
18
18
  int worker_cnt;
19
19
  int worker_pids[MAX_WORKERS];
20
20
  VALUE *eval_threads; // Qnil terminated
21
+ VALUE forker;
21
22
  RUse uses;
22
23
  } *RServer;
23
24
 
data/ext/agoo/server.c CHANGED
@@ -149,7 +149,7 @@ listen_loop(void *x) {
149
149
  cnt--;
150
150
  agoo_err_clear(&err);
151
151
  } else {
152
- int con_cnt;
152
+ // int con_cnt;
153
153
  #ifdef OSX_OS
154
154
  setsockopt(client_sock, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval));
155
155
  #endif
@@ -163,8 +163,8 @@ listen_loop(void *x) {
163
163
  agoo_log_cat(&agoo_con_cat, "Server with pid %d accepted connection %llu on %s [%d] from %s",
164
164
  getpid(), (unsigned long long)cnt, b->id, con->sock, con->remote);
165
165
 
166
- con_cnt = atomic_fetch_add(&agoo_server.con_cnt, 1);
167
166
  /* TBD
167
+ con_cnt = atomic_fetch_add(&agoo_server.con_cnt, 1);
168
168
  if (agoo_server.loop_max > agoo_server.loop_cnt && agoo_server.loop_cnt * LOOP_UP < con_cnt) {
169
169
  add_con_loop();
170
170
  }
data/lib/agoo/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Agoo
3
3
  # Agoo version.
4
- VERSION = '2.15.8'
4
+ VERSION = '2.15.9'
5
5
  end
data/lib/agoo.rb CHANGED
@@ -8,4 +8,5 @@ require 'agoo/graphql'
8
8
  require 'rack/handler/agoo'
9
9
  require 'agoo/agoo' # C extension
10
10
 
11
+ ENV['RACKUP_HANDLER'] = 'Agoo'
11
12
  ENV['RACK_HANDLER'] = 'Agoo'
@@ -177,8 +177,14 @@ using the -O NAME[=VALUE] option of rackup. Note that if binds are provided the
177
177
  end
178
178
 
179
179
  begin
180
- ::Rack::Handler.register('agoo', 'Rack::Handler::Agoo')
181
- ::Rack::Handler.register('Agoo', 'Rack::Handler::Agoo')
180
+ ::Rackup::Handler.register('agoo', Rack::Handler::Agoo)
181
+ ::Rackup::Handler.register('Agoo', Rack::Handler::Agoo)
182
182
  rescue Exception
183
+ begin
184
+ # try the old style
185
+ ::Rack::Handler.register('agoo', 'Rack::Handler::Agoo')
186
+ ::Rack::Handler.register('Agoo', 'Rack::Handler::Agoo')
187
+ rescue Exception
188
+ end
183
189
  # Rack or Rack::Handler.register has not been required.
184
190
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: agoo
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.15.8
4
+ version: 2.15.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-07 00:00:00.000000000 Z
11
+ date: 2024-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oj
@@ -190,7 +190,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
190
190
  version: '0'
191
191
  requirements:
192
192
  - Linux or macOS
193
- rubygems_version: 3.4.10
193
+ rubygems_version: 3.4.1
194
194
  signing_key:
195
195
  specification_version: 4
196
196
  summary: An HTTP server