aspirin 0.0.0 → 0.0.1
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.
- data/VERSION +1 -1
- data/ext/aspirin.c +132 -177
- data/ext/aspirin.h +87 -0
- metadata +4 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.1
|
data/ext/aspirin.c
CHANGED
@@ -1,19 +1,4 @@
|
|
1
|
-
#include
|
2
|
-
#ifdef HAVE_RUBY_ST_H
|
3
|
-
#include <ruby/st.h>
|
4
|
-
#else
|
5
|
-
#include <st.h>
|
6
|
-
#endif
|
7
|
-
#include <signal.h>
|
8
|
-
#include <sys/queue.h>
|
9
|
-
#include <stdio.h>
|
10
|
-
#include <ctype.h>
|
11
|
-
|
12
|
-
#include <event.h>
|
13
|
-
#include <evhttp.h>
|
14
|
-
#include <evutil.h>
|
15
|
-
|
16
|
-
#define INSPECT(obj) {VALUE __obj__ = rb_inspect((obj)); fprintf(stderr, "%d:%s\n", __LINE__, RSTRING_PTR(__obj__));}
|
1
|
+
#include "aspirin.h"
|
17
2
|
|
18
3
|
static VALUE rb_mAspirin;
|
19
4
|
static VALUE rb_cAspirin_Server;
|
@@ -26,79 +11,21 @@ static const char* const status_code_str[] = {
|
|
26
11
|
"Continue","Switching Protocols","Processing","OK","Created","Accepted","Non-Authoritative Information","No Content","Reset Content","Partial Content","Multi-Status","Already Reported","IM Used","Multiple Choices","Moved Permanently","Found","See Other","Not Modified","Use Proxy","","Temporary Redirect","Bad Request","Unauthorized","Payment Required","Forbidden","Not Found","Method Not Allowed","Not Acceptable","Proxy Authentication Required","Request Timeout","Conflict","Gone","Length Required","Precondition Failed","Request Entity Too Large","Request-URI Too Long","Unsupported Media Type","Requested Range Not Satisfiable","Expectation Failed","","","Unprocessable Entity","Locked","Failed Dependency","","Upgrade Required","Internal Server Error","Not Implemented","Bad Gateway","Service Unavailable","Gateway Timeout","HTTP Version Not Supported","Variant Also Negotiates","Insufficient Storage","Loop Detected","Not Extended"
|
27
12
|
};
|
28
13
|
static VALUE default_env;
|
29
|
-
|
30
|
-
typedef struct
|
31
|
-
{
|
32
|
-
struct event_base* base;
|
33
|
-
struct evhttp* http;
|
34
|
-
struct event signal;
|
35
|
-
VALUE app;
|
36
|
-
VALUE options;
|
37
|
-
VALUE env;
|
38
|
-
} Aspirin_Server;
|
39
|
-
|
40
|
-
// Aspirin::Server.new
|
41
|
-
static VALUE aspirin_server_initialize(VALUE, VALUE, VALUE);
|
42
|
-
// Aspirin::Server.start
|
43
|
-
static VALUE aspirin_server_start(VALUE);
|
44
|
-
// Rack::Handler::Aspirin.run
|
45
|
-
static VALUE rack_handler_aspirin_run(int, VALUE*, VALUE);
|
46
|
-
|
47
|
-
static VALUE aspirin_server_address(VALUE);
|
48
|
-
static int aspirin_server_port(VALUE);
|
49
|
-
|
50
|
-
static VALUE aspirin_server_alloc(VALUE);
|
51
|
-
static void aspirin_server_mark(Aspirin_Server*);
|
52
|
-
static void aspirin_server_free(Aspirin_Server*);
|
53
|
-
|
54
|
-
static void aspirin_server_http_request(struct evhttp_request*, void*);
|
55
|
-
static VALUE aspirin_server_create_env(struct evhttp_request*, Aspirin_Server*);
|
56
|
-
|
57
|
-
static void aspirin_server_base_initialize(Aspirin_Server*);
|
58
|
-
static void aspirin_server_signal_initialize(Aspirin_Server*);
|
59
|
-
static void aspirin_server_sigint(int, short, void*);
|
60
|
-
static void aspirin_server_http_initialize(Aspirin_Server*);
|
61
|
-
|
62
|
-
static void set_http_version(VALUE, struct evhttp_request*);
|
63
|
-
static void set_path_info(VALUE, struct evhttp_request*);
|
64
|
-
static void set_response_header(struct evhttp_request*, VALUE);
|
65
|
-
static void set_additional_header(struct evhttp_request*);
|
66
|
-
|
67
|
-
static void init_default_env();
|
68
|
-
static VALUE dupe_default_env();
|
69
|
-
static void init_status_code_tbl();
|
70
|
-
static char* get_status_code_message(int);
|
71
|
-
|
72
|
-
static char* upcase(char*);
|
73
|
-
static char* hyphen_to_under(char*);
|
14
|
+
static VALUE global_envs[GLOBAL_ENVS_NUM];
|
74
15
|
|
75
16
|
static void
|
76
17
|
init_default_env()
|
77
18
|
{
|
78
|
-
VALUE rack_url_scheme, rack_version, gateway_interface, server_protocol, script_name;
|
79
|
-
|
80
|
-
rack_url_scheme = rb_str_new2("http");
|
81
|
-
rack_version = rb_ary_new3(2, INT2FIX(1), INT2FIX(1));
|
82
|
-
gateway_interface = rb_str_new2("CGI/1.2");
|
83
|
-
server_protocol = rb_str_new2("HTTP/1.1");
|
84
|
-
script_name = rb_str_new2("");
|
85
|
-
|
86
|
-
OBJ_FREEZE(rack_url_scheme);
|
87
|
-
OBJ_FREEZE(rack_version);
|
88
|
-
OBJ_FREEZE(gateway_interface);
|
89
|
-
OBJ_FREEZE(server_protocol);
|
90
|
-
OBJ_FREEZE(script_name);
|
91
|
-
|
92
19
|
default_env = rb_hash_new();
|
93
20
|
|
94
21
|
rb_hash_aset(default_env, rb_str_new2("rack.multiprocess"), Qfalse);
|
95
22
|
rb_hash_aset(default_env, rb_str_new2("rack.multithread"), Qfalse);
|
96
23
|
rb_hash_aset(default_env, rb_str_new2("rack.run_once"), Qfalse);
|
97
|
-
rb_hash_aset(default_env, rb_str_new2("rack.url_scheme"),
|
98
|
-
rb_hash_aset(default_env, rb_str_new2("rack.version"),
|
99
|
-
rb_hash_aset(default_env, rb_str_new2("GATEWAY_INTERFACE"),
|
100
|
-
rb_hash_aset(default_env, rb_str_new2("SCRIPT_NAME"),
|
101
|
-
rb_hash_aset(default_env, rb_str_new2("SERVER_PROTOCOL"),
|
24
|
+
rb_hash_aset(default_env, rb_str_new2("rack.url_scheme"), rb_obj_freeze(rb_str_new2("http")));
|
25
|
+
rb_hash_aset(default_env, rb_str_new2("rack.version"), rb_obj_freeze(rb_ary_new3(2, INT2FIX(1), INT2FIX(1))));
|
26
|
+
rb_hash_aset(default_env, rb_str_new2("GATEWAY_INTERFACE"), rb_obj_freeze(rb_str_new2("CGI/1.2")));
|
27
|
+
rb_hash_aset(default_env, rb_str_new2("SCRIPT_NAME"), rb_obj_freeze(rb_str_new2("")));
|
28
|
+
rb_hash_aset(default_env, rb_str_new2("SERVER_PROTOCOL"), rb_obj_freeze(rb_str_new2("HTTP/1.1")));
|
102
29
|
}
|
103
30
|
|
104
31
|
static VALUE
|
@@ -107,6 +34,30 @@ dupe_default_env()
|
|
107
34
|
return rb_funcall(default_env, rb_intern("dup"), 0);
|
108
35
|
}
|
109
36
|
|
37
|
+
static void
|
38
|
+
init_global_envs()
|
39
|
+
{
|
40
|
+
int i;
|
41
|
+
global_envs[GE_GET ] = rb_str_new2("GET");
|
42
|
+
global_envs[GE_HEAD ] = rb_str_new2("HEAD");
|
43
|
+
global_envs[GE_HTTP_VERSION ] = rb_str_new2("HTTP_VERSION");
|
44
|
+
global_envs[GE_PATH_INFO ] = rb_str_new2("PATH_INFO");
|
45
|
+
global_envs[GE_POST ] = rb_str_new2("POST");
|
46
|
+
global_envs[GE_QUERY_STRING ] = rb_str_new2("QUERY_STRING");
|
47
|
+
global_envs[GE_RACK_ERRORS ] = rb_str_new2("rack.errors");
|
48
|
+
global_envs[GE_RACK_INPUT ] = rb_str_new2("rack.input");
|
49
|
+
global_envs[GE_REMOTE_ADDR ] = rb_str_new2("REMOTE_ADDR");
|
50
|
+
global_envs[GE_REQUEST_METHOD] = rb_str_new2("REQUEST_METHOD");
|
51
|
+
global_envs[GE_REQUEST_PATH ] = rb_str_new2("REQUEST_PATH");
|
52
|
+
global_envs[GE_REQUEST_URI ] = rb_str_new2("REQUEST_URI");
|
53
|
+
global_envs[GE_SERVER_NAME ] = rb_str_new2("SERVER_NAME");
|
54
|
+
global_envs[GE_SERVER_PORT ] = rb_str_new2("SERVER_PORT");
|
55
|
+
for(i=0; i<GLOBAL_ENVS_NUM; i++)
|
56
|
+
{
|
57
|
+
global_envs[i] = rb_obj_freeze(global_envs[i]);
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
110
61
|
static void
|
111
62
|
init_status_code_tbl()
|
112
63
|
{
|
@@ -131,7 +82,7 @@ set_http_version(VALUE env, struct evhttp_request *req)
|
|
131
82
|
{
|
132
83
|
char buf[8 + 1]; // HTTP/x.y
|
133
84
|
snprintf(buf, 9, "HTTP/%d.%d", req->major, req->minor);
|
134
|
-
rb_hash_aset(env,
|
85
|
+
rb_hash_aset(env, global_envs[GE_HTTP_VERSION], rb_obj_freeze(rb_str_new2(buf)));
|
135
86
|
}
|
136
87
|
|
137
88
|
static void
|
@@ -157,12 +108,12 @@ set_path_info(VALUE env, struct evhttp_request *req)
|
|
157
108
|
request_uri = rb_str_new2(buf);
|
158
109
|
query_string = rb_str_new2(query);
|
159
110
|
|
160
|
-
|
161
|
-
|
111
|
+
rb_obj_freeze(request_uri);
|
112
|
+
rb_obj_freeze(query_string);
|
162
113
|
|
163
|
-
rb_hash_aset(env,
|
164
|
-
rb_hash_aset(env,
|
165
|
-
rb_hash_aset(env,
|
114
|
+
rb_hash_aset(env, global_envs[GE_PATH_INFO], request_uri);
|
115
|
+
rb_hash_aset(env, global_envs[GE_REQUEST_PATH], request_uri);
|
116
|
+
rb_hash_aset(env, global_envs[GE_QUERY_STRING], query_string);
|
166
117
|
|
167
118
|
xfree(buf);
|
168
119
|
}
|
@@ -173,7 +124,6 @@ set_http_header(VALUE env, struct evhttp_request *req)
|
|
173
124
|
char *buf;
|
174
125
|
size_t len;
|
175
126
|
struct evkeyval *header;
|
176
|
-
VALUE key, val;
|
177
127
|
|
178
128
|
TAILQ_FOREACH(header, req->input_headers, next)
|
179
129
|
{
|
@@ -187,10 +137,7 @@ set_http_header(VALUE env, struct evhttp_request *req)
|
|
187
137
|
buf[len + 5] = '\0';
|
188
138
|
hyphen_to_under(upcase(buf));
|
189
139
|
|
190
|
-
|
191
|
-
val = rb_str_new2(header->value);
|
192
|
-
OBJ_FREEZE(val);
|
193
|
-
rb_hash_aset(env, key, val);
|
140
|
+
rb_hash_aset(env, rb_str_new2(buf), rb_obj_freeze(rb_str_new2(header->value)));
|
194
141
|
|
195
142
|
xfree(buf);
|
196
143
|
}
|
@@ -200,37 +147,36 @@ set_http_header(VALUE env, struct evhttp_request *req)
|
|
200
147
|
static VALUE
|
201
148
|
aspirin_server_create_env(struct evhttp_request *req, Aspirin_Server *srv)
|
202
149
|
{
|
203
|
-
VALUE env, rack_input, strio, remote_host, request_uri
|
150
|
+
VALUE env, rack_input, strio, remote_host, request_uri;
|
204
151
|
|
205
152
|
env = rb_funcall(srv->env, rb_intern("dup"), 0);
|
206
153
|
|
207
|
-
rb_hash_aset(env,
|
154
|
+
rb_hash_aset(env, global_envs[GE_RACK_ERRORS], rb_gv_get("$stderr"));
|
208
155
|
|
209
156
|
rack_input = rb_str_new((const char*)EVBUFFER_DATA(req->input_buffer),
|
210
157
|
EVBUFFER_LENGTH(req->input_buffer));
|
211
|
-
|
158
|
+
rb_obj_freeze(rack_input);
|
212
159
|
strio = rb_funcall(rb_cStringIO, rb_intern("new"), 1, rack_input);
|
213
|
-
rb_hash_aset(env,
|
160
|
+
rb_hash_aset(env, global_envs[GE_RACK_INPUT], strio);
|
214
161
|
|
215
|
-
|
216
|
-
|
217
|
-
|
162
|
+
rb_hash_aset(env,
|
163
|
+
global_envs[GE_REMOTE_ADDR],
|
164
|
+
rb_obj_freeze(rb_str_new2(req->remote_host)));
|
218
165
|
|
219
|
-
|
220
|
-
|
221
|
-
|
166
|
+
rb_hash_aset(env,
|
167
|
+
global_envs[GE_REQUEST_URI],
|
168
|
+
rb_obj_freeze(rb_str_new2(evhttp_request_uri(req))));
|
222
169
|
|
223
|
-
method = rb_str_new2("REQUEST_METHOD");
|
224
170
|
switch(req->type)
|
225
171
|
{
|
226
172
|
case EVHTTP_REQ_GET:
|
227
|
-
rb_hash_aset(env,
|
173
|
+
rb_hash_aset(env, global_envs[GE_REQUEST_METHOD], global_envs[GE_GET]);
|
228
174
|
break;
|
229
175
|
case EVHTTP_REQ_POST:
|
230
|
-
rb_hash_aset(env,
|
176
|
+
rb_hash_aset(env, global_envs[GE_REQUEST_METHOD], global_envs[GE_POST]);
|
231
177
|
break;
|
232
178
|
case EVHTTP_REQ_HEAD:
|
233
|
-
rb_hash_aset(env,
|
179
|
+
rb_hash_aset(env, global_envs[GE_REQUEST_METHOD], global_envs[GE_HEAD]);
|
234
180
|
break;
|
235
181
|
}
|
236
182
|
|
@@ -271,13 +217,39 @@ set_additional_header(struct evhttp_request *req)
|
|
271
217
|
evhttp_add_header(req->output_headers, "Connection", "close");
|
272
218
|
}
|
273
219
|
|
220
|
+
static VALUE
|
221
|
+
body_concat(VALUE chunk, VALUE* buff)
|
222
|
+
{
|
223
|
+
struct evbuffer *buf = DATA_PTR(*buff);
|
224
|
+
StringValue(chunk);
|
225
|
+
evbuffer_add(buf, RSTRING_PTR(chunk), RSTRING_LEN(chunk));
|
226
|
+
return Qnil;
|
227
|
+
}
|
228
|
+
|
229
|
+
static VALUE
|
230
|
+
body_each(VALUE body)
|
231
|
+
{
|
232
|
+
VALUE data = rb_ary_entry(body, 1);
|
233
|
+
rb_iterate(rb_each, rb_ary_entry(body, 0), body_concat, (VALUE)&data);
|
234
|
+
return Qnil;
|
235
|
+
}
|
236
|
+
|
237
|
+
static VALUE
|
238
|
+
body_close(VALUE body)
|
239
|
+
{
|
240
|
+
if(rb_respond_to(body, rb_intern("close")))
|
241
|
+
{
|
242
|
+
rb_funcall(body, rb_intern("close"), 0);
|
243
|
+
}
|
244
|
+
return Qnil;
|
245
|
+
}
|
246
|
+
|
274
247
|
static void
|
275
248
|
aspirin_server_http_request(struct evhttp_request *req, void *arg)
|
276
249
|
{
|
277
|
-
static VALUE args[][1] = {{INT2FIX(0)},{INT2FIX(1)},{INT2FIX(2)}};
|
278
250
|
struct evbuffer *buf;
|
279
251
|
Aspirin_Server *srv;
|
280
|
-
VALUE env, result,
|
252
|
+
VALUE env, result, body, buff;
|
281
253
|
int status_code;
|
282
254
|
char *status_code_msg;
|
283
255
|
|
@@ -285,22 +257,25 @@ aspirin_server_http_request(struct evhttp_request *req, void *arg)
|
|
285
257
|
env = aspirin_server_create_env(req, srv);
|
286
258
|
result = rb_funcall(srv->app, rb_intern("call"), 1, env);
|
287
259
|
|
288
|
-
status_code = NUM2INT(
|
260
|
+
status_code = NUM2INT(rb_ary_entry(result, 0));
|
289
261
|
status_code_msg = get_status_code_message(status_code);
|
290
262
|
if(status_code_msg == NULL)
|
291
263
|
{
|
292
264
|
status_code_msg = "";
|
293
265
|
}
|
294
266
|
|
295
|
-
set_response_header(req,
|
267
|
+
set_response_header(req, rb_ary_entry(result, 1));
|
296
268
|
set_additional_header(req);
|
297
269
|
|
298
|
-
|
270
|
+
buff = Data_Wrap_Struct(rb_cData, 0, 0, 0);
|
271
|
+
DATA_PTR(buff) = req->output_buffer;
|
272
|
+
|
273
|
+
body = rb_ary_new3(2, rb_ary_entry(result, 2), buff);
|
274
|
+
|
275
|
+
rb_ensure(body_each, body, body_close, rb_ary_entry(result, 2));
|
276
|
+
evhttp_send_reply(req, status_code, status_code_msg, NULL);
|
299
277
|
|
300
|
-
|
301
|
-
evbuffer_add(buf, RSTRING_PTR(bodies), RSTRING_LEN(bodies));
|
302
|
-
evhttp_send_reply(req, status_code, status_code_msg, buf);
|
303
|
-
evbuffer_free(buf);
|
278
|
+
DATA_PTR(buff) = NULL;
|
304
279
|
}
|
305
280
|
|
306
281
|
static Aspirin_Server*
|
@@ -368,7 +343,9 @@ aspirin_server_free(Aspirin_Server* srv)
|
|
368
343
|
return;
|
369
344
|
}
|
370
345
|
|
371
|
-
event_del(&srv->
|
346
|
+
event_del(&srv->sig_int);
|
347
|
+
event_del(&srv->sig_quit);
|
348
|
+
event_del(&srv->sig_term);
|
372
349
|
|
373
350
|
if(srv->http)
|
374
351
|
{
|
@@ -393,11 +370,18 @@ aspirin_server_alloc(VALUE klass)
|
|
393
370
|
}
|
394
371
|
|
395
372
|
static void
|
396
|
-
|
373
|
+
aspirin_server_stop_bang(int fd, short event, void *arg)
|
374
|
+
{
|
375
|
+
Aspirin_Server *srv = arg;
|
376
|
+
event_base_loopbreak(srv->base);
|
377
|
+
}
|
378
|
+
|
379
|
+
static void
|
380
|
+
aspirin_server_stop(int fd, short event, void *arg)
|
397
381
|
{
|
398
382
|
Aspirin_Server *srv = arg;
|
399
383
|
struct timeval delay = {1, 0};
|
400
|
-
event_del(&srv->
|
384
|
+
event_del(&srv->sig_quit);
|
401
385
|
event_base_loopexit(srv->base, &delay);
|
402
386
|
}
|
403
387
|
|
@@ -407,61 +391,21 @@ aspirin_server_port(VALUE options)
|
|
407
391
|
VALUE port = Qnil;
|
408
392
|
if(TYPE(options) == T_HASH)
|
409
393
|
{
|
410
|
-
port = rb_hash_aref(options, ID2SYM(rb_intern("port")));
|
411
|
-
if(!NIL_P(port)){
|
412
|
-
return NUM2INT(port);
|
413
|
-
}
|
414
|
-
port = rb_hash_aref(options, rb_str_new2("port"));
|
415
|
-
if(!NIL_P(port)){
|
416
|
-
return NUM2INT(port);
|
417
|
-
}
|
418
394
|
port = rb_hash_aref(options, ID2SYM(rb_intern("Port")));
|
419
395
|
if(!NIL_P(port)){
|
420
396
|
return NUM2INT(port);
|
421
397
|
}
|
422
|
-
port = rb_hash_aref(options, rb_str_new2("Port"));
|
423
|
-
if(!NIL_P(port)){
|
424
|
-
return NUM2INT(port);
|
425
|
-
}
|
426
|
-
port = rb_hash_aref(options, ID2SYM(rb_intern("PORT")));
|
427
|
-
if(!NIL_P(port)){
|
428
|
-
return NUM2INT(port);
|
429
|
-
}
|
430
|
-
port = rb_hash_aref(options, rb_str_new2("PORT"));
|
431
|
-
if(!NIL_P(port)){
|
432
|
-
return NUM2INT(port);
|
433
|
-
}
|
434
398
|
}
|
435
399
|
return 9292;
|
436
400
|
}
|
437
401
|
|
438
402
|
static VALUE
|
439
|
-
|
403
|
+
aspirin_server_host(VALUE options)
|
440
404
|
{
|
441
405
|
VALUE address = Qnil;
|
442
406
|
if(TYPE(options) == T_HASH)
|
443
407
|
{
|
444
|
-
address = rb_hash_aref(options, ID2SYM(rb_intern("
|
445
|
-
if(!NIL_P(address)){
|
446
|
-
return address;
|
447
|
-
}
|
448
|
-
address = rb_hash_aref(options, rb_str_new2("address"));
|
449
|
-
if(!NIL_P(address)){
|
450
|
-
return address;
|
451
|
-
}
|
452
|
-
address = rb_hash_aref(options, ID2SYM(rb_intern("Address")));
|
453
|
-
if(!NIL_P(address)){
|
454
|
-
return address;
|
455
|
-
}
|
456
|
-
address = rb_hash_aref(options, rb_str_new2("Address"));
|
457
|
-
if(!NIL_P(address)){
|
458
|
-
return address;
|
459
|
-
}
|
460
|
-
address = rb_hash_aref(options, ID2SYM(rb_intern("ADDRESS")));
|
461
|
-
if(!NIL_P(address)){
|
462
|
-
return address;
|
463
|
-
}
|
464
|
-
address = rb_hash_aref(options, rb_str_new2("ADDRESS"));
|
408
|
+
address = rb_hash_aref(options, ID2SYM(rb_intern("Host")));
|
465
409
|
if(!NIL_P(address)){
|
466
410
|
return address;
|
467
411
|
}
|
@@ -478,26 +422,34 @@ aspirin_server_base_initialize(Aspirin_Server *srv)
|
|
478
422
|
static void
|
479
423
|
aspirin_server_signal_initialize(Aspirin_Server *srv)
|
480
424
|
{
|
481
|
-
event_set(&srv->
|
482
|
-
event_base_set(srv->base, &srv->
|
483
|
-
event_add(&srv->
|
425
|
+
event_set(&srv->sig_quit, SIGQUIT, EV_SIGNAL|EV_PERSIST, aspirin_server_stop, srv);
|
426
|
+
event_base_set(srv->base, &srv->sig_quit);
|
427
|
+
event_add(&srv->sig_quit, NULL);
|
428
|
+
|
429
|
+
event_set(&srv->sig_int, SIGINT, EV_SIGNAL|EV_PERSIST, aspirin_server_stop_bang, srv);
|
430
|
+
event_base_set(srv->base, &srv->sig_int);
|
431
|
+
event_add(&srv->sig_int, NULL);
|
432
|
+
|
433
|
+
event_set(&srv->sig_term, SIGTERM, EV_SIGNAL|EV_PERSIST, aspirin_server_stop_bang, srv);
|
434
|
+
event_base_set(srv->base, &srv->sig_term);
|
435
|
+
event_add(&srv->sig_term, NULL);
|
484
436
|
}
|
485
437
|
|
486
438
|
static void
|
487
439
|
aspirin_server_http_initialize(Aspirin_Server *srv)
|
488
440
|
{
|
489
|
-
VALUE
|
441
|
+
VALUE host = aspirin_server_host(srv->options);
|
490
442
|
int port = aspirin_server_port(srv->options);
|
491
443
|
|
492
|
-
StringValue(
|
493
|
-
rb_hash_aset(srv->env,
|
444
|
+
StringValue(host);
|
445
|
+
rb_hash_aset(srv->env, global_envs[GE_SERVER_NAME], host);
|
494
446
|
|
495
447
|
char port_str[6];
|
496
448
|
snprintf(port_str, 5, "%d", port);
|
497
|
-
rb_hash_aset(srv->env,
|
449
|
+
rb_hash_aset(srv->env, global_envs[GE_SERVER_PORT], rb_str_new2(port_str));
|
498
450
|
|
499
451
|
srv->http = evhttp_new(srv->base);
|
500
|
-
evhttp_bind_socket(srv->http, RSTRING_PTR(
|
452
|
+
evhttp_bind_socket(srv->http, RSTRING_PTR(host), port);
|
501
453
|
evhttp_set_gencb(srv->http, aspirin_server_http_request, srv);
|
502
454
|
}
|
503
455
|
|
@@ -505,10 +457,10 @@ static char*
|
|
505
457
|
upcase(char* str)
|
506
458
|
{
|
507
459
|
if(str){
|
508
|
-
|
509
|
-
for(
|
460
|
+
char* tmp;
|
461
|
+
for(tmp=str; *tmp; tmp++)
|
510
462
|
{
|
511
|
-
|
463
|
+
*tmp = toupper(*tmp);
|
512
464
|
}
|
513
465
|
}
|
514
466
|
return str;
|
@@ -518,12 +470,12 @@ static char*
|
|
518
470
|
hyphen_to_under(char* str)
|
519
471
|
{
|
520
472
|
if(str){
|
521
|
-
|
522
|
-
for(
|
473
|
+
char* tmp;
|
474
|
+
for(tmp=str; *tmp; tmp++)
|
523
475
|
{
|
524
|
-
if(
|
476
|
+
if(*tmp == '-')
|
525
477
|
{
|
526
|
-
|
478
|
+
*tmp = '_';
|
527
479
|
}
|
528
480
|
}
|
529
481
|
}
|
@@ -544,8 +496,11 @@ rack_handler_aspirin_run(int argc, VALUE *argv, VALUE obj)
|
|
544
496
|
|
545
497
|
void Init_aspirin(void)
|
546
498
|
{
|
499
|
+
VALUE rb_mRack, rb_mRack_Handler, rb_mRack_Handler_Aspirin;
|
500
|
+
|
547
501
|
init_default_env();
|
548
502
|
init_status_code_tbl();
|
503
|
+
init_global_envs();
|
549
504
|
|
550
505
|
rb_require("stringio");
|
551
506
|
rb_cStringIO = rb_const_get(rb_cObject, rb_intern("StringIO"));
|
@@ -559,8 +514,8 @@ void Init_aspirin(void)
|
|
559
514
|
rb_define_method(rb_cAspirin_Server, "start", aspirin_server_start, 0);
|
560
515
|
|
561
516
|
// Rack::Handler::Aspirin
|
562
|
-
|
563
|
-
|
564
|
-
|
517
|
+
rb_mRack = rb_define_module("Rack");
|
518
|
+
rb_mRack_Handler = rb_define_module_under(rb_mRack, "Handler");
|
519
|
+
rb_mRack_Handler_Aspirin = rb_define_module_under(rb_mRack_Handler, "Aspirin");
|
565
520
|
rb_define_singleton_method(rb_mRack_Handler_Aspirin, "run", rack_handler_aspirin_run, -1);
|
566
521
|
}
|
data/ext/aspirin.h
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
#ifndef __ASPIRIN_H__
|
2
|
+
#define __ASPIRIN_H__
|
3
|
+
|
4
|
+
#include <ruby.h>
|
5
|
+
#ifdef HAVE_RUBY_ST_H
|
6
|
+
#include <ruby/st.h>
|
7
|
+
#else
|
8
|
+
#include <st.h>
|
9
|
+
#endif
|
10
|
+
|
11
|
+
#include <ctype.h>
|
12
|
+
#include <signal.h>
|
13
|
+
#include <stdio.h>
|
14
|
+
#include <sys/queue.h>
|
15
|
+
|
16
|
+
#include <event.h>
|
17
|
+
#include <evhttp.h>
|
18
|
+
#include <evutil.h>
|
19
|
+
|
20
|
+
#define INSPECT(obj) {VALUE __obj__ = rb_inspect((obj)); fprintf(stderr, "%d:%s\n", __LINE__, RSTRING_PTR(__obj__));}
|
21
|
+
|
22
|
+
enum{
|
23
|
+
GE_GET,
|
24
|
+
GE_HEAD,
|
25
|
+
GE_HTTP_VERSION,
|
26
|
+
GE_PATH_INFO,
|
27
|
+
GE_POST,
|
28
|
+
GE_QUERY_STRING,
|
29
|
+
GE_RACK_ERRORS,
|
30
|
+
GE_RACK_INPUT,
|
31
|
+
GE_REMOTE_ADDR,
|
32
|
+
GE_REQUEST_METHOD,
|
33
|
+
GE_REQUEST_PATH,
|
34
|
+
GE_REQUEST_URI,
|
35
|
+
GE_SERVER_NAME,
|
36
|
+
GE_SERVER_PORT,
|
37
|
+
GLOBAL_ENVS_NUM,
|
38
|
+
};
|
39
|
+
|
40
|
+
typedef struct
|
41
|
+
{
|
42
|
+
struct event_base* base;
|
43
|
+
struct evhttp* http;
|
44
|
+
struct event sig_int;
|
45
|
+
struct event sig_quit;
|
46
|
+
struct event sig_term;
|
47
|
+
VALUE app;
|
48
|
+
VALUE options;
|
49
|
+
VALUE env;
|
50
|
+
} Aspirin_Server;
|
51
|
+
|
52
|
+
// Aspirin::Server.new
|
53
|
+
static VALUE aspirin_server_initialize(VALUE, VALUE, VALUE);
|
54
|
+
// Aspirin::Server#start
|
55
|
+
static VALUE aspirin_server_start(VALUE);
|
56
|
+
// Rack::Handler::Aspirin.run
|
57
|
+
static VALUE rack_handler_aspirin_run(int, VALUE*, VALUE);
|
58
|
+
|
59
|
+
static VALUE aspirin_server_address(VALUE);
|
60
|
+
static int aspirin_server_port(VALUE);
|
61
|
+
|
62
|
+
static VALUE aspirin_server_alloc(VALUE);
|
63
|
+
static void aspirin_server_mark(Aspirin_Server*);
|
64
|
+
static void aspirin_server_free(Aspirin_Server*);
|
65
|
+
|
66
|
+
static void aspirin_server_http_request(struct evhttp_request*, void*);
|
67
|
+
static VALUE aspirin_server_create_env(struct evhttp_request*, Aspirin_Server*);
|
68
|
+
|
69
|
+
static void aspirin_server_base_initialize(Aspirin_Server*);
|
70
|
+
static void aspirin_server_signal_initialize(Aspirin_Server*);
|
71
|
+
static void aspirin_server_stop(int, short, void*);
|
72
|
+
static void aspirin_server_stop_bang(int, short, void*);
|
73
|
+
static void aspirin_server_http_initialize(Aspirin_Server*);
|
74
|
+
|
75
|
+
static void set_http_version(VALUE, struct evhttp_request*);
|
76
|
+
static void set_path_info(VALUE, struct evhttp_request*);
|
77
|
+
static void set_response_header(struct evhttp_request*, VALUE);
|
78
|
+
static void set_additional_header(struct evhttp_request*);
|
79
|
+
|
80
|
+
static void init_default_env();
|
81
|
+
static VALUE dupe_default_env();
|
82
|
+
static void init_status_code_tbl();
|
83
|
+
static char* get_status_code_message(int);
|
84
|
+
|
85
|
+
static char* upcase(char*);
|
86
|
+
static char* hyphen_to_under(char*);
|
87
|
+
#endif
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- fistfvck
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-06-
|
17
|
+
date: 2010-06-30 00:00:00 +09:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -51,6 +51,7 @@ files:
|
|
51
51
|
- example/test.rb
|
52
52
|
- example/thn.rb
|
53
53
|
- ext/aspirin.c
|
54
|
+
- ext/aspirin.h
|
54
55
|
- ext/extconf.rb
|
55
56
|
- spec/aspirin_spec.rb
|
56
57
|
- spec/spec.opts
|