rhebok 0.9.1 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
![rhebok logo](https://s3-ap-northeast-1.amazonaws.com/softwarearchives/rhebookfix-350.png)
|
4
|
+
|
5
|
+
|
6
|
+
[![Build Status](https://travis-ci.org/kazeburo/rhebok.svg?branch=master)](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
|