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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fd12b50300a5e3b8b0c520c1780e4c4739914624
4
- data.tar.gz: 3ed92d6cb499a00830b9b26e2ce97ec401c85252
3
+ metadata.gz: 7cf21a4ceaeeaf1c6e72a19f59555508984ee6c6
4
+ data.tar.gz: 29b1d23eebdd7837be2af68adb2b6dabefea2590
5
5
  SHA512:
6
- metadata.gz: aacc1363c0c7d17800c0789c144cf688d492043f190bb3d2674f48ea8233382e024775d8e7e9777c34acebe70e4c8faa6f4a29b55abf729ad032605dc4d49654
7
- data.tar.gz: de67014ec7944a6b575ac8fc6a7a9a9120d519b8d53a7ac524d751e2a0f7bd8e41b37da261c98182444f81d0cd6e709372b13e94eecac979aa4375509022e81d
6
+ metadata.gz: ce57b5d0c2dc1f2c880f81255f2424f5157ffab68eff12bb2c898c4acfd5b478e4dc23b0cfe38ea9157cce6214c6e68ec28a597afe13eb887aa5446d2b18ef57
7
+ data.tar.gz: d590aec96108ede772c81176c385c3bb4a15d98b8ea41a527e5316cc9bfb86dbc954ca2fffc62bf4be2af931739e63b746ec0569e0aa369d644eabce558af940
data/Changes CHANGED
@@ -1,3 +1,7 @@
1
+ 0.9.2 2015-12-24T00:31:23
2
+
3
+ - optimize a bit
4
+
1
5
  0.9.1 2015-12-07T10:37:51
2
6
 
3
7
  - disable chunked transfer by default
data/README.md CHANGED
@@ -1,6 +1,11 @@
1
1
  # Rhebok
2
2
 
3
- Rhebok is High Performance Rack Handler/Web Server. 2x performance when compared against Unicorn.
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. But does not have Keepalive
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
 
@@ -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: return "Continue";
55
- case 101: return "Switching Protocols";
56
- case 102: return "Processing"; /* RFC 2518 (WebDAV) */
57
- case 200: return "OK";
58
- case 201: return "Created";
59
- case 202: return "Accepted";
60
- case 203: return "Non-Authoritative Information";
61
- case 204: return "No Content";
62
- case 205: return "Reset Content";
63
- case 206: return "Partial Content";
64
- case 207: return "Multi-Status"; /* RFC 2518 (WebDAV) */
65
- case 208: return "Already Reported"; /* RFC 5842 */
66
- case 300: return "Multiple Choices";
67
- case 301: return "Moved Permanently";
68
- case 302: return "Found";
69
- case 303: return "See Other";
70
- case 304: return "Not Modified";
71
- case 305: return "Use Proxy";
72
- case 307: return "Temporary Redirect";
73
- case 400: return "Bad Request";
74
- case 401: return "Unauthorized";
75
- case 402: return "Payment Required";
76
- case 403: return "Forbidden";
77
- case 404: return "Not Found";
78
- case 405: return "Method Not Allowed";
79
- case 406: return "Not Acceptable";
80
- case 407: return "Proxy Authentication Required";
81
- case 408: return "Request Timeout";
82
- case 409: return "Conflict";
83
- case 410: return "Gone";
84
- case 411: return "Length Required";
85
- case 412: return "Precondition Failed";
86
- case 413: return "Request Entity Too Large";
87
- case 414: return "Request-URI Too Large";
88
- case 415: return "Unsupported Media Type";
89
- case 416: return "Request Range Not Satisfiable";
90
- case 417: return "Expectation Failed";
91
- case 418: return "I'm a teapot"; /* RFC 2324 */
92
- case 422: return "Unprocessable Entity"; /* RFC 2518 (WebDAV) */
93
- case 423: return "Locked"; /* RFC 2518 (WebDAV) */
94
- case 424: return "Failed Dependency"; /* RFC 2518 (WebDAV) */
95
- case 425: return "No code"; /* WebDAV Advanced Collections */
96
- case 426: return "Upgrade Required"; /* RFC 2817 */
97
- case 428: return "Precondition Required";
98
- case 429: return "Too Many Requests";
99
- case 431: return "Request Header Fields Too Large";
100
- case 449: return "Retry with"; /* unofficial Microsoft */
101
- case 500: return "Internal Server Error";
102
- case 501: return "Not Implemented";
103
- case 502: return "Bad Gateway";
104
- case 503: return "Service Unavailable";
105
- case 504: return "Gateway Timeout";
106
- case 505: return "HTTP Version Not Supported";
107
- case 506: return "Variant Also Negotiates"; /* RFC 2295 */
108
- case 507: return "Insufficient Storage"; /* RFC 2518 (WebDAV) */
109
- case 509: return "Bandwidth Limit Exceeded"; /* unofficial */
110
- case 510: return "Not Extended"; /* RFC 2774 */
111
- case 511: return "Network Authentication Required";
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
- return "Informational";
117
+ RETURN_STATUS_MESSAGE("Informational", *mlen);
117
118
  }
118
119
  else if (200 <= code && code <= 299) {
119
- return "Success";
120
- }
121
- else if (300 <= code && code <= 399) {
122
- return "Redirection";
123
- }
124
- else if (400 <= code && code <= 499) {
125
- return "Client Error";
126
- }
127
- else {
128
- return "Error";
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
- int _date_line(char * date_line) {
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(&lt);
451
+ if ( last == lt ) return date_buf;
452
+ last = lt;
446
453
  gmtime_r(&lt, &gtm);
447
- date_line[i++] = 'D';
448
- date_line[i++] = 'a';
449
- date_line[i++] = 't';
450
- date_line[i++] = 'e';
451
- date_line[i++] = ':';
452
- date_line[i++] = ' ';
453
- str_s(date_line, &i, DoW[gtm.tm_wday], 3);
454
- date_line[i++] = ',';
455
- date_line[i++] = ' ';
456
- str_i(date_line, &i, gtm.tm_mday, 2);
457
- date_line[i++] = ' ';
458
- str_s(date_line, &i, MoY[gtm.tm_mon], 3);
459
- date_line[i++] = ' ';
460
- str_i(date_line, &i, gtm.tm_year + 1900, 4);
461
- date_line[i++] = ' ';
462
- str_i(date_line, &i, gtm.tm_hour,2);
463
- date_line[i++] = ':';
464
- str_i(date_line, &i, gtm.tm_min,2);
465
- date_line[i++] = ':';
466
- str_i(date_line, &i, gtm.tm_sec,2);
467
- date_line[i++] = ' ';
468
- date_line[i++] = 'G';
469
- date_line[i++] = 'M';
470
- date_line[i++] = 'T';
471
- date_line[i++] = 13;
472
- date_line[i++] = 10;
473
- return i;
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 == Qnil ) {
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 != Qnil ) {
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
- /* continuing lines of a mulitiline header */
549
- if ( last_value != Qnil )
550
- rb_str_cat(last_value, headers[i].value, headers[i].value_len);
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 != Qnil ) {
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[512];
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
- chunked_header_buf = ALLOC_N(char, 32 * blen);
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=0;
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, strlen(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
- /* value */
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
- v[1].iov_len = _date_line(date_line);
940
- v[1].iov_base = date_line;
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
- v[iovcnt].iov_base = "Connection: close\r\n\r\n";
950
- v[iovcnt].iov_len = sizeof("Connection: close\r\n\r\n") - 1;
951
- iovcnt++;
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
- xfree(chunked_header_buf);
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);
@@ -1,3 +1,3 @@
1
1
  class Rhebok
2
- VERSION = "0.9.1"
2
+ VERSION = "0.9.2"
3
3
  end
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.1
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-07 00:00:00.000000000 Z
11
+ date: 2015-12-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler