agoo 2.1.1 → 2.1.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of agoo might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0618dff57c263cccb782e0fbccc807bf434815109c3809078ebd4d12570e1bde'
4
- data.tar.gz: 2603682170f882a06d20e50ad0d9ab753b927f730331c224ce9e4dcc2cbea581
3
+ metadata.gz: e352cb4e13de1ea7e2bde18b69084458a22061b34d2e2876a958e6580719e9f5
4
+ data.tar.gz: fe95bb555e84f531835cf6964266926ee57e585b2aeb1839df3dcf448f08e1b2
5
5
  SHA512:
6
- metadata.gz: cc4b5878761a72885f79ed8baecfb8bf23b6d516e7035ec97d14e655980432feb3923d8bbeae4824bcbfcb5e61c05562fb5e53fda03afdc40e841cbb2676f9fc
7
- data.tar.gz: 159dba44203a4612598949a47e4fbd8f11a99b19dcceb368f1ebab4c65a5c785790163dcdb6998f780b17d0d9836c26087d3a68ae6367376d144007993094fc0
6
+ metadata.gz: 59e7282f5603b4849ab7e6d5b007099e3533421cb00a305ee89c7709dee1ac75dea40d559adf906800cba06aa23acfb4ce3847d6200fb9f67ddd2f800de6aaf1
7
+ data.tar.gz: 5133a7c384c40a87e2a4578a25753bd0fbd8f7011e1214a1f52ff71f9573423bc39a1aa53cbd5d63fd0ce2fe0b7b9147f5c22d0bf6738516d881e7617fb0e474
@@ -1,5 +1,15 @@
1
1
  # CHANGELOG
2
2
 
3
+ ### 2.1.3 - 2018-05-16
4
+
5
+ - Optimized `rackup` to look for files in the root directory before calling rackup as the default. The root is now set to `./public` instead of `.`. The `:rmux` (rack multiplex) turns that off.
6
+
7
+ ### 2.1.2 - 2018-05-15
8
+
9
+ - Added `#open?` method to the Upgraded (connection client) class.
10
+
11
+ - Slight improvement performcance serving static assets for Rails.
12
+
3
13
  ### 2.1.1 - 2018-05-11
4
14
 
5
15
  - Subject can now be Symbols or any other object that responds top `#to_s`.
data/README.md CHANGED
@@ -41,11 +41,11 @@ performance HTTP server that serves static resource at hundreds of thousands
41
41
  of fetchs per second. A a simple hello world Ruby handler at over 100,000
42
42
  requests per second on a desktop computer. That places Agoo at about 85 times
43
43
  faster than Sinatra and 1000 times faster than Rails. In both cases the
44
- latency was two orders of magnitude lower or more. Checkout the benchmarks on
45
- <a href="http://opo.technology/benchmarks.html#web_benchmarks">OpO
46
- benchmarks</a>. Note that the benchmarks had to use a C program called <a
47
- href="https://github.com/ohler55/perfer">Perfer</a> to hit the Agoo
48
- limits. Ruby benchmarks driver could not push Agoo hard enough.
44
+ latency was two orders of magnitude lower or more. Checkout the
45
+ [benchmarks](http://opo.technology/benchmarks.html#web_benchmarks). Note that
46
+ the benchmarks had to use a C program called
47
+ [Perfer](https://github.com/ohler55/perfer) to hit the Agoo limits. Ruby
48
+ benchmarks driver could not push Agoo hard enough.
49
49
 
50
50
  Agoo supports the [Ruby rack API](https://rack.github.io) which allows for the
51
51
  use of rack compatible gems such as Hanami and Rails. Agoo also supports WebSockets and SSE.
@@ -57,8 +57,8 @@ use of rack compatible gems such as Hanami and Rails. Agoo also supports WebSock
57
57
  extension](https://github.com/rack/rack/pull/1272) and give it a look and a
58
58
  thumbs-up or heart if you like it.
59
59
 
60
- - Agoo now serves Rails static assets 2000 times faster than the default
61
- Puma. Thats right, 2000 times faster.
60
+ - Agoo now serves Rails static assets more than 2000 times faster than the
61
+ default Puma. Thats right, [2000 times faster](misc/rails.md).
62
62
 
63
63
  ## Releases
64
64
 
@@ -69,7 +69,7 @@ the develop branch. Pull requests should be made against the develop branch.
69
69
 
70
70
  ## Links
71
71
 
72
- - *Documentation*: http://rubydoc.info/gems/agoo
72
+ - *Documentation*: http://rubydoc.info/gems/agoo or http://www.ohler.com/agoo/doc/index.html
73
73
 
74
74
  - *GitHub* *repo*: https://github.com/ohler55/agoo
75
75
 
@@ -124,6 +124,31 @@ should_close(const char *header, int hlen) {
124
124
  return false;
125
125
  }
126
126
 
127
+ static bool
128
+ page_response(Con c, Page p, char *hend) {
129
+ Res res;
130
+ char *b;
131
+
132
+ if (NULL == (res = res_create(c))) {
133
+ return true;
134
+ }
135
+ if (NULL == c->res_tail) {
136
+ c->res_head = res;
137
+ } else {
138
+ c->res_tail->next = res;
139
+ }
140
+ c->res_tail = res;
141
+
142
+ b = strstr(c->buf, "\r\n");
143
+ res->close = should_close(b, (int)(hend - b));
144
+ if (res->close) {
145
+ c->closing = true;
146
+ }
147
+ res_set_message(res, p->resp);
148
+
149
+ return false;
150
+ }
151
+
127
152
  // Returns:
128
153
  // 0 - when header has not been read
129
154
  // message length - when length can be determined
@@ -244,26 +269,35 @@ con_header_read(Con c) {
244
269
  mlen = hend - c->buf + 4 + clen;
245
270
  if (GET == method &&
246
271
  NULL != (p = group_get(&err, &the_server.pages, path, (int)(pend - path)))) {
247
- if (NULL == (res = res_create(c))) {
272
+ if (page_response(c, p, hend)) {
248
273
  return bad_request(c, 500, __LINE__);
249
274
  }
250
- if (NULL == c->res_tail) {
251
- c->res_head = res;
252
- } else {
253
- c->res_tail->next = res;
254
- }
255
- c->res_tail = res;
275
+ return -mlen;
256
276
 
257
- b = strstr(c->buf, "\r\n");
258
- res->close = should_close(b, (int)(hend - b));
259
- if (res->close) {
260
- c->closing = true;
277
+ // TBD int hook_or_page(method, path, pend, &hook)
278
+ // return http status
279
+ // 0 is not handled
280
+ // 200 means taken care of
281
+ // default (over 200) call bad_request
282
+ }
283
+ if (GET == method && the_server.root_first &&
284
+ NULL != (p = page_get(&err, &the_server.pages, path, (int)(pend - path)))) {
285
+ if (page_response(c, p, hend)) {
286
+ return bad_request(c, 500, __LINE__);
261
287
  }
262
- res_set_message(res, p->resp);
263
-
264
288
  return -mlen;
265
- } else if (NULL == (hook = hook_find(the_server.hooks, method, path, pend))) {
289
+ }
290
+ if (NULL == (hook = hook_find(the_server.hooks, method, path, pend))) {
266
291
  if (GET == method) {
292
+ if (the_server.root_first) { // already checked
293
+ if (NULL != the_server.hook404) {
294
+ // There would be too many parameters to pass to a
295
+ // separate function so just goto the hook processing.
296
+ hook = the_server.hook404;
297
+ goto HOOKED;
298
+ }
299
+ return bad_request(c, 404, __LINE__);
300
+ }
267
301
  if (NULL == (p = page_get(&err, &the_server.pages, path, (int)(pend - path)))) {
268
302
  if (NULL != the_server.hook404) {
269
303
  // There would be too many parameters to pass to a
@@ -273,23 +307,9 @@ con_header_read(Con c) {
273
307
  }
274
308
  return bad_request(c, 404, __LINE__);
275
309
  }
276
- if (NULL == (res = res_create(c))) {
310
+ if (page_response(c, p, hend)) {
277
311
  return bad_request(c, 500, __LINE__);
278
312
  }
279
- if (NULL == c->res_tail) {
280
- c->res_head = res;
281
- } else {
282
- c->res_tail->next = res;
283
- }
284
- c->res_tail = res;
285
-
286
- b = strstr(c->buf, "\r\n");
287
- res->close = should_close(b, (int)(hend - b));
288
- if (res->close) {
289
- c->closing = true;
290
- }
291
- res_set_message(res, p->resp);
292
-
293
313
  return -mlen;
294
314
  }
295
315
  }
@@ -401,11 +401,33 @@ update_contents(Cache cache, Page p) {
401
401
  return true;
402
402
  }
403
403
 
404
+ static Page
405
+ page_check(Err err, Cache cache, Page page) {
406
+ double now = dtime();
407
+
408
+ if (page->last_check + PAGE_RECHECK_TIME < now) {
409
+ struct stat fattr;
410
+
411
+ if (0 == stat(page->path, &fattr) && page->mtime != fattr.st_mtime) {
412
+ update_contents(cache, page);
413
+ if (NULL == page->resp) {
414
+ page_destroy(page);
415
+ err_set(err, ERR_NOT_FOUND, "not found.");
416
+ return NULL;
417
+ }
418
+ }
419
+ page->last_check = now;
420
+ }
421
+ return page;
422
+ }
423
+
404
424
  Page
405
425
  page_get(Err err, Cache cache, const char *path, int plen) {
406
426
  Page page;
407
427
 
408
- // TBD check for .. and ~
428
+ if (NULL != strstr(path, "../")) {
429
+ return NULL;
430
+ }
409
431
  if (NULL == (page = cache_get(cache, path, plen))) {
410
432
  Page old;
411
433
  char full_path[2048];
@@ -433,21 +455,7 @@ page_get(Err err, Cache cache, const char *path, int plen) {
433
455
  page_destroy(old);
434
456
  }
435
457
  } else {
436
- double now = dtime();
437
-
438
- if (page->last_check + PAGE_RECHECK_TIME < now) {
439
- struct stat fattr;
440
-
441
- if (0 == stat(page->path, &fattr) && page->mtime != fattr.st_mtime) {
442
- update_contents(cache, page);
443
- if (NULL == page->resp) {
444
- page_destroy(page);
445
- err_set(err, ERR_NOT_FOUND, "not found.");
446
- return NULL;
447
- }
448
- }
449
- page->last_check = now;
450
- }
458
+ page = page_check(err, cache, page);
451
459
  }
452
460
  return page;
453
461
  }
@@ -457,11 +465,13 @@ group_get(Err err, Cache cache, const char *path, int plen) {
457
465
  Page page = NULL;
458
466
  Group g = NULL;
459
467
  char full_path[2048];
460
- Page old;
461
468
  char *s;
462
469
  Dir d;
470
+ double now;
463
471
 
464
- // TBD check for .. and ~
472
+ if (NULL != strstr(path, "../")) {
473
+ return NULL;
474
+ }
465
475
  for (g = cache->groups; NULL != g; g = g->next) {
466
476
  if (g->plen < plen && 0 == strncmp(path, g->path, g->plen) && '/' == path[g->plen]) {
467
477
  break;
@@ -471,55 +481,54 @@ group_get(Err err, Cache cache, const char *path, int plen) {
471
481
  return NULL;
472
482
  }
473
483
  for (d = g->dirs; NULL != d; d = d->next) {
474
- if (sizeof(full_path) <= d->plen + plen) {
484
+ if ((int)sizeof(full_path) <= d->plen + plen) {
475
485
  continue;
476
486
  }
477
487
  s = stpcpy(full_path, d->path);
478
488
  strncpy(s, path + g->plen, plen - g->plen);
479
489
  s += plen - g->plen;
480
490
  *s = '\0';
481
- if (0 == access(full_path, R_OK)) {
491
+ if (NULL != (page = cache_get(cache, full_path, s - full_path))) {
482
492
  break;
483
493
  }
484
494
  }
485
- if (NULL == d) {
486
- return NULL;
487
- }
488
- plen = s - full_path;
489
- path = full_path;
490
- if (NULL == (page = cache_get(cache, path, plen))) {
491
- Page old;
492
-
493
- if (NULL == (page = page_create(path))) {
494
- err_set(err, ERR_MEMORY, "Failed to allocate memory for Page.");
495
- return NULL;
495
+ if (NULL == page) {
496
+ for (d = g->dirs; NULL != d; d = d->next) {
497
+ if ((int)sizeof(full_path) <= d->plen + plen) {
498
+ continue;
499
+ }
500
+ s = stpcpy(full_path, d->path);
501
+ strncpy(s, path + g->plen, plen - g->plen);
502
+ s += plen - g->plen;
503
+ *s = '\0';
504
+ if (0 == access(full_path, R_OK)) {
505
+ break;
506
+ }
496
507
  }
497
- if (!update_contents(cache, page) || NULL == page->resp) {
498
- page_destroy(page);
499
- err_set(err, ERR_NOT_FOUND, "not found.");
508
+ if (NULL == d) {
500
509
  return NULL;
501
510
  }
502
- if (NULL != (old = cache_set(cache, path, plen, page))) {
503
- page_destroy(old);
504
- }
505
- } else {
506
- double now = dtime();
507
-
508
- if (page->last_check + PAGE_RECHECK_TIME < now) {
509
- struct stat fattr;
510
-
511
- if (0 == stat(page->path, &fattr) && page->mtime != fattr.st_mtime) {
512
- update_contents(cache, page);
513
- if (NULL == page->resp) {
514
- page_destroy(page);
515
- err_set(err, ERR_NOT_FOUND, "not found.");
516
- return NULL;
517
- }
511
+ plen = s - full_path;
512
+ path = full_path;
513
+ if (NULL == (page = cache_get(cache, path, plen))) {
514
+ Page old;
515
+
516
+ if (NULL == (page = page_create(path))) {
517
+ err_set(err, ERR_MEMORY, "Failed to allocate memory for Page.");
518
+ return NULL;
519
+ }
520
+ if (!update_contents(cache, page) || NULL == page->resp) {
521
+ page_destroy(page);
522
+ err_set(err, ERR_NOT_FOUND, "not found.");
523
+ return NULL;
524
+ }
525
+ if (NULL != (old = cache_set(cache, path, plen, page))) {
526
+ page_destroy(old);
518
527
  }
519
- page->last_check = now;
520
528
  }
529
+ return page;
521
530
  }
522
- return page;
531
+ return page_check(err, cache, page);
523
532
  }
524
533
 
525
534
  Group
@@ -135,6 +135,7 @@ configure(Err err, int port, const char *root, VALUE options) {
135
135
  the_server.listen_thread = 0;
136
136
  the_server.con_thread = 0;
137
137
  the_server.max_push_pending = 32;
138
+ the_server.root_first = false;
138
139
  if (Qnil != options) {
139
140
  VALUE v;
140
141
 
@@ -159,6 +160,9 @@ configure(Err err, int port, const char *root, VALUE options) {
159
160
  if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("pedantic"))))) {
160
161
  the_server.pedantic = (Qtrue == v);
161
162
  }
163
+ if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("root_first"))))) {
164
+ the_server.root_first = (Qtrue == v);
165
+ }
162
166
  if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("Port"))))) {
163
167
  if (rb_cInteger == rb_obj_class(v)) {
164
168
  the_server.port = NUM2INT(v);
@@ -207,7 +211,7 @@ configure(Err err, int port, const char *root, VALUE options) {
207
211
  *
208
212
  * - *options* [_Hash_] server options
209
213
  *
210
- * - *:pedantic* [_true_|_false_] if true response header and status codes are check and an exception raised if they violate the rack spec at https://github.com/rack/rack/blob/master/SPEC, https://tools.ietf.org/html/rfc3875#section-4.1.18, or https://tools.ietf.org/html/rfc7230.
214
+ * - *:pedantic* [_true_|_false_] if true response header and status codes are checked and an exception raised if they violate the rack spec at https://github.com/rack/rack/blob/master/SPEC, https://tools.ietf.org/html/rfc3875#section-4.1.18, or https://tools.ietf.org/html/rfc7230.
211
215
  *
212
216
  * - *:thread_count* [_Integer_] number of ruby worker threads. Defaults to one. If zero then the _start_ function will not return but instead will proess using the thread that called _start_. Usually the default is best unless the workers are making IO calls.
213
217
  */
@@ -23,6 +23,7 @@ typedef struct _Server {
23
23
  int max_push_pending;
24
24
  int port;
25
25
  bool pedantic;
26
+ bool root_first;
26
27
  atomic_int running;
27
28
  pthread_t listen_thread;
28
29
  pthread_t con_thread;
@@ -283,6 +283,24 @@ pending(VALUE self) {
283
283
  return INT2NUM(pending);
284
284
  }
285
285
 
286
+ /* Document-method: open?
287
+ *
288
+ * call-seq: open?()
289
+ *
290
+ * Returns true if the connection is open and false otherwise.
291
+ */
292
+ static VALUE
293
+ up_open(VALUE self) {
294
+ Upgraded up = get_upgraded(self);
295
+ int pending = -1;
296
+
297
+ if (NULL != up) {
298
+ pending = atomic_load(&up->pending);
299
+ atomic_fetch_sub(&up->ref_cnt, 1);
300
+ }
301
+ return 0 <= pending ? Qtrue : Qfalse;
302
+ }
303
+
286
304
  /* Document-method: protocol
287
305
  *
288
306
  * call-seq: protocol()
@@ -371,6 +389,7 @@ upgraded_init(VALUE mod) {
371
389
  rb_define_method(upgraded_class, "pending", pending, 0);
372
390
  rb_define_method(upgraded_class, "protocol", protocol, 0);
373
391
  rb_define_method(upgraded_class, "publish", ragoo_publish, 2);
392
+ rb_define_method(upgraded_class, "open?", up_open, 0);
374
393
 
375
394
  on_open_id = rb_intern("on_open");
376
395
  to_s_id = rb_intern("to_s");
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Agoo
3
3
  # Agoo version.
4
- VERSION = '2.1.1'
4
+ VERSION = '2.1.3'
5
5
  end
@@ -10,14 +10,16 @@ module Rack
10
10
  # The Rack::Handler::Agoo module is a handler for common rack config.rb files.
11
11
  module Agoo
12
12
 
13
- # Run the server. Options are the same as for Agoo::Server plus a :prot
13
+ # Run the server. Options are the same as for Agoo::Server plus a :port
14
14
  # and :root option.
15
15
  def self.run(handler, options={})
16
16
  port = 9292
17
- root = '.'
17
+ root = './public'
18
+ root_set = false
18
19
  default_handler = nil
19
20
  not_found_handler = nil
20
21
  path_map = {}
22
+ options[:root_first] = true # the default for rack
21
23
 
22
24
  default_handler = handler unless handler.nil?
23
25
  options.each { |k,v|
@@ -26,7 +28,10 @@ module Rack
26
28
  options.delete(k)
27
29
  elsif :root == k
28
30
  root = v
31
+ root_set = true
29
32
  options.delete(k)
33
+ elsif :rmux == k
34
+ options[:root_first] = false
30
35
  elsif k.nil?
31
36
  not_found_handler = v
32
37
  options.delete(k)
@@ -46,6 +51,7 @@ module Rack
46
51
  begin
47
52
  # If Rails is loaded this should work else just ignore.
48
53
  ::Agoo::Server.path_group('/assets', Rails.configuration.assets.paths)
54
+ root = Rails.public_path unless root_set
49
55
  rescue Exception
50
56
  end
51
57
  unless default_handler.nil?
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.1.1
4
+ version: 2.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-11 00:00:00.000000000 Z
11
+ date: 2018-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oj