rage-iodine 1.7.58

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.
Files changed (128) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
  3. data/.github/workflows/ruby.yml +42 -0
  4. data/.gitignore +20 -0
  5. data/.rspec +2 -0
  6. data/.yardopts +8 -0
  7. data/CHANGELOG.md +1098 -0
  8. data/Gemfile +11 -0
  9. data/LICENSE.txt +21 -0
  10. data/LIMITS.md +41 -0
  11. data/README.md +782 -0
  12. data/Rakefile +23 -0
  13. data/SPEC-PubSub-Draft.md +159 -0
  14. data/SPEC-WebSocket-Draft.md +239 -0
  15. data/bin/console +22 -0
  16. data/bin/info.md +353 -0
  17. data/bin/mustache_bench.rb +100 -0
  18. data/bin/poc/Gemfile.lock +23 -0
  19. data/bin/poc/README.md +37 -0
  20. data/bin/poc/config.ru +66 -0
  21. data/bin/poc/gemfile +1 -0
  22. data/bin/poc/www/index.html +57 -0
  23. data/examples/async_task.ru +92 -0
  24. data/examples/bates/README.md +3 -0
  25. data/examples/bates/config.ru +342 -0
  26. data/examples/bates/david+bold.pdf +0 -0
  27. data/examples/bates/public/drop-pdf.png +0 -0
  28. data/examples/bates/public/index.html +600 -0
  29. data/examples/config.ru +59 -0
  30. data/examples/echo.ru +59 -0
  31. data/examples/etag.ru +16 -0
  32. data/examples/hello.ru +29 -0
  33. data/examples/pubsub_engine.ru +81 -0
  34. data/examples/rack3.ru +12 -0
  35. data/examples/redis.ru +70 -0
  36. data/examples/shootout.ru +73 -0
  37. data/examples/sub-protocols.ru +90 -0
  38. data/examples/tcp_client.rb +66 -0
  39. data/examples/x-sendfile.ru +14 -0
  40. data/exe/iodine +280 -0
  41. data/ext/iodine/extconf.rb +110 -0
  42. data/ext/iodine/fio.c +12096 -0
  43. data/ext/iodine/fio.h +6390 -0
  44. data/ext/iodine/fio_cli.c +431 -0
  45. data/ext/iodine/fio_cli.h +189 -0
  46. data/ext/iodine/fio_json_parser.h +687 -0
  47. data/ext/iodine/fio_siphash.c +157 -0
  48. data/ext/iodine/fio_siphash.h +37 -0
  49. data/ext/iodine/fio_tls.h +129 -0
  50. data/ext/iodine/fio_tls_missing.c +649 -0
  51. data/ext/iodine/fio_tls_openssl.c +1056 -0
  52. data/ext/iodine/fio_tmpfile.h +50 -0
  53. data/ext/iodine/fiobj.h +44 -0
  54. data/ext/iodine/fiobj4fio.h +21 -0
  55. data/ext/iodine/fiobj_ary.c +333 -0
  56. data/ext/iodine/fiobj_ary.h +139 -0
  57. data/ext/iodine/fiobj_data.c +1185 -0
  58. data/ext/iodine/fiobj_data.h +167 -0
  59. data/ext/iodine/fiobj_hash.c +409 -0
  60. data/ext/iodine/fiobj_hash.h +176 -0
  61. data/ext/iodine/fiobj_json.c +622 -0
  62. data/ext/iodine/fiobj_json.h +68 -0
  63. data/ext/iodine/fiobj_mem.h +71 -0
  64. data/ext/iodine/fiobj_mustache.c +317 -0
  65. data/ext/iodine/fiobj_mustache.h +62 -0
  66. data/ext/iodine/fiobj_numbers.c +344 -0
  67. data/ext/iodine/fiobj_numbers.h +127 -0
  68. data/ext/iodine/fiobj_str.c +433 -0
  69. data/ext/iodine/fiobj_str.h +172 -0
  70. data/ext/iodine/fiobject.c +620 -0
  71. data/ext/iodine/fiobject.h +654 -0
  72. data/ext/iodine/hpack.h +1923 -0
  73. data/ext/iodine/http.c +2736 -0
  74. data/ext/iodine/http.h +1019 -0
  75. data/ext/iodine/http1.c +825 -0
  76. data/ext/iodine/http1.h +29 -0
  77. data/ext/iodine/http1_parser.h +1835 -0
  78. data/ext/iodine/http_internal.c +1279 -0
  79. data/ext/iodine/http_internal.h +248 -0
  80. data/ext/iodine/http_mime_parser.h +350 -0
  81. data/ext/iodine/iodine.c +1433 -0
  82. data/ext/iodine/iodine.h +64 -0
  83. data/ext/iodine/iodine_caller.c +218 -0
  84. data/ext/iodine/iodine_caller.h +27 -0
  85. data/ext/iodine/iodine_connection.c +941 -0
  86. data/ext/iodine/iodine_connection.h +55 -0
  87. data/ext/iodine/iodine_defer.c +420 -0
  88. data/ext/iodine/iodine_defer.h +6 -0
  89. data/ext/iodine/iodine_fiobj2rb.h +120 -0
  90. data/ext/iodine/iodine_helpers.c +282 -0
  91. data/ext/iodine/iodine_helpers.h +12 -0
  92. data/ext/iodine/iodine_http.c +1280 -0
  93. data/ext/iodine/iodine_http.h +23 -0
  94. data/ext/iodine/iodine_json.c +302 -0
  95. data/ext/iodine/iodine_json.h +6 -0
  96. data/ext/iodine/iodine_mustache.c +567 -0
  97. data/ext/iodine/iodine_mustache.h +6 -0
  98. data/ext/iodine/iodine_pubsub.c +580 -0
  99. data/ext/iodine/iodine_pubsub.h +26 -0
  100. data/ext/iodine/iodine_rack_io.c +273 -0
  101. data/ext/iodine/iodine_rack_io.h +20 -0
  102. data/ext/iodine/iodine_store.c +142 -0
  103. data/ext/iodine/iodine_store.h +20 -0
  104. data/ext/iodine/iodine_tcp.c +346 -0
  105. data/ext/iodine/iodine_tcp.h +13 -0
  106. data/ext/iodine/iodine_tls.c +261 -0
  107. data/ext/iodine/iodine_tls.h +13 -0
  108. data/ext/iodine/mustache_parser.h +1546 -0
  109. data/ext/iodine/redis_engine.c +957 -0
  110. data/ext/iodine/redis_engine.h +79 -0
  111. data/ext/iodine/resp_parser.h +317 -0
  112. data/ext/iodine/scheduler.c +173 -0
  113. data/ext/iodine/scheduler.h +6 -0
  114. data/ext/iodine/websocket_parser.h +506 -0
  115. data/ext/iodine/websockets.c +752 -0
  116. data/ext/iodine/websockets.h +185 -0
  117. data/iodine.gemspec +50 -0
  118. data/lib/iodine/connection.rb +61 -0
  119. data/lib/iodine/json.rb +42 -0
  120. data/lib/iodine/mustache.rb +113 -0
  121. data/lib/iodine/pubsub.rb +55 -0
  122. data/lib/iodine/rack_utils.rb +43 -0
  123. data/lib/iodine/tls.rb +16 -0
  124. data/lib/iodine/version.rb +3 -0
  125. data/lib/iodine.rb +274 -0
  126. data/lib/rack/handler/iodine.rb +33 -0
  127. data/logo.png +0 -0
  128. metadata +284 -0
@@ -0,0 +1,282 @@
1
+ /*
2
+ Copyright: Boaz segev, 2016-2017
3
+ License: MIT
4
+
5
+ Feel free to copy, use and enjoy according to the license provided.
6
+ */
7
+ #include "iodine.h"
8
+
9
+ #include "http.h"
10
+ #include <ruby/encoding.h>
11
+
12
+ /*
13
+ Add all sorts of useless stuff here.
14
+ */
15
+
16
+ static ID iodine_to_i_func_id;
17
+ static rb_encoding *IodineUTF8Encoding;
18
+
19
+ /* *****************************************************************************
20
+ URL Decoding
21
+ ***************************************************************************** */
22
+ /**
23
+ Decodes a URL encoded String in place.
24
+
25
+ Raises an exception on error... but this might result in a partially decoded
26
+ String.
27
+ */
28
+ static VALUE url_decode_inplace(VALUE self, VALUE str) {
29
+ Check_Type(str, T_STRING);
30
+ ssize_t len =
31
+ http_decode_url(RSTRING_PTR(str), RSTRING_PTR(str), RSTRING_LEN(str));
32
+ if (len < 0)
33
+ rb_raise(rb_eRuntimeError, "Malformed URL string - couldn't decode (String "
34
+ "might have been partially altered).");
35
+ rb_str_set_len(str, len);
36
+ return str;
37
+ (void)self;
38
+ }
39
+
40
+ /**
41
+ Decodes a URL encoded String, returning a new String with the decoded data.
42
+ */
43
+ static VALUE url_decode(VALUE self, VALUE str) {
44
+ Check_Type(str, T_STRING);
45
+ VALUE str2 = rb_str_buf_new(RSTRING_LEN(str));
46
+ ssize_t len =
47
+ http_decode_url(RSTRING_PTR(str2), RSTRING_PTR(str), RSTRING_LEN(str));
48
+ if (len < 0)
49
+ rb_raise(rb_eRuntimeError, "Malformed URL string - couldn't decode.");
50
+ rb_str_set_len(str2, len);
51
+ return str2;
52
+ (void)self;
53
+ }
54
+
55
+ /**
56
+ Decodes a percent encoded String (normally the "path" of a request), editing the
57
+ String in place.
58
+
59
+ Raises an exception on error... but this might result in a partially decoded
60
+ String.
61
+ */
62
+ static VALUE path_decode_inplace(VALUE self, VALUE str) {
63
+ Check_Type(str, T_STRING);
64
+ ssize_t len =
65
+ http_decode_path(RSTRING_PTR(str), RSTRING_PTR(str), RSTRING_LEN(str));
66
+ if (len < 0)
67
+ rb_raise(rb_eRuntimeError,
68
+ "Malformed URL path string - couldn't decode (String "
69
+ "might have been partially altered).");
70
+ rb_str_set_len(str, len);
71
+ return str;
72
+ (void)self;
73
+ }
74
+
75
+ /**
76
+ Decodes a percent encoded String (normally the "path" of a request), returning a
77
+ new String with the decoded data.
78
+ */
79
+ static VALUE path_decode(VALUE self, VALUE str) {
80
+ Check_Type(str, T_STRING);
81
+ VALUE str2 = rb_str_buf_new(RSTRING_LEN(str));
82
+ ssize_t len =
83
+ http_decode_path(RSTRING_PTR(str2), RSTRING_PTR(str), RSTRING_LEN(str));
84
+ if (len < 0)
85
+ rb_raise(rb_eRuntimeError, "Malformed URL path string - couldn't decode.");
86
+ rb_str_set_len(str2, len);
87
+ return str2;
88
+ (void)self;
89
+ }
90
+
91
+ /**
92
+ Decodes a URL encoded String, returning a new String with the decoded data.
93
+
94
+ This variation matches the Rack::Utils.unescape signature by accepting and
95
+ mostly ignoring an optional Encoding argument.
96
+ */
97
+ static VALUE unescape(int argc, VALUE *argv, VALUE self) {
98
+ if (argc < 1 || argc > 2)
99
+ rb_raise(rb_eArgError,
100
+ "wrong number of arguments (given %d, expected 1..2).", argc);
101
+ VALUE str = argv[0];
102
+ Check_Type(str, T_STRING);
103
+ VALUE str2 = rb_str_buf_new(RSTRING_LEN(str));
104
+ ssize_t len =
105
+ http_decode_url(RSTRING_PTR(str2), RSTRING_PTR(str), RSTRING_LEN(str));
106
+ if (len < 0)
107
+ rb_raise(rb_eRuntimeError, "Malformed URL path string - couldn't decode.");
108
+ rb_str_set_len(str2, len);
109
+ rb_encoding *enc = IodineUTF8Encoding;
110
+ if (argc == 2 && argv[1] != Qnil && argv[1] != Qfalse) {
111
+ enc = rb_enc_get(argv[1]);
112
+ if (!enc)
113
+ enc = IodineUTF8Encoding;
114
+ }
115
+ rb_enc_associate(str2, enc);
116
+ return str2;
117
+ (void)self;
118
+ }
119
+
120
+ /* *****************************************************************************
121
+ HTTP Dates
122
+ ***************************************************************************** */
123
+
124
+ /**
125
+ Takes an optional Integer for Unix Time and returns a faster (though less
126
+ localized) HTTP Date formatted String.
127
+
128
+
129
+ Iodine::Rack.time2str => "Sun, 11 Jun 2017 06:14:08 GMT"
130
+
131
+ Iodine::Rack.time2str(Time.now.to_i) => "Wed, 15 Nov 1995 06:25:24 GMT"
132
+
133
+ Since Iodine uses time caching within it's reactor, using the default value
134
+ (now) will be faster than providing an explicit time using `Time.now.to_i`.
135
+
136
+ */
137
+ static VALUE date_str(int argc, VALUE *argv, VALUE self) {
138
+ if (argc > 1)
139
+ rb_raise(rb_eArgError,
140
+ "wrong number of arguments (given %d, expected 0..1).", argc);
141
+ time_t last_tick;
142
+ if (argc) {
143
+ if (TYPE(argv[0]) != T_FIXNUM)
144
+ argv[0] = rb_funcallv(argv[0], iodine_to_i_func_id, 0, NULL);
145
+ Check_Type(argv[0], T_FIXNUM);
146
+ last_tick =
147
+ FIX2ULONG(argv[0]) ? FIX2ULONG(argv[0]) : fio_last_tick().tv_sec;
148
+ } else
149
+ last_tick = fio_last_tick().tv_sec;
150
+ VALUE str = rb_str_buf_new(32);
151
+ struct tm tm;
152
+
153
+ http_gmtime(last_tick, &tm);
154
+ size_t len = http_date2str(RSTRING_PTR(str), &tm);
155
+ rb_str_set_len(str, len);
156
+ return str;
157
+ (void)self;
158
+ }
159
+
160
+ /**
161
+ Takes `time` and returns a faster (though less localized) HTTP Date formatted
162
+ String.
163
+
164
+
165
+ Iodine::Rack.rfc2822(Time.now) => "Sun, 11 Jun 2017 06:14:08 -0000"
166
+
167
+ Iodine::Rack.rfc2822(0) => "Sun, 11 Jun 2017 06:14:08 -0000"
168
+
169
+ Since Iodine uses time caching within it's reactor, using the default value
170
+ (by passing 0) will be faster than providing an explicit time using `Time.now`.
171
+ */
172
+ static VALUE iodine_rfc2822(VALUE self, VALUE rtm) {
173
+ time_t last_tick;
174
+ rtm = rb_funcallv(rtm, iodine_to_i_func_id, 0, NULL);
175
+ last_tick = FIX2ULONG(rtm) ? FIX2ULONG(rtm) : fio_last_tick().tv_sec;
176
+ VALUE str = rb_str_buf_new(34);
177
+ struct tm tm;
178
+
179
+ http_gmtime(last_tick, &tm);
180
+ size_t len = http_date2rfc2822(RSTRING_PTR(str), &tm);
181
+ rb_str_set_len(str, len);
182
+ return str;
183
+ (void)self;
184
+ }
185
+
186
+ /**
187
+ Takes `time` and returns a faster (though less localized) HTTP Date formatted
188
+ String.
189
+
190
+
191
+ Iodine::Rack.rfc2109(Time.now) => "Sun, 11-Jun-2017 06:14:08 GMT"
192
+
193
+ Iodine::Rack.rfc2109(0) => "Sun, 11-Jun-2017 06:14:08 GMT"
194
+
195
+ Since Iodine uses time caching within it's reactor, using the default value
196
+ (by passing 0) will be faster than providing an explicit time using `Time.now`.
197
+ */
198
+ static VALUE iodine_rfc2109(VALUE self, VALUE rtm) {
199
+ time_t last_tick;
200
+ rtm = rb_funcallv(rtm, iodine_to_i_func_id, 0, NULL);
201
+ last_tick = FIX2ULONG(rtm) ? FIX2ULONG(rtm) : fio_last_tick().tv_sec;
202
+ VALUE str = rb_str_buf_new(32);
203
+ struct tm tm;
204
+
205
+ http_gmtime(last_tick, &tm);
206
+ size_t len = http_date2rfc2109(RSTRING_PTR(str), &tm);
207
+ rb_str_set_len(str, len);
208
+ return str;
209
+ (void)self;
210
+ }
211
+
212
+ /* *****************************************************************************
213
+ Ruby Initialization
214
+ ***************************************************************************** */
215
+
216
+ void iodine_init_helpers(void) {
217
+ iodine_to_i_func_id = rb_intern("to_i");
218
+ IodineUTF8Encoding = rb_enc_find("UTF-8");
219
+ VALUE tmp = rb_define_module_under(IodineModule, "Rack");
220
+ // clang-format off
221
+ /*
222
+ Iodine does NOT monkey patch Rack automatically. However, it's possible and recommended to moneky patch Rack::Utils to use the methods in this module.
223
+
224
+ Choosing to monkey patch Rack::Utils could offer significant performance gains for some applications. i.e. (on my machine):
225
+
226
+ require 'iodine'
227
+ require 'rack'
228
+ # a String in need of decoding
229
+ s = '%E3%83%AB%E3%83%93%E3%82%A4%E3%82%B9%E3%81%A8'
230
+ Benchmark.bm do |bm|
231
+ # Pre-Patch
232
+ bm.report(" Rack.unescape") {1_000_000.times { Rack::Utils.unescape s } }
233
+ bm.report(" Rack.rfc2822") {1_000_000.times { Rack::Utils.rfc2822(Time.now) } }
234
+ bm.report(" Rack.rfc2109") {1_000_000.times { Rack::Utils.rfc2109(Time.now) } }
235
+ # Perform Patch
236
+ Iodine.patch_rack
237
+ puts " --- Monkey Patching Rack ---"
238
+ # Post Patch
239
+ bm.report("Patched.unescape") {1_000_000.times { Rack::Utils.unescape s } }
240
+ bm.report(" Patched.rfc2822") {1_000_000.times { Rack::Utils.rfc2822(Time.now) } }
241
+ bm.report(" Patched.rfc2109") {1_000_000.times { Rack::Utils.rfc2109(Time.now) } }
242
+ end && nil
243
+
244
+ Results:
245
+ user system total real
246
+ Rack.unescape 8.706881 0.019995 8.726876 ( 8.740530)
247
+ Rack.rfc2822 3.270305 0.007519 3.277824 ( 3.279416)
248
+ Rack.rfc2109 3.152188 0.003852 3.156040 ( 3.157975)
249
+ --- Monkey Patching Rack ---
250
+ Patched.unescape 0.327231 0.003125 0.330356 ( 0.337090)
251
+ Patched.rfc2822 0.691304 0.003330 0.694634 ( 0.701172)
252
+ Patched.rfc2109 0.685029 0.001956 0.686985 ( 0.687607)
253
+
254
+ */
255
+ tmp = rb_define_module_under(tmp, "Utils");
256
+ // clang-format on
257
+ rb_define_module_function(tmp, "decode_url!", url_decode_inplace, 1);
258
+ rb_define_module_function(tmp, "decode_url", url_decode, 1);
259
+ rb_define_module_function(tmp, "decode_path!", path_decode_inplace, 1);
260
+ rb_define_module_function(tmp, "decode_path", path_decode, 1);
261
+ rb_define_module_function(tmp, "time2str", date_str, -1);
262
+ rb_define_module_function(tmp, "rfc2109", iodine_rfc2109, 1);
263
+ rb_define_module_function(tmp, "rfc2822", iodine_rfc2822, 1);
264
+
265
+ /*
266
+ The monkey-patched methods are in this module, allowing Iodine::Rack::Utils to
267
+ include non-patched methods as well.
268
+ */
269
+ tmp = rb_define_module_under(IodineBaseModule, "MonkeyPatch");
270
+ tmp = rb_define_module_under(tmp, "RackUtils");
271
+ // clang-format on
272
+ /* we define it all twice for easier monkey patching */
273
+ rb_define_method(tmp, "unescape", unescape, -1);
274
+ rb_define_method(tmp, "unescape_path", path_decode, 1);
275
+ rb_define_method(tmp, "rfc2109", iodine_rfc2109, 1);
276
+ rb_define_method(tmp, "rfc2822", iodine_rfc2822, 1);
277
+ rb_define_singleton_method(tmp, "unescape", unescape, -1);
278
+ rb_define_singleton_method(tmp, "unescape_path", path_decode, 1);
279
+ rb_define_singleton_method(tmp, "rfc2109", iodine_rfc2109, 1);
280
+ rb_define_singleton_method(tmp, "rfc2822", iodine_rfc2822, 1);
281
+ // rb_define_module_function(IodineUtils, "time2str", date_str, -1);
282
+ }
@@ -0,0 +1,12 @@
1
+ #ifndef H_IODINE_HELPERS_H
2
+ #define H_IODINE_HELPERS_H
3
+ /*
4
+ Copyright: Boaz segev, 2016-2018
5
+ License: MIT
6
+
7
+ Feel free to copy, use and enjoy according to the license provided.
8
+ */
9
+
10
+ void iodine_init_helpers(void);
11
+
12
+ #endif