agoo 2.15.8 → 2.15.10

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 02abdb9101a03fc778a6cac9b0ee843e1ba5d174faf33737dec99953f9950651
4
- data.tar.gz: 2a59de84f142434913db679a6ea0cbe696f7681b5ff748da8f20cbced2f7358b
3
+ metadata.gz: 99f743f7259396ec783c42850172f11c99e3bfd067b65a10a1cfde0c44feda19
4
+ data.tar.gz: 314f7709e216fe0afc3190ab05a808b114b5766503e6fb0d82e8f65a77f140e4
5
5
  SHA512:
6
- metadata.gz: f4126df37e2339f76d007c0d96d5929b4ba50dc0ea65e4a50d7a3577403fe641eaf8054cc48e975b18786b321eddfe022a0994556784c5b33dd93504d9981d00
7
- data.tar.gz: 9072e8a005ce5fbc1b033c14cd05990096371d4d885a65a7e1af2684ab5cd13cf745de71ce1b846f1655b7176b179d254aa9369c79200adfe15cfdcc9975e2fc
6
+ metadata.gz: 0b85b630147884b41eb1eeda65b2278bbc491375ab193ec93c2989c2fe49aea4edec540353ff3cf4d3d63b383178f3949132e0f63e08d2bc220855d75efaaae9
7
+ data.tar.gz: eb537b2c220f3e6eceaf2a3c82de5dee1e883c5e321c5199c42cb22601a60a927212b49e885fa678a08343e7c6bc08fa67153518f78453b7149a7575e8d4b830
data/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  All changes to the Agoo gem are documented here. Releases follow semantic versioning.
4
4
 
5
+ ## [2.15.10] - 2024-04-14
6
+
7
+ ### Added
8
+ - Added metadata element to the gemspec file.
9
+
10
+ ## [2.15.9] - 2024-02-26
11
+
12
+ ### Fixed
13
+
14
+ - Updated to support the most recent version of rack.
15
+
5
16
  ## [2.15.8] - 2023-10-07
6
17
 
7
18
  ### 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.10'
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.10
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-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oj
@@ -163,7 +163,10 @@ files:
163
163
  homepage: https://github.com/ohler55/agoo
164
164
  licenses:
165
165
  - MIT
166
- metadata: {}
166
+ metadata:
167
+ changelog_uri: https://github.com/ohler55/agoo/CHANGELOG.md
168
+ source_code_uri: https://github.com/ohler55/agoo
169
+ homepage: https://github.com/ohler55/agoo
167
170
  post_install_message:
168
171
  rdoc_options:
169
172
  - "-t"