rhebok 0.9.1 → 0.9.2
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.
- checksums.yaml +4 -4
- data/Changes +4 -0
- data/README.md +12 -7
- data/ext/rhebok/rhebok.c +154 -139
- data/lib/rhebok/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7cf21a4ceaeeaf1c6e72a19f59555508984ee6c6
|
4
|
+
data.tar.gz: 29b1d23eebdd7837be2af68adb2b6dabefea2590
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce57b5d0c2dc1f2c880f81255f2424f5157ffab68eff12bb2c898c4acfd5b478e4dc23b0cfe38ea9157cce6214c6e68ec28a597afe13eb887aa5446d2b18ef57
|
7
|
+
data.tar.gz: d590aec96108ede772c81176c385c3bb4a15d98b8ea41a527e5316cc9bfb86dbc954ca2fffc62bf4be2af931739e63b746ec0569e0aa369d644eabce558af940
|
data/Changes
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
# Rhebok
|
2
2
|
|
3
|
-
|
3
|
+

|
4
|
+
|
5
|
+
|
6
|
+
[](https://travis-ci.org/kazeburo/rhebok)
|
7
|
+
|
8
|
+
Rhebok is High Performance Rack Handler/Web Server. 2x performance when compared against Unicorn.
|
4
9
|
|
5
10
|
Rhebok supports following features.
|
6
11
|
|
@@ -9,7 +14,7 @@ Rhebok supports following features.
|
|
9
14
|
- uses writev(2) for output responses
|
10
15
|
- prefork and graceful shutdown using [prefork_engine](https://rubygems.org/gems/prefork_engine)
|
11
16
|
- hot deploy using [start_server](https://metacpan.org/release/Server-Starter) ([here](https://github.com/lestrrat/go-server-starter) is golang version by lestrrat-san)
|
12
|
-
- supports HTTP/1.1
|
17
|
+
- supports HTTP/1.1 except for KeepAlive
|
13
18
|
- supports OobGC
|
14
19
|
|
15
20
|
This server is suitable for running HTTP application servers behind a reverse proxy like nginx.
|
@@ -211,11 +216,11 @@ ruby version
|
|
211
216
|
nginx.conf
|
212
217
|
|
213
218
|
worker_processes 16;
|
214
|
-
|
219
|
+
|
215
220
|
events {
|
216
221
|
worker_connections 50000;
|
217
222
|
}
|
218
|
-
|
223
|
+
|
219
224
|
http {
|
220
225
|
include mime.types;
|
221
226
|
access_log off;
|
@@ -289,8 +294,8 @@ unicorn.rb
|
|
289
294
|
command to run
|
290
295
|
|
291
296
|
$ bundle exec unicorn -c unicorn.rb -E production config.ru
|
292
|
-
|
293
|
-
#### Hello World/Rack Application
|
297
|
+
|
298
|
+
#### Hello World/Rack Application
|
294
299
|
|
295
300
|
$ ./wrk -t 4 -c 500 -d 30 http://localhost/
|
296
301
|
Running 30s test @ http://localhost/
|
@@ -328,7 +333,7 @@ command to run
|
|
328
333
|
|
329
334
|
### Server Environment
|
330
335
|
|
331
|
-
I used EC2 for benchmarking. Instance type if c3.8xlarge(32cores). A benchmark tool and web servers were executed at same hosts. Before benchmark, increase somaxconn and nfiles.
|
336
|
+
I used EC2 for benchmarking. Instance type if c3.8xlarge(32cores). A benchmark tool and web servers were executed at same hosts. Before benchmark, increase somaxconn and nfiles.
|
332
337
|
|
333
338
|
## See Also
|
334
339
|
|
data/ext/rhebok/rhebok.c
CHANGED
@@ -35,6 +35,7 @@
|
|
35
35
|
#define EXPECT_FAILED "HTTP/1.1 417 Expectation Failed\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nExpectation Failed\r\n"
|
36
36
|
#define READ_BUF 16384
|
37
37
|
#define TOU(ch) (('a' <= ch && ch <= 'z') ? ch - ('a' - 'A') : ch)
|
38
|
+
#define RETURN_STATUS_MESSAGE(s, l) l = sizeof(s) - 1; return s;
|
38
39
|
|
39
40
|
static const char *DoW[] = {
|
40
41
|
"Sun","Mon","Tue","Wed","Thu","Fri","Sat"
|
@@ -49,84 +50,84 @@ static const char xdigit[16] = {'0','1','2','3','4','5','6','7','8','9','a','b',
|
|
49
50
|
/* Unmarked codes are from RFC 2616 */
|
50
51
|
/* See also: http://en.wikipedia.org/wiki/List_of_HTTP_status_codes */
|
51
52
|
static const char *
|
52
|
-
status_message (int code) {
|
53
|
+
status_message (int code, size_t *mlen) {
|
53
54
|
switch (code) {
|
54
|
-
case 100:
|
55
|
-
case 101:
|
56
|
-
case 102:
|
57
|
-
case 200:
|
58
|
-
case 201:
|
59
|
-
case 202:
|
60
|
-
case 203:
|
61
|
-
case 204:
|
62
|
-
case 205:
|
63
|
-
case 206:
|
64
|
-
case 207:
|
65
|
-
case 208:
|
66
|
-
case 300:
|
67
|
-
case 301:
|
68
|
-
case 302:
|
69
|
-
case 303:
|
70
|
-
case 304:
|
71
|
-
case 305:
|
72
|
-
case 307:
|
73
|
-
case 400:
|
74
|
-
case 401:
|
75
|
-
case 402:
|
76
|
-
case 403:
|
77
|
-
case 404:
|
78
|
-
case 405:
|
79
|
-
case 406:
|
80
|
-
case 407:
|
81
|
-
case 408:
|
82
|
-
case 409:
|
83
|
-
case 410:
|
84
|
-
case 411:
|
85
|
-
case 412:
|
86
|
-
case 413:
|
87
|
-
case 414:
|
88
|
-
case 415:
|
89
|
-
case 416:
|
90
|
-
case 417:
|
91
|
-
case 418:
|
92
|
-
case 422:
|
93
|
-
case 423:
|
94
|
-
case 424:
|
95
|
-
case 425:
|
96
|
-
case 426:
|
97
|
-
case 428:
|
98
|
-
case 429:
|
99
|
-
case 431:
|
100
|
-
case 449:
|
101
|
-
case 500:
|
102
|
-
case 501:
|
103
|
-
case 502:
|
104
|
-
case 503:
|
105
|
-
case 504:
|
106
|
-
case 505:
|
107
|
-
case 506:
|
108
|
-
case 507:
|
109
|
-
case 509:
|
110
|
-
case 510:
|
111
|
-
case 511:
|
55
|
+
case 100: RETURN_STATUS_MESSAGE("Continue", *mlen);
|
56
|
+
case 101: RETURN_STATUS_MESSAGE("Switching Protocols", *mlen);
|
57
|
+
case 102: RETURN_STATUS_MESSAGE("Processing", *mlen); /* RFC 2518 (WebDAV) */
|
58
|
+
case 200: RETURN_STATUS_MESSAGE("OK", *mlen);
|
59
|
+
case 201: RETURN_STATUS_MESSAGE("Created", *mlen);
|
60
|
+
case 202: RETURN_STATUS_MESSAGE("Accepted", *mlen);
|
61
|
+
case 203: RETURN_STATUS_MESSAGE("Non-Authoritative Information", *mlen);
|
62
|
+
case 204: RETURN_STATUS_MESSAGE("No Content", *mlen);
|
63
|
+
case 205: RETURN_STATUS_MESSAGE("Reset Content", *mlen);
|
64
|
+
case 206: RETURN_STATUS_MESSAGE("Partial Content", *mlen);
|
65
|
+
case 207: RETURN_STATUS_MESSAGE("Multi-Status", *mlen); /* RFC 2518 (WebDAV) */
|
66
|
+
case 208: RETURN_STATUS_MESSAGE("Already Reported", *mlen); /* RFC 5842 */
|
67
|
+
case 300: RETURN_STATUS_MESSAGE("Multiple Choices", *mlen);
|
68
|
+
case 301: RETURN_STATUS_MESSAGE("Moved Permanently", *mlen);
|
69
|
+
case 302: RETURN_STATUS_MESSAGE("Found", *mlen);
|
70
|
+
case 303: RETURN_STATUS_MESSAGE("See Other", *mlen);
|
71
|
+
case 304: RETURN_STATUS_MESSAGE("Not Modified", *mlen);
|
72
|
+
case 305: RETURN_STATUS_MESSAGE("Use Proxy", *mlen);
|
73
|
+
case 307: RETURN_STATUS_MESSAGE("Temporary Redirect", *mlen);
|
74
|
+
case 400: RETURN_STATUS_MESSAGE("Bad Request", *mlen);
|
75
|
+
case 401: RETURN_STATUS_MESSAGE("Unauthorized", *mlen);
|
76
|
+
case 402: RETURN_STATUS_MESSAGE("Payment Required", *mlen);
|
77
|
+
case 403: RETURN_STATUS_MESSAGE("Forbidden", *mlen);
|
78
|
+
case 404: RETURN_STATUS_MESSAGE("Not Found", *mlen);
|
79
|
+
case 405: RETURN_STATUS_MESSAGE("Method Not Allowed", *mlen);
|
80
|
+
case 406: RETURN_STATUS_MESSAGE("Not Acceptable", *mlen);
|
81
|
+
case 407: RETURN_STATUS_MESSAGE("Proxy Authentication Required", *mlen);
|
82
|
+
case 408: RETURN_STATUS_MESSAGE("Request Timeout", *mlen);
|
83
|
+
case 409: RETURN_STATUS_MESSAGE("Conflict", *mlen);
|
84
|
+
case 410: RETURN_STATUS_MESSAGE("Gone", *mlen);
|
85
|
+
case 411: RETURN_STATUS_MESSAGE("Length Required", *mlen);
|
86
|
+
case 412: RETURN_STATUS_MESSAGE("Precondition Failed", *mlen);
|
87
|
+
case 413: RETURN_STATUS_MESSAGE("Request Entity Too Large", *mlen);
|
88
|
+
case 414: RETURN_STATUS_MESSAGE("Request-URI Too Large", *mlen);
|
89
|
+
case 415: RETURN_STATUS_MESSAGE("Unsupported Media Type", *mlen);
|
90
|
+
case 416: RETURN_STATUS_MESSAGE("Request Range Not Satisfiable", *mlen);
|
91
|
+
case 417: RETURN_STATUS_MESSAGE("Expectation Failed", *mlen);
|
92
|
+
case 418: RETURN_STATUS_MESSAGE("I'm a teapot", *mlen); /* RFC 2324 */
|
93
|
+
case 422: RETURN_STATUS_MESSAGE("Unprocessable Entity", *mlen); /* RFC 2518 (WebDAV) */
|
94
|
+
case 423: RETURN_STATUS_MESSAGE("Locked", *mlen); /* RFC 2518 (WebDAV) */
|
95
|
+
case 424: RETURN_STATUS_MESSAGE("Failed Dependency", *mlen); /* RFC 2518 (WebDAV) */
|
96
|
+
case 425: RETURN_STATUS_MESSAGE("No code", *mlen); /* WebDAV Advanced Collections */
|
97
|
+
case 426: RETURN_STATUS_MESSAGE("Upgrade Required", *mlen); /* RFC 2817 */
|
98
|
+
case 428: RETURN_STATUS_MESSAGE("Precondition Required", *mlen);
|
99
|
+
case 429: RETURN_STATUS_MESSAGE("Too Many Requests", *mlen);
|
100
|
+
case 431: RETURN_STATUS_MESSAGE("Request Header Fields Too Large", *mlen);
|
101
|
+
case 449: RETURN_STATUS_MESSAGE("Retry with", *mlen); /* unofficial Microsoft */
|
102
|
+
case 500: RETURN_STATUS_MESSAGE("Internal Server Error", *mlen);
|
103
|
+
case 501: RETURN_STATUS_MESSAGE("Not Implemented", *mlen);
|
104
|
+
case 502: RETURN_STATUS_MESSAGE("Bad Gateway", *mlen);
|
105
|
+
case 503: RETURN_STATUS_MESSAGE("Service Unavailable", *mlen);
|
106
|
+
case 504: RETURN_STATUS_MESSAGE("Gateway Timeout", *mlen);
|
107
|
+
case 505: RETURN_STATUS_MESSAGE("HTTP Version Not Supported", *mlen);
|
108
|
+
case 506: RETURN_STATUS_MESSAGE("Variant Also Negotiates", *mlen); /* RFC 2295 */
|
109
|
+
case 507: RETURN_STATUS_MESSAGE("Insufficient Storage", *mlen); /* RFC 2518 (WebDAV) */
|
110
|
+
case 509: RETURN_STATUS_MESSAGE("Bandwidth Limit Exceeded", *mlen); /* unofficial */
|
111
|
+
case 510: RETURN_STATUS_MESSAGE("Not Extended", *mlen); /* RFC 2774 */
|
112
|
+
case 511: RETURN_STATUS_MESSAGE("Network Authentication Required", *mlen);
|
112
113
|
default: break;
|
113
114
|
}
|
114
115
|
/* default to the Nxx group names in RFC 2616 */
|
115
116
|
if (100 <= code && code <= 199) {
|
116
|
-
|
117
|
+
RETURN_STATUS_MESSAGE("Informational", *mlen);
|
117
118
|
}
|
118
119
|
else if (200 <= code && code <= 299) {
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
120
|
+
RETURN_STATUS_MESSAGE("Success", *mlen);
|
121
|
+
}
|
122
|
+
else if (300 <= code && code <= 399) {
|
123
|
+
RETURN_STATUS_MESSAGE("Redirection", *mlen);
|
124
|
+
}
|
125
|
+
else if (400 <= code && code <= 499) {
|
126
|
+
RETURN_STATUS_MESSAGE("Client Error", *mlen);
|
127
|
+
}
|
128
|
+
else {
|
129
|
+
RETURN_STATUS_MESSAGE("Error", *mlen);
|
130
|
+
}
|
130
131
|
}
|
131
132
|
|
132
133
|
static VALUE cRhebok;
|
@@ -156,6 +157,8 @@ struct common_header {
|
|
156
157
|
static int common_headers_num = 0;
|
157
158
|
static struct common_header common_headers[20];
|
158
159
|
|
160
|
+
static char date_buf[sizeof("Date: Sat, 19 Dec 2015 14:16:27 GMT\r\n")-1];
|
161
|
+
|
159
162
|
static
|
160
163
|
void set_common_header(const char * key, int key_len, const int raw)
|
161
164
|
{
|
@@ -341,7 +344,8 @@ ssize_t _read_timeout(const int fileno, const double timeout, char * read_buf, c
|
|
341
344
|
DO_READ:
|
342
345
|
rfds[0].fd = fileno;
|
343
346
|
rfds[0].events = POLLIN;
|
344
|
-
rv = read(fileno, read_buf, read_len);
|
347
|
+
//rv = read(fileno, read_buf, read_len);
|
348
|
+
rv = recvfrom(fileno, read_buf, read_len, 0, NULL, NULL);
|
345
349
|
if ( rv >= 0 ) {
|
346
350
|
return rv;
|
347
351
|
}
|
@@ -438,39 +442,42 @@ int _chunked_header(char *buf, ssize_t len) {
|
|
438
442
|
}
|
439
443
|
|
440
444
|
static
|
441
|
-
|
445
|
+
char * _date_header(void) {
|
446
|
+
static time_t last;
|
442
447
|
struct tm gtm;
|
443
448
|
time_t lt;
|
444
449
|
int i = 0;
|
445
450
|
time(<);
|
451
|
+
if ( last == lt ) return date_buf;
|
452
|
+
last = lt;
|
446
453
|
gmtime_r(<, >m);
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
str_s(
|
454
|
-
|
455
|
-
|
456
|
-
str_i(
|
457
|
-
|
458
|
-
str_s(
|
459
|
-
|
460
|
-
str_i(
|
461
|
-
|
462
|
-
str_i(
|
463
|
-
|
464
|
-
str_i(
|
465
|
-
|
466
|
-
str_i(
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
return
|
454
|
+
date_buf[i++] = 'D';
|
455
|
+
date_buf[i++] = 'a';
|
456
|
+
date_buf[i++] = 't';
|
457
|
+
date_buf[i++] = 'e';
|
458
|
+
date_buf[i++] = ':';
|
459
|
+
date_buf[i++] = ' ';
|
460
|
+
str_s(date_buf, &i, DoW[gtm.tm_wday], 3);
|
461
|
+
date_buf[i++] = ',';
|
462
|
+
date_buf[i++] = ' ';
|
463
|
+
str_i(date_buf, &i, gtm.tm_mday, 2);
|
464
|
+
date_buf[i++] = ' ';
|
465
|
+
str_s(date_buf, &i, MoY[gtm.tm_mon], 3);
|
466
|
+
date_buf[i++] = ' ';
|
467
|
+
str_i(date_buf, &i, gtm.tm_year + 1900, 4);
|
468
|
+
date_buf[i++] = ' ';
|
469
|
+
str_i(date_buf, &i, gtm.tm_hour,2);
|
470
|
+
date_buf[i++] = ':';
|
471
|
+
str_i(date_buf, &i, gtm.tm_min,2);
|
472
|
+
date_buf[i++] = ':';
|
473
|
+
str_i(date_buf, &i, gtm.tm_sec,2);
|
474
|
+
date_buf[i++] = ' ';
|
475
|
+
date_buf[i++] = 'G';
|
476
|
+
date_buf[i++] = 'M';
|
477
|
+
date_buf[i++] = 'T';
|
478
|
+
date_buf[i++] = 13;
|
479
|
+
date_buf[i++] = 10;
|
480
|
+
return date_buf;
|
474
481
|
}
|
475
482
|
|
476
483
|
static
|
@@ -484,7 +491,7 @@ int _parse_http_request(char *buf, ssize_t buf_len, VALUE env) {
|
|
484
491
|
size_t num_headers, question_at;
|
485
492
|
size_t i;
|
486
493
|
int ret;
|
487
|
-
char tmp[MAX_HEADER_NAME_LEN + sizeof("HTTP_") - 1];
|
494
|
+
char tmp[MAX_HEADER_NAME_LEN + sizeof("HTTP_") - 1] = "HTTP_";
|
488
495
|
VALUE last_value;
|
489
496
|
|
490
497
|
num_headers = MAX_HEADERS;
|
@@ -509,6 +516,7 @@ int _parse_http_request(char *buf, ssize_t buf_len, VALUE env) {
|
|
509
516
|
if (question_at != path_len) ++question_at;
|
510
517
|
rb_hash_aset(env, query_string_key, rb_str_new(path + question_at, path_len - question_at));
|
511
518
|
last_value = Qnil;
|
519
|
+
|
512
520
|
for (i = 0; i < num_headers; ++i) {
|
513
521
|
if (headers[i].name != NULL) {
|
514
522
|
const char* name;
|
@@ -516,7 +524,7 @@ int _parse_http_request(char *buf, ssize_t buf_len, VALUE env) {
|
|
516
524
|
VALUE slot;
|
517
525
|
VALUE env_key;
|
518
526
|
env_key = find_common_header(headers + i);
|
519
|
-
if ( env_key
|
527
|
+
if ( NIL_P(env_key) ) {
|
520
528
|
const char* s;
|
521
529
|
char* d;
|
522
530
|
size_t n;
|
@@ -525,7 +533,6 @@ int _parse_http_request(char *buf, ssize_t buf_len, VALUE env) {
|
|
525
533
|
ret = -1;
|
526
534
|
goto done;
|
527
535
|
}
|
528
|
-
strcpy(tmp, "HTTP_");
|
529
536
|
for (s = headers[i].name, n = headers[i].name_len, d = tmp + 5;
|
530
537
|
n != 0;
|
531
538
|
s++, --n, d++) {
|
@@ -536,7 +543,7 @@ int _parse_http_request(char *buf, ssize_t buf_len, VALUE env) {
|
|
536
543
|
}
|
537
544
|
}
|
538
545
|
slot = rb_hash_aref(env, env_key);
|
539
|
-
if ( slot
|
546
|
+
if ( !NIL_P(slot) ) {
|
540
547
|
rb_str_cat2(slot, ", ");
|
541
548
|
rb_str_cat(slot, headers[i].value, headers[i].value_len);
|
542
549
|
} else {
|
@@ -545,12 +552,11 @@ int _parse_http_request(char *buf, ssize_t buf_len, VALUE env) {
|
|
545
552
|
last_value = slot;
|
546
553
|
}
|
547
554
|
} else {
|
548
|
-
|
549
|
-
|
550
|
-
|
555
|
+
// continuing lines of a mulitiline header
|
556
|
+
if ( !NIL_P(last_value) )
|
557
|
+
rb_str_cat(last_value, headers[i].value, headers[i].value_len);
|
551
558
|
}
|
552
559
|
}
|
553
|
-
|
554
560
|
done:
|
555
561
|
return ret;
|
556
562
|
}
|
@@ -622,8 +628,13 @@ VALUE rhe_accept(VALUE self, VALUE fileno, VALUE timeoutv, VALUE tcp, VALUE env)
|
|
622
628
|
buf_len += rv;
|
623
629
|
}
|
624
630
|
|
631
|
+
//rv = _write_timeout(fd, timeout, "HTTP/1.0 200 OK\r\nConnection: close\r\n\r\n200 OK\r\n",
|
632
|
+
// sizeof("HTTP/1.0 200 OK\r\nConnection: close\r\n\r\n200 OK\r\n") - 1);
|
633
|
+
//close(fd);
|
634
|
+
//goto badexit;
|
635
|
+
|
625
636
|
VALUE expect_val = rb_hash_aref(env, expect_key);
|
626
|
-
if ( expect_val
|
637
|
+
if ( !NIL_P(expect_val) ) {
|
627
638
|
if ( strncmp(RSTRING_PTR(expect_val), "100-continue", RSTRING_LEN(expect_val)) == 0 ) {
|
628
639
|
rv = _write_timeout(fd, timeout, EXPECT_CONTINUE, sizeof(EXPECT_CONTINUE) - 1);
|
629
640
|
if ( rv <= 0 ) {
|
@@ -813,10 +824,11 @@ VALUE rhe_write_response(VALUE self, VALUE filenov, VALUE timeoutv, VALUE status
|
|
813
824
|
ssize_t count;
|
814
825
|
int i;
|
815
826
|
ssize_t remain;
|
816
|
-
char status_line[512];
|
817
|
-
char date_line
|
818
|
-
char server_line[1032];
|
827
|
+
char status_line[512] = "HTTP/1.1 ";
|
828
|
+
char * date_line;
|
819
829
|
int date_pushed = 0;
|
830
|
+
char * server_line;
|
831
|
+
int server_pushed = 0;
|
820
832
|
VALUE harr;
|
821
833
|
VALUE key_obj;
|
822
834
|
VALUE val_obj;
|
@@ -835,7 +847,7 @@ VALUE rhe_write_response(VALUE self, VALUE filenov, VALUE timeoutv, VALUE status
|
|
835
847
|
int status_code = NUM2INT(status_codev);
|
836
848
|
int use_chunked = NUM2INT(use_chunkedv);
|
837
849
|
int header_only = NUM2INT(header_onlyv);
|
838
|
-
|
850
|
+
|
839
851
|
/* status_with_no_entity_body */
|
840
852
|
if ( status_code < 200 || status_code == 204 || status_code == 304 ) {
|
841
853
|
use_chunked = 0;
|
@@ -847,28 +859,21 @@ VALUE rhe_write_response(VALUE self, VALUE filenov, VALUE timeoutv, VALUE status
|
|
847
859
|
hlen = RARRAY_LEN(harr);
|
848
860
|
blen = RARRAY_LEN(body);
|
849
861
|
iovcnt = 10 + (hlen * 2) + blen;
|
850
|
-
if ( use_chunked )
|
862
|
+
if ( use_chunked ) {
|
851
863
|
iovcnt += blen*2;
|
852
|
-
|
864
|
+
chunked_header_buf = ALLOC_N(char, 32 * blen);
|
865
|
+
}
|
853
866
|
|
854
867
|
{
|
855
868
|
struct iovec v[iovcnt]; // Needs C99 compiler
|
869
|
+
size_t mlen;
|
856
870
|
/* status line */
|
857
871
|
iovcnt = 0;
|
858
|
-
i=
|
859
|
-
status_line[i++] = 'H';
|
860
|
-
status_line[i++] = 'T';
|
861
|
-
status_line[i++] = 'T';
|
862
|
-
status_line[i++] = 'P';
|
863
|
-
status_line[i++] = '/';
|
864
|
-
status_line[i++] = '1';
|
865
|
-
status_line[i++] = '.';
|
866
|
-
status_line[i++] = '1';
|
867
|
-
status_line[i++] = ' ';
|
872
|
+
i = sizeof("HTTP/1.1 ") - 1;
|
868
873
|
str_i(status_line,&i,status_code,3);
|
869
874
|
status_line[i++] = ' ';
|
870
|
-
message = status_message(status_code);
|
871
|
-
str_s(status_line, &i, message,
|
875
|
+
message = status_message(status_code, &mlen);
|
876
|
+
str_s(status_line, &i, message, mlen);
|
872
877
|
status_line[i++] = 13;
|
873
878
|
status_line[i++] = 10;
|
874
879
|
v[iovcnt].iov_base = status_line;
|
@@ -883,6 +888,7 @@ VALUE rhe_write_response(VALUE self, VALUE filenov, VALUE timeoutv, VALUE status
|
|
883
888
|
iovcnt++;
|
884
889
|
|
885
890
|
date_pushed = 0;
|
891
|
+
|
886
892
|
for ( i = 0; i < hlen; i++ ) {
|
887
893
|
key_obj = rb_ary_entry(harr, i);
|
888
894
|
key = RSTRING_PTR(key_obj);
|
@@ -896,6 +902,7 @@ VALUE rhe_write_response(VALUE self, VALUE filenov, VALUE timeoutv, VALUE status
|
|
896
902
|
val_obj = rb_ary_entry(harr, i);
|
897
903
|
|
898
904
|
if ( strncasecmp(key,"Date",key_len) == 0 ) {
|
905
|
+
date_line = ALLOC_N(char, sizeof("Date: ")-1 + RSTRING_LEN(val_obj) + sizeof("\r\n")-1);
|
899
906
|
strcpy(date_line, "Date: ");
|
900
907
|
for ( s=RSTRING_PTR(val_obj), n = RSTRING_LEN(val_obj), d=date_line+sizeof("Date: ")-1; n !=0; s++, --n, d++) {
|
901
908
|
*d = *s;
|
@@ -908,6 +915,7 @@ VALUE rhe_write_response(VALUE self, VALUE filenov, VALUE timeoutv, VALUE status
|
|
908
915
|
continue;
|
909
916
|
}
|
910
917
|
if ( strncasecmp(key,"Server",key_len) == 0 ) {
|
918
|
+
server_line = ALLOC_N(char, sizeof("Server: ")-1 + RSTRING_LEN(val_obj) + sizeof("\r\n")-1);
|
911
919
|
strcpy(server_line, "Server: ");
|
912
920
|
for ( s=RSTRING_PTR(val_obj), n = RSTRING_LEN(val_obj), d=server_line+sizeof("Server: ")-1; n !=0; s++, --n, d++) {
|
913
921
|
*d = *s;
|
@@ -916,6 +924,7 @@ VALUE rhe_write_response(VALUE self, VALUE filenov, VALUE timeoutv, VALUE status
|
|
916
924
|
server_line[sizeof("Server: ") -1 + RSTRING_LEN(val_obj) + 1] = 10;
|
917
925
|
v[2].iov_base = server_line;
|
918
926
|
v[2].iov_len = sizeof("Server: ") -1 + RSTRING_LEN(val_obj) + 2;
|
927
|
+
server_pushed = 1;
|
919
928
|
continue;
|
920
929
|
}
|
921
930
|
|
@@ -926,7 +935,7 @@ VALUE rhe_write_response(VALUE self, VALUE filenov, VALUE timeoutv, VALUE status
|
|
926
935
|
v[iovcnt].iov_len = sizeof(": ") - 1;
|
927
936
|
iovcnt++;
|
928
937
|
|
929
|
-
|
938
|
+
// value
|
930
939
|
v[iovcnt].iov_base = RSTRING_PTR(val_obj);
|
931
940
|
v[iovcnt].iov_len = RSTRING_LEN(val_obj);
|
932
941
|
iovcnt++;
|
@@ -936,19 +945,20 @@ VALUE rhe_write_response(VALUE self, VALUE filenov, VALUE timeoutv, VALUE status
|
|
936
945
|
}
|
937
946
|
|
938
947
|
if ( date_pushed == 0 ) {
|
939
|
-
|
940
|
-
|
948
|
+
v[1].iov_len = sizeof("Date: Sat, 19 Dec 2015 14:16:27 GMT\r\n") - 1;
|
949
|
+
v[1].iov_base = _date_header();
|
941
950
|
}
|
942
951
|
|
943
952
|
if ( use_chunked ) {
|
944
|
-
v[iovcnt].iov_base = "Transfer-Encoding: chunked\r\n";
|
945
|
-
v[iovcnt].iov_len = sizeof("Transfer-Encoding: chunked\r\n") - 1;
|
953
|
+
v[iovcnt].iov_base = "Transfer-Encoding: chunked\r\nConnection: close\r\n\r\n";
|
954
|
+
v[iovcnt].iov_len = sizeof("Transfer-Encoding: chunked\r\nConnection: close\r\n\r\n") - 1;
|
946
955
|
iovcnt++;
|
947
956
|
}
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
957
|
+
else {
|
958
|
+
v[iovcnt].iov_base = "Connection: close\r\n\r\n";
|
959
|
+
v[iovcnt].iov_len = sizeof("Connection: close\r\n\r\n") - 1;
|
960
|
+
iovcnt++;
|
961
|
+
}
|
952
962
|
|
953
963
|
ssize_t chb_offset = 0;
|
954
964
|
for ( i=0; i<blen; i++) {
|
@@ -1002,7 +1012,12 @@ VALUE rhe_write_response(VALUE self, VALUE filenov, VALUE timeoutv, VALUE status
|
|
1002
1012
|
}
|
1003
1013
|
}
|
1004
1014
|
}
|
1005
|
-
|
1015
|
+
if ( use_chunked )
|
1016
|
+
xfree(chunked_header_buf);
|
1017
|
+
if ( server_pushed )
|
1018
|
+
xfree(server_line);
|
1019
|
+
if ( date_pushed )
|
1020
|
+
xfree(date_line);
|
1006
1021
|
if ( rv < 0 ) {
|
1007
1022
|
return Qnil;
|
1008
1023
|
}
|
@@ -1040,7 +1055,8 @@ void Init_rhebok()
|
|
1040
1055
|
|
1041
1056
|
expect_key = rb_obj_freeze(rb_str_new2("HTTP_EXPECT"));
|
1042
1057
|
rb_gc_register_address(&expect_key);
|
1043
|
-
|
1058
|
+
|
1059
|
+
set_common_header("HOST",sizeof("HOST") - 1, 0);
|
1044
1060
|
set_common_header("ACCEPT",sizeof("ACCEPT") - 1, 0);
|
1045
1061
|
set_common_header("ACCEPT-ENCODING",sizeof("ACCEPT-ENCODING") - 1, 0);
|
1046
1062
|
set_common_header("ACCEPT-LANGUAGE",sizeof("ACCEPT-LANGUAGE") - 1, 0);
|
@@ -1049,7 +1065,6 @@ void Init_rhebok()
|
|
1049
1065
|
set_common_header("CONTENT-LENGTH",sizeof("CONTENT-LENGTH") - 1, 1);
|
1050
1066
|
set_common_header("CONTENT-TYPE",sizeof("CONTENT-TYPE") - 1, 1);
|
1051
1067
|
set_common_header("COOKIE",sizeof("COOKIE") - 1, 0);
|
1052
|
-
set_common_header("HOST",sizeof("HOST") - 1, 0);
|
1053
1068
|
set_common_header("IF-MODIFIED-SINCE",sizeof("IF-MODIFIED-SINCE") - 1, 0);
|
1054
1069
|
set_common_header("REFERER",sizeof("REFERER") - 1, 0);
|
1055
1070
|
set_common_header("USER-AGENT",sizeof("USER-AGENT") - 1, 0);
|
data/lib/rhebok/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rhebok
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masahiro Nagano
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-12-
|
11
|
+
date: 2015-12-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|