agoo 1.0.0 → 1.1.0

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: ec0e1021cff3ef520275f242403861641910567fddf30d07d0df0f4d456e2d1f
4
- data.tar.gz: 7a6058474e50a04e1e068cf4911762079d9a7ec0777087914b1a40faf61b2ff6
3
+ metadata.gz: 6e35f7871e0927d3f8f560b3d9b529507ae392867aca53a9665c275a627070d5
4
+ data.tar.gz: 79a0b47f55c6b823844cf4e1679a068b0329ac407f9495bb1b5e6c3ad1b4f8de
5
5
  SHA512:
6
- metadata.gz: 03fa2278f4a6b70d1495577086ed15015f70ab7600a46dc02d6d4e91d996bfdcc1e818217a9043b83d3490c637ab53859402dead80524ea2bf0319812a536c2a
7
- data.tar.gz: 2517add46e2130c993aee42e69fddc05b27b62d6582217c6f6f24cae585c53051536b9bca1b914e900deba6963dd2f70a53496a77993a7310308774e797149c5
6
+ metadata.gz: 1916a0a04b117d76f366d0f11cf105f5245e0e20b07cd1032a9dec29c03845e490a988405946397f229fd85aba9bf3720f68fc91f07ce21e1c8079991c0ffbaf
7
+ data.tar.gz: 87a2b7e8345f1e8a0876f076121ae92a8659c8a8360d55a259edf037dc0e626b978567f167ba5d3702bfe426e60a6ebeb5560a6809a1253069f0d55ec851b481
data/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  [![Build Status](https://img.shields.io/travis/ohler55/agoo/master.svg)](http://travis-ci.org/ohler55/agoo?branch=master)
4
4
  [![Gem Version](https://badge.fury.io/rb/agoo.svg)](https://badge.fury.io/rb/agoo)
5
+ ![Gem](https://img.shields.io/gem/dt/agoo.svg)
5
6
 
6
7
  A High Performance HTTP Server for Ruby
7
8
 
@@ -49,7 +50,10 @@ use of rack compatible gems.
49
50
 
50
51
  ## Releases
51
52
 
52
- See [{file:CHANGELOG.md}](CHANGELOG.md)
53
+ See [file:CHANGELOG.md](CHANGELOG.md)
54
+
55
+ Releases are made from the master branch. The default branch for checkout is
56
+ the develop branch. Pull requests should be made against the develop branch.
53
57
 
54
58
  ## Links
55
59
 
@@ -59,4 +63,6 @@ See [{file:CHANGELOG.md}](CHANGELOG.md)
59
63
 
60
64
  - *RubyGems* *repo*: https://rubygems.org/gems/agoo
61
65
 
66
+ - *WABuR* *repo*: https://github.com/ohler55/wabur has an option to use Agoo
67
+
62
68
  Follow [@peterohler on Twitter](http://twitter.com/#!/peterohler) for announcements and news about the Agoo gem.
data/ext/agoo/agoo.c CHANGED
@@ -4,15 +4,22 @@
4
4
  #include <ruby.h>
5
5
 
6
6
  #include "error_stream.h"
7
+ #include "rack_logger.h"
7
8
  #include "request.h"
8
9
  #include "response.h"
9
10
  #include "server.h"
10
11
 
12
+ /* Document-module: Agoo
13
+ *
14
+ * A High Performance HTTP Server that supports the Ruby rack API. The word
15
+ * agoo is a Japanese word for a type of flying fish.
16
+ */
11
17
  void
12
18
  Init_agoo() {
13
19
  VALUE mod = rb_define_module("Agoo");
14
20
 
15
21
  error_stream_init(mod);
22
+ rack_logger_init(mod);
16
23
  request_init(mod);
17
24
  response_init(mod);
18
25
  server_init(mod);
data/ext/agoo/page.c CHANGED
@@ -5,6 +5,8 @@
5
5
  #include <stdlib.h>
6
6
  #include <sys/stat.h>
7
7
 
8
+ #include <ruby.h>
9
+
8
10
  #include "dtime.h"
9
11
  #include "page.h"
10
12
 
@@ -16,25 +18,51 @@ typedef struct _Mime {
16
18
  const char *type;
17
19
  } *Mime;
18
20
 
21
+ // These are used for the initial load.
19
22
  static struct _Mime mime_map[] = {
23
+ { "asc", "text/plain" },
24
+ { "avi", "video/x-msvideo" },
25
+ { "bin", "application/octet-stream" },
26
+ { "bmp", "image/bmp" },
27
+ { "cer", "application/pkix-cert" },
28
+ { "crl", "application/pkix-crl" },
29
+ { "crt", "application/x-x509-ca-cert" },
20
30
  { "css", "text/css" },
31
+ { "doc", "application/msword" },
21
32
  { "eot", "application/vnd.ms-fontobject" },
33
+ { "eps", "application/postscript" },
22
34
  { "es5", "application/javascript" },
23
35
  { "es6", "application/javascript" },
24
36
  { "gif", "image/gif" },
37
+ { "htm", "text/html" },
25
38
  { "html", "text/html" },
26
39
  { "ico", "image/x-icon" },
27
40
  { "jpeg", "image/jpeg" },
28
41
  { "jpg", "image/jpeg" },
29
42
  { "js", "application/javascript" },
30
43
  { "json", "application/json" },
44
+ { "mov", "video/quicktime" },
45
+ { "mpe", "video/mpeg" },
46
+ { "mpeg", "video/mpeg" },
47
+ { "mpg", "video/mpeg" },
48
+ { "pdf", "application/pdf" },
31
49
  { "png", "image/png" },
50
+ { "ppt", "application/vnd.ms-powerpoint" },
51
+ { "ps", "application/postscript" },
52
+ { "qt", "video/quicktime" },
53
+ { "rb", "text/plain" },
54
+ { "rtf", "application/rtf" },
32
55
  { "sse", "text/plain" },
33
56
  { "svg", "image/svg+xml" },
57
+ { "tif", "image/tiff" },
58
+ { "tiff", "image/tiff" },
34
59
  { "ttf", "application/font-sfnt" },
35
60
  { "txt", "text/plain" },
36
61
  { "woff", "application/font-woff" },
37
62
  { "woff2", "font/woff2" },
63
+ { "xls", "application/vnd.ms-excel" },
64
+ { "xml", "application/xml" },
65
+ { "zip", "application/zip" },
38
66
  { NULL, NULL }
39
67
  };
40
68
 
@@ -72,25 +100,28 @@ get_bucketp(Cache cache, uint64_t h) {
72
100
  return cache->buckets + (PAGE_BUCKET_MASK & (h ^ (h << 5) ^ (h >> 7)));
73
101
  }
74
102
 
75
- void
76
- cache_init(Cache cache) {
77
- memset(cache, 0, sizeof(struct _Cache));
103
+ static MimeSlot*
104
+ get_mime_bucketp(Cache cache, uint64_t h) {
105
+ return cache->muckets + (MIME_BUCKET_MASK & (h ^ (h << 5) ^ (h >> 7)));
78
106
  }
79
107
 
80
- void
81
- cache_destroy(Cache cache) {
82
- Slot *sp = cache->buckets;
83
- Slot s;
84
- Slot n;
108
+ const char*
109
+ mime_get(Cache cache, const char *key) {
110
+ int klen = (int)strlen(key);
111
+ int len = klen;
112
+ int64_t h = calc_hash(key, &len);
113
+ MimeSlot *bucket = get_mime_bucketp(cache, h);
114
+ MimeSlot s;
115
+ const char *v = NULL;
85
116
 
86
- for (int i = PAGE_BUCKET_SIZE; 0 < i; i--, sp++) {
87
- for (s = *sp; NULL != s; s = n) {
88
- n = s->next;
89
- free(s);
117
+ for (s = *bucket; NULL != s; s = s->next) {
118
+ if (h == (int64_t)s->hash && len == (int)s->klen &&
119
+ ((0 <= len && len <= MAX_KEY_UNIQ) || 0 == strncmp(s->key, key, klen))) {
120
+ v = s->value;
121
+ break;
90
122
  }
91
- *sp = NULL;
92
123
  }
93
- free(cache);
124
+ return v;
94
125
  }
95
126
 
96
127
  Page
@@ -111,7 +142,44 @@ cache_get(Cache cache, const char *key, int klen) {
111
142
  return v;
112
143
  }
113
144
 
114
- Page
145
+ void
146
+ mime_set(Cache cache, const char *key, const char *value) {
147
+ int klen = (int)strlen(key);
148
+ int len = klen;
149
+ int64_t h = calc_hash(key, &len);
150
+ MimeSlot *bucket = get_mime_bucketp(cache, h);
151
+ MimeSlot s;
152
+
153
+ if (MAX_MIME_KEY_LEN < len) {
154
+ rb_raise(rb_eArgError, "%s is too long for a file extension. Maximum is %d", key, MAX_MIME_KEY_LEN);
155
+ }
156
+ for (s = *bucket; NULL != s; s = s->next) {
157
+ if (h == (int64_t)s->hash && len == s->klen &&
158
+ ((0 <= len && len <= MAX_KEY_UNIQ) || 0 == strcmp(s->key, key))) {
159
+ if (h == (int64_t)s->hash && len == s->klen &&
160
+ ((0 <= len && len <= MAX_KEY_UNIQ) || 0 == strcmp(s->key, key))) {
161
+ free(s->value);
162
+ s->value = strdup(value);
163
+ return;
164
+ }
165
+ }
166
+ }
167
+ if (NULL == (s = (MimeSlot)malloc(sizeof(struct _MimeSlot)))) {
168
+ rb_raise(rb_eArgError, "out of memory adding %s", key);
169
+ }
170
+ s->hash = h;
171
+ s->klen = len;
172
+ if (NULL == key) {
173
+ *s->key = '\0';
174
+ } else {
175
+ strcpy(s->key, key);
176
+ }
177
+ s->value = strdup(value);
178
+ s->next = *bucket;
179
+ *bucket = s;
180
+ }
181
+
182
+ static Page
115
183
  cache_set(Cache cache, const char *key, int klen, Page value) {
116
184
  int len = klen;
117
185
  int64_t h = calc_hash(key, &len);
@@ -152,6 +220,44 @@ cache_set(Cache cache, const char *key, int klen, Page value) {
152
220
  return old;
153
221
  }
154
222
 
223
+ void
224
+ cache_init(Cache cache) {
225
+ Mime m;
226
+
227
+ memset(cache, 0, sizeof(struct _Cache));
228
+ for (m = mime_map; NULL != m->suffix; m++) {
229
+ mime_set(cache, m->suffix, m->type);
230
+ }
231
+ }
232
+
233
+ void
234
+ cache_destroy(Cache cache) {
235
+ Slot *sp = cache->buckets;
236
+ Slot s;
237
+ Slot n;
238
+ MimeSlot *mp = cache->muckets;
239
+ MimeSlot sm;
240
+ MimeSlot m;
241
+ int i;
242
+
243
+ for (i = PAGE_BUCKET_SIZE; 0 < i; i--, sp++) {
244
+ for (s = *sp; NULL != s; s = n) {
245
+ n = s->next;
246
+ free(s);
247
+ }
248
+ *sp = NULL;
249
+ }
250
+
251
+ for (i = MIME_BUCKET_SIZE; 0 < i; i--, mp++) {
252
+ for (sm = *mp; NULL != sm; sm = m) {
253
+ m = sm->next;
254
+ free(sm);
255
+ }
256
+ *mp = NULL;
257
+ }
258
+ free(cache);
259
+ }
260
+
155
261
  // The page resp contents point to the page resp msg to save memory and reduce
156
262
  // allocations.
157
263
  Page
@@ -182,7 +288,7 @@ page_destroy(Page p) {
182
288
  }
183
289
 
184
290
  static bool
185
- update_contents(Page p) {
291
+ update_contents(Cache cache, Page p) {
186
292
  const char *mime = NULL;
187
293
  int plen = (int)strlen(p->path);
188
294
  const char *suffix = p->path + plen - 1;
@@ -201,18 +307,9 @@ update_contents(Page p) {
201
307
  }
202
308
  }
203
309
  if (NULL != suffix) {
204
- Mime m;
205
-
206
310
  suffix++;
207
- for (m = mime_map; NULL != m->suffix; m++) {
208
- if (0 == strcasecmp(m->suffix, suffix)) {
209
- break;
210
- }
211
- }
212
- if (NULL == m) {
311
+ if (NULL == (mime = mime_get(cache, suffix))) {
213
312
  mime = "text/plain";
214
- } else {
215
- mime = m->type;
216
313
  }
217
314
  } else {
218
315
  mime = "text/plain";
@@ -313,7 +410,7 @@ page_get(Err err, Cache cache, const char *dir, const char *path, int plen) {
313
410
  err_set(err, ERR_MEMORY, "Failed to allocate memory for Page.");
314
411
  return NULL;
315
412
  }
316
- if (!update_contents(page) || NULL == page->resp) {
413
+ if (!update_contents(cache, page) || NULL == page->resp) {
317
414
  page_destroy(page);
318
415
  err_set(err, ERR_NOT_FOUND, "not found.");
319
416
  return NULL;
@@ -328,7 +425,7 @@ page_get(Err err, Cache cache, const char *dir, const char *path, int plen) {
328
425
  struct stat fattr;
329
426
 
330
427
  if (0 == stat(page->path, &fattr) && page->mtime != fattr.st_mtime) {
331
- update_contents(page);
428
+ update_contents(cache, page);
332
429
  if (NULL == page->resp) {
333
430
  page_destroy(page);
334
431
  err_set(err, ERR_NOT_FOUND, "not found.");
data/ext/agoo/page.h CHANGED
@@ -13,6 +13,10 @@
13
13
  #define PAGE_BUCKET_SIZE 1024
14
14
  #define PAGE_BUCKET_MASK 1023
15
15
 
16
+ #define MAX_MIME_KEY_LEN 15
17
+ #define MIME_BUCKET_SIZE 64
18
+ #define MIME_BUCKET_MASK 63
19
+
16
20
  typedef struct _Page {
17
21
  Text resp;
18
22
  char *path;
@@ -28,12 +32,22 @@ typedef struct _Slot {
28
32
  int klen;
29
33
  } *Slot;
30
34
 
35
+ typedef struct _MimeSlot {
36
+ struct _MimeSlot *next;
37
+ char key[MAX_MIME_KEY_LEN + 1];
38
+ char *value;
39
+ uint64_t hash;
40
+ int klen;
41
+ } *MimeSlot;
42
+
31
43
  typedef struct _Cache {
32
44
  Slot buckets[PAGE_BUCKET_SIZE];
45
+ MimeSlot muckets[MIME_BUCKET_SIZE];
33
46
  } *Cache;
34
47
 
35
48
  extern void cache_init(Cache cache);
36
49
  extern void page_destroy(Page p);
37
50
  extern Page page_get(Err err, Cache cache, const char *dir, const char *path, int plen);
51
+ extern void mime_set(Cache cache, const char *key, const char *value);
38
52
 
39
53
  #endif /* __AGOO_PAGE_H__ */
@@ -0,0 +1,162 @@
1
+ // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
+
3
+ #include <stdlib.h>
4
+
5
+ #include "rack_logger.h"
6
+ #include "log.h"
7
+ #include "text.h"
8
+
9
+ static VALUE rl_class = Qundef;
10
+
11
+ typedef struct _RackLogger {
12
+ Server server;
13
+ } *RackLogger;
14
+
15
+ VALUE
16
+ rack_logger_new(Server server) {
17
+ RackLogger rl = ALLOC(struct _RackLogger);
18
+
19
+ rl->server = server;
20
+
21
+ return Data_Wrap_Struct(rl_class, NULL, xfree, rl);
22
+ }
23
+
24
+ static void
25
+ log_message(RackLogger rl, LogLevel level, VALUE message) {
26
+ volatile VALUE rs = rb_funcall(message, rb_intern("to_s"), 0);
27
+
28
+ rb_check_type(rs, T_STRING);
29
+
30
+ if (rb_block_given_p()) {
31
+ Text text = text_create(StringValuePtr(rs), (int)RSTRING_LEN(rs));
32
+ volatile VALUE x = rb_yield_values(0);
33
+
34
+ if (Qnil != x) {
35
+ rs = rb_funcall(x, rb_intern("to_s"), 0);
36
+ text = text_append(text, ": ", 2);
37
+ text = text_append(text, StringValuePtr(rs), (int)RSTRING_LEN(rs));
38
+ }
39
+ switch (level) {
40
+ case FATAL:
41
+ log_cat(&rl->server->error_cat, "%s", text->text);
42
+ exit(0);
43
+ break;
44
+ case ERROR:
45
+ log_cat(&rl->server->error_cat, "%s", text->text);
46
+ break;
47
+ case WARN:
48
+ log_cat(&rl->server->warn_cat, "%s", text->text);
49
+ break;
50
+ case INFO:
51
+ log_cat(&rl->server->info_cat, "%s", text->text);
52
+ break;
53
+ case DEBUG:
54
+ log_cat(&rl->server->debug_cat, "%s", text->text);
55
+ break;
56
+ default:
57
+ break;
58
+ }
59
+ text_release(text);
60
+ } else {
61
+ switch (level) {
62
+ case FATAL:
63
+ log_cat(&rl->server->error_cat, "%s", StringValuePtr(rs));
64
+ exit(0);
65
+ break;
66
+ case ERROR:
67
+ log_cat(&rl->server->error_cat, "%s", StringValuePtr(rs));
68
+ break;
69
+ case WARN:
70
+ log_cat(&rl->server->warn_cat, "%s", StringValuePtr(rs));
71
+ break;
72
+ case INFO:
73
+ log_cat(&rl->server->info_cat, "%s", StringValuePtr(rs));
74
+ break;
75
+ case DEBUG:
76
+ log_cat(&rl->server->debug_cat, "%s", StringValuePtr(rs));
77
+ break;
78
+ default:
79
+ break;
80
+ }
81
+ }
82
+ }
83
+
84
+ /* Document-method: debug
85
+ *
86
+ * call-seq: debug(message, &block)
87
+ *
88
+ * Calls the Server#debug method.
89
+ */
90
+ static VALUE
91
+ rl_debug(VALUE self, VALUE message) {
92
+ log_message((RackLogger)DATA_PTR(self), DEBUG, message);
93
+
94
+ return Qnil;
95
+ }
96
+
97
+ /* Document-method: info
98
+ *
99
+ * call-seq: info(message, &block)
100
+ *
101
+ * Calls the Server#info method.
102
+ */
103
+ static VALUE
104
+ rl_info(VALUE self, VALUE message) {
105
+ log_message((RackLogger)DATA_PTR(self), INFO, message);
106
+
107
+ return Qnil;
108
+ }
109
+
110
+ /* Document-method: warn
111
+ *
112
+ * call-seq: warn(message, &block)
113
+ *
114
+ * Calls the Server#warn method.
115
+ */
116
+ static VALUE
117
+ rl_warn(VALUE self, VALUE message) {
118
+ log_message((RackLogger)DATA_PTR(self), WARN, message);
119
+
120
+ return Qnil;
121
+ }
122
+
123
+ /* Document-method: error
124
+ *
125
+ * call-seq: error(message, &block)
126
+ *
127
+ * Calls the Server#error method.
128
+ */
129
+ static VALUE
130
+ rl_error(VALUE self, VALUE message) {
131
+ log_message((RackLogger)DATA_PTR(self), ERROR, message);
132
+
133
+ return Qnil;
134
+ }
135
+
136
+ /* Document-method: fatal
137
+ *
138
+ * call-seq: fatal(message, &block)
139
+ *
140
+ * Calls the Server#fatal method.
141
+ */
142
+ static VALUE
143
+ rl_fatal(VALUE self, VALUE message) {
144
+ log_message((RackLogger)DATA_PTR(self), FATAL, message);
145
+
146
+ return Qnil;
147
+ }
148
+
149
+ /* Document-class: Agoo::RackLogger
150
+ *
151
+ * Used in a request as the _rack.logger_ attribute.
152
+ */
153
+ void
154
+ rack_logger_init(VALUE mod) {
155
+ rl_class = rb_define_class_under(mod, "RackLogger", rb_cObject);
156
+
157
+ rb_define_method(rl_class, "debug", rl_debug, 1);
158
+ rb_define_method(rl_class, "info", rl_info, 1);
159
+ rb_define_method(rl_class, "warn", rl_warn, 1);
160
+ rb_define_method(rl_class, "error", rl_error, 1);
161
+ rb_define_method(rl_class, "fatal", rl_fatal, 1);
162
+ }
@@ -0,0 +1,13 @@
1
+ // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
+
3
+ #ifndef __AGOO_RACK_LOGGER_H__
4
+ #define __AGOO_RACK_LOGGER_H__
5
+
6
+ #include <ruby.h>
7
+
8
+ #include "server.h"
9
+
10
+ extern void rack_logger_init(VALUE mod);
11
+ extern VALUE rack_logger_new(Server server);
12
+
13
+ #endif // __AGOO_RACK_LOGGER_H__
data/ext/agoo/request.c CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  #include "con.h"
6
6
  #include "error_stream.h"
7
+ #include "rack_logger.h"
7
8
  #include "request.h"
8
9
 
9
10
  static VALUE req_class = Qundef;
@@ -23,6 +24,7 @@ static VALUE put_val = Qundef;
23
24
  static VALUE query_string_val = Qundef;
24
25
  static VALUE rack_errors_val = Qundef;
25
26
  static VALUE rack_input_val = Qundef;
27
+ static VALUE rack_logger_val = Qundef;
26
28
  static VALUE rack_multiprocess_val = Qundef;
27
29
  static VALUE rack_multithread_val = Qundef;
28
30
  static VALUE rack_run_once_val = Qundef;
@@ -434,6 +436,25 @@ body(VALUE self) {
434
436
  return rb_str_new(r->body.start, r->body.len);
435
437
  }
436
438
 
439
+ static VALUE
440
+ req_rack_logger(Req req) {
441
+ return rack_logger_new(req->server);
442
+ }
443
+
444
+ /* Document-method: rack_logger
445
+ *
446
+ * call-seq: rack_logger()
447
+ *
448
+ * Returns a RackLogger that can be used to log messages with the server
449
+ * logger. The methods supported are debug(), info(), warn(), error(), and
450
+ * fatal(). The signature is the same as the standard Ruby Logger of
451
+ * info(message, &block).
452
+ */
453
+ static VALUE
454
+ rack_logger(VALUE self) {
455
+ return req_rack_logger((Req)DATA_PTR(self));
456
+ }
457
+
437
458
  /* Document-class: Agoo::Request
438
459
  *
439
460
  * A Request is passes to handler that respond to the _on_request_ method. The
@@ -461,6 +482,7 @@ request_env(Req req) {
461
482
  rb_hash_aset(env, rack_multithread_val, req_rack_multithread(req));
462
483
  rb_hash_aset(env, rack_multiprocess_val, Qfalse);
463
484
  rb_hash_aset(env, rack_run_once_val, Qfalse);
485
+ rb_hash_aset(env, rack_logger_val, req_rack_logger(req));
464
486
 
465
487
  return env;
466
488
  }
@@ -529,6 +551,7 @@ request_init(VALUE mod) {
529
551
  rb_define_method(req_class, "rack_run_once", rack_run_once, 0);
530
552
  rb_define_method(req_class, "headers", headers, 0);
531
553
  rb_define_method(req_class, "body", body, 0);
554
+ rb_define_method(req_class, "rack_logger", rack_logger, 0);
532
555
 
533
556
  new_id = rb_intern("new");
534
557
 
@@ -549,6 +572,7 @@ request_init(VALUE mod) {
549
572
  query_string_val = rb_str_new_cstr("QUERY_STRING"); rb_gc_register_address(&query_string_val);
550
573
  rack_errors_val = rb_str_new_cstr("rack.errors"); rb_gc_register_address(&rack_errors_val);
551
574
  rack_input_val = rb_str_new_cstr("rack.input"); rb_gc_register_address(&rack_input_val);
575
+ rack_logger_val = rb_str_new_cstr("rack.logger"); rb_gc_register_address(&rack_logger_val);
552
576
  rack_multiprocess_val = rb_str_new_cstr("rack.multiprocess");rb_gc_register_address(&rack_multiprocess_val);
553
577
  rack_multithread_val = rb_str_new_cstr("rack.multithread");rb_gc_register_address(&rack_multithread_val);
554
578
  rack_run_once_val = rb_str_new_cstr("rack.run_once"); rb_gc_register_address(&rack_run_once_val);
data/ext/agoo/server.c CHANGED
@@ -875,6 +875,20 @@ handle_not_found(VALUE self, VALUE handler) {
875
875
  return Qnil;
876
876
  }
877
877
 
878
+ /* Document-method: add_mime
879
+ *
880
+ * call-seq: add_mime(suffix, type)
881
+ *
882
+ * Adds a mime type by associating a type string with a suffix. This is used
883
+ * for static files.
884
+ */
885
+ static VALUE
886
+ add_mime(VALUE self, VALUE suffix, VALUE type) {
887
+ mime_set(&((Server)DATA_PTR(self))->pages, StringValuePtr(suffix), StringValuePtr(type));
888
+
889
+ return Qnil;
890
+ }
891
+
878
892
  /* Document-class: Agoo::Server
879
893
  *
880
894
  * An HTTP server that support the rack API as well as some other optimized
@@ -905,6 +919,7 @@ server_init(VALUE mod) {
905
919
 
906
920
  rb_define_method(server_class, "handle", handle, 3);
907
921
  rb_define_method(server_class, "handle_not_found", handle_not_found, 1);
922
+ rb_define_method(server_class, "add_mime", add_mime, 2);
908
923
 
909
924
  call_id = rb_intern("call");
910
925
  each_id = rb_intern("each");
data/lib/agoo.rb CHANGED
@@ -1,6 +1,4 @@
1
1
 
2
- # Agoo is the module that includes an HTTP server. The word agoo is a Japanese
3
- # word for a type of flying fish.
4
2
  module Agoo
5
3
  end
6
4
 
data/lib/agoo/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Agoo
3
3
  # Agoo version.
4
- VERSION = '1.0.0'
4
+ VERSION = '1.1.0'
5
5
  end
@@ -109,6 +109,7 @@ class BaseHandlerTest < Minitest::Test
109
109
  "rack.run_once" => false,
110
110
  "rack.url_scheme" => "http",
111
111
  "rack.version" => "1.3",
112
+ "rack.logger" => nil,
112
113
  }
113
114
  expect.each_pair { |k,v|
114
115
  if v.nil?
@@ -57,7 +57,6 @@ class RackHandlerTest < Minitest::Test
57
57
  response: false,
58
58
  eval: true,
59
59
  })
60
- #sleep(100)
61
60
 
62
61
  handler = TellMeHandler.new
63
62
  server.handle(:GET, "/tellme", handler)
data/test/static_test.rb CHANGED
@@ -30,8 +30,10 @@ class StaticTest < Minitest::Test
30
30
  response: false,
31
31
  eval: true,
32
32
  })
33
+ server.add_mime('odd', 'text/odd')
33
34
  server.start()
34
35
  fetch_index_test
36
+ mime_test
35
37
  fetch_auto_index_test
36
38
  fetch_nested_test
37
39
  fetch_not_found_test
@@ -43,7 +45,12 @@ class StaticTest < Minitest::Test
43
45
 
44
46
  def fetch_index_test
45
47
  uri = URI('http://localhost:6466/index.html')
46
- content = Net::HTTP.get(uri)
48
+ req = Net::HTTP::Get.new(uri)
49
+ res = Net::HTTP.start(uri.hostname, uri.port) { |h|
50
+ h.request(req)
51
+ }
52
+ content = res.body
53
+ assert_equal('text/html', res['Content-Type'])
47
54
  expect = %|<!DOCTYPE html>
48
55
  <html>
49
56
  <head><title>Agoo Test</title></head>
@@ -53,6 +60,15 @@ class StaticTest < Minitest::Test
53
60
  assert_equal(expect, content)
54
61
  end
55
62
 
63
+ def mime_test
64
+ uri = URI('http://localhost:6466/odd.odd')
65
+ req = Net::HTTP::Get.new(uri)
66
+ res = Net::HTTP.start(uri.hostname, uri.port) { |h|
67
+ h.request(req)
68
+ }
69
+ assert_equal('text/odd', res['Content-Type'])
70
+ end
71
+
56
72
  def fetch_auto_index_test
57
73
  uri = URI('http://localhost:6466/')
58
74
  content = Net::HTTP.get(uri)
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: 1.0.0
4
+ version: 1.1.0
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-02-06 00:00:00.000000000 Z
11
+ date: 2018-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -103,6 +103,8 @@ files:
103
103
  - ext/agoo/page.h
104
104
  - ext/agoo/queue.c
105
105
  - ext/agoo/queue.h
106
+ - ext/agoo/rack_logger.c
107
+ - ext/agoo/rack_logger.h
106
108
  - ext/agoo/request.c
107
109
  - ext/agoo/request.h
108
110
  - ext/agoo/res.c
@@ -132,7 +134,9 @@ rdoc_options:
132
134
  - "-m"
133
135
  - README.md
134
136
  - "-x"
135
- - test/*
137
+ - '"test/*"'
138
+ - "-x"
139
+ - extconf.rb
136
140
  require_paths:
137
141
  - lib
138
142
  required_ruby_version: !ruby/object:Gem::Requirement