aspirin 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|