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.
- checksums.yaml +7 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
- data/.github/workflows/ruby.yml +42 -0
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/.yardopts +8 -0
- data/CHANGELOG.md +1098 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +21 -0
- data/LIMITS.md +41 -0
- data/README.md +782 -0
- data/Rakefile +23 -0
- data/SPEC-PubSub-Draft.md +159 -0
- data/SPEC-WebSocket-Draft.md +239 -0
- data/bin/console +22 -0
- data/bin/info.md +353 -0
- data/bin/mustache_bench.rb +100 -0
- data/bin/poc/Gemfile.lock +23 -0
- data/bin/poc/README.md +37 -0
- data/bin/poc/config.ru +66 -0
- data/bin/poc/gemfile +1 -0
- data/bin/poc/www/index.html +57 -0
- data/examples/async_task.ru +92 -0
- data/examples/bates/README.md +3 -0
- data/examples/bates/config.ru +342 -0
- data/examples/bates/david+bold.pdf +0 -0
- data/examples/bates/public/drop-pdf.png +0 -0
- data/examples/bates/public/index.html +600 -0
- data/examples/config.ru +59 -0
- data/examples/echo.ru +59 -0
- data/examples/etag.ru +16 -0
- data/examples/hello.ru +29 -0
- data/examples/pubsub_engine.ru +81 -0
- data/examples/rack3.ru +12 -0
- data/examples/redis.ru +70 -0
- data/examples/shootout.ru +73 -0
- data/examples/sub-protocols.ru +90 -0
- data/examples/tcp_client.rb +66 -0
- data/examples/x-sendfile.ru +14 -0
- data/exe/iodine +280 -0
- data/ext/iodine/extconf.rb +110 -0
- data/ext/iodine/fio.c +12096 -0
- data/ext/iodine/fio.h +6390 -0
- data/ext/iodine/fio_cli.c +431 -0
- data/ext/iodine/fio_cli.h +189 -0
- data/ext/iodine/fio_json_parser.h +687 -0
- data/ext/iodine/fio_siphash.c +157 -0
- data/ext/iodine/fio_siphash.h +37 -0
- data/ext/iodine/fio_tls.h +129 -0
- data/ext/iodine/fio_tls_missing.c +649 -0
- data/ext/iodine/fio_tls_openssl.c +1056 -0
- data/ext/iodine/fio_tmpfile.h +50 -0
- data/ext/iodine/fiobj.h +44 -0
- data/ext/iodine/fiobj4fio.h +21 -0
- data/ext/iodine/fiobj_ary.c +333 -0
- data/ext/iodine/fiobj_ary.h +139 -0
- data/ext/iodine/fiobj_data.c +1185 -0
- data/ext/iodine/fiobj_data.h +167 -0
- data/ext/iodine/fiobj_hash.c +409 -0
- data/ext/iodine/fiobj_hash.h +176 -0
- data/ext/iodine/fiobj_json.c +622 -0
- data/ext/iodine/fiobj_json.h +68 -0
- data/ext/iodine/fiobj_mem.h +71 -0
- data/ext/iodine/fiobj_mustache.c +317 -0
- data/ext/iodine/fiobj_mustache.h +62 -0
- data/ext/iodine/fiobj_numbers.c +344 -0
- data/ext/iodine/fiobj_numbers.h +127 -0
- data/ext/iodine/fiobj_str.c +433 -0
- data/ext/iodine/fiobj_str.h +172 -0
- data/ext/iodine/fiobject.c +620 -0
- data/ext/iodine/fiobject.h +654 -0
- data/ext/iodine/hpack.h +1923 -0
- data/ext/iodine/http.c +2736 -0
- data/ext/iodine/http.h +1019 -0
- data/ext/iodine/http1.c +825 -0
- data/ext/iodine/http1.h +29 -0
- data/ext/iodine/http1_parser.h +1835 -0
- data/ext/iodine/http_internal.c +1279 -0
- data/ext/iodine/http_internal.h +248 -0
- data/ext/iodine/http_mime_parser.h +350 -0
- data/ext/iodine/iodine.c +1433 -0
- data/ext/iodine/iodine.h +64 -0
- data/ext/iodine/iodine_caller.c +218 -0
- data/ext/iodine/iodine_caller.h +27 -0
- data/ext/iodine/iodine_connection.c +941 -0
- data/ext/iodine/iodine_connection.h +55 -0
- data/ext/iodine/iodine_defer.c +420 -0
- data/ext/iodine/iodine_defer.h +6 -0
- data/ext/iodine/iodine_fiobj2rb.h +120 -0
- data/ext/iodine/iodine_helpers.c +282 -0
- data/ext/iodine/iodine_helpers.h +12 -0
- data/ext/iodine/iodine_http.c +1280 -0
- data/ext/iodine/iodine_http.h +23 -0
- data/ext/iodine/iodine_json.c +302 -0
- data/ext/iodine/iodine_json.h +6 -0
- data/ext/iodine/iodine_mustache.c +567 -0
- data/ext/iodine/iodine_mustache.h +6 -0
- data/ext/iodine/iodine_pubsub.c +580 -0
- data/ext/iodine/iodine_pubsub.h +26 -0
- data/ext/iodine/iodine_rack_io.c +273 -0
- data/ext/iodine/iodine_rack_io.h +20 -0
- data/ext/iodine/iodine_store.c +142 -0
- data/ext/iodine/iodine_store.h +20 -0
- data/ext/iodine/iodine_tcp.c +346 -0
- data/ext/iodine/iodine_tcp.h +13 -0
- data/ext/iodine/iodine_tls.c +261 -0
- data/ext/iodine/iodine_tls.h +13 -0
- data/ext/iodine/mustache_parser.h +1546 -0
- data/ext/iodine/redis_engine.c +957 -0
- data/ext/iodine/redis_engine.h +79 -0
- data/ext/iodine/resp_parser.h +317 -0
- data/ext/iodine/scheduler.c +173 -0
- data/ext/iodine/scheduler.h +6 -0
- data/ext/iodine/websocket_parser.h +506 -0
- data/ext/iodine/websockets.c +752 -0
- data/ext/iodine/websockets.h +185 -0
- data/iodine.gemspec +50 -0
- data/lib/iodine/connection.rb +61 -0
- data/lib/iodine/json.rb +42 -0
- data/lib/iodine/mustache.rb +113 -0
- data/lib/iodine/pubsub.rb +55 -0
- data/lib/iodine/rack_utils.rb +43 -0
- data/lib/iodine/tls.rb +16 -0
- data/lib/iodine/version.rb +3 -0
- data/lib/iodine.rb +274 -0
- data/lib/rack/handler/iodine.rb +33 -0
- data/logo.png +0 -0
- 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
|
+
}
|