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 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