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 +4 -4
- data/README.md +7 -1
- data/ext/agoo/agoo.c +7 -0
- data/ext/agoo/page.c +125 -28
- data/ext/agoo/page.h +14 -0
- data/ext/agoo/rack_logger.c +162 -0
- data/ext/agoo/rack_logger.h +13 -0
- data/ext/agoo/request.c +24 -0
- data/ext/agoo/server.c +15 -0
- data/lib/agoo.rb +0 -2
- data/lib/agoo/version.rb +1 -1
- data/test/base_handler_test.rb +1 -0
- data/test/rack_handler_test.rb +0 -1
- data/test/static_test.rb +17 -1
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6e35f7871e0927d3f8f560b3d9b529507ae392867aca53a9665c275a627070d5
|
4
|
+
data.tar.gz: 79a0b47f55c6b823844cf4e1679a068b0329ac407f9495bb1b5e6c3ad1b4f8de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 [
|
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
|
-
|
76
|
-
|
77
|
-
|
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
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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 (
|
87
|
-
|
88
|
-
|
89
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
data/lib/agoo/version.rb
CHANGED
data/test/base_handler_test.rb
CHANGED
data/test/rack_handler_test.rb
CHANGED
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
|
-
|
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.
|
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-
|
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
|