Module: Iodine::Base::MonkeyPatch::RackUtils

Defined in:
lib/iodine/monkeypatch.rb,
ext/iodine/iodine_helpers.c

Overview

Iodine does NOT monkey patch Rack automatically. However, it’s possible to moneky patch Rack::Utils using this module.

Choosing to monkey patch Rack::Utils could offer significant performance gains for some applications. i.e. (on my machine):

require 'iodine'
require 'rack'
# a String in need of decoding
s = '%E3%83%AB%E3%83%93%E3%82%A4%E3%82%B9%E3%81%A8'
Benchmark.bm do |bm|
  # Pre-Patch
  bm.report("   Rack.unescape")    {1_000_000.times { Rack::Utils.unescape s } }
  bm.report("    Rack.rfc2822")    {1_000_000.times { Rack::Utils.rfc2822(Time.now) } }
  bm.report("    Rack.rfc2109")    {1_000_000.times { Rack::Utils.rfc2109(Time.now) } }
  # Perform Patch
  Iodine.patch_rack
  puts "            --- Monkey Patching Rack ---"
  # Post Patch
  bm.report("Patched.unescape")    {1_000_000.times { Rack::Utils.unescape s } }
  bm.report(" Patched.rfc2822")    {1_000_000.times { Rack::Utils.rfc2822(Time.now) } }
  bm.report(" Patched.rfc2109")    {1_000_000.times { Rack::Utils.rfc2109(Time.now) } }
end && nil

Results:

user     system      total        real
Rack.unescape  8.660000   0.010000   8.670000 (  8.687807)
Rack.rfc2822  3.730000   0.000000   3.730000 (  3.727732)
Rack.rfc2109  3.020000   0.010000   3.030000 (  3.031940)
             --- Monkey Patching Rack ---
Patched.unescape  0.340000   0.000000   0.340000 (  0.341506)
Patched.rfc2822  0.740000   0.000000   0.740000 (  0.737796)
Patched.rfc2109  0.690000   0.010000   0.700000 (  0.700155)

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.rfc2109(rtm) ⇒ Object

Takes ‘time` and returns a faster (though less localized) HTTP Date formatted String.

Iodine::Rack.rfc2109(Time.now) => "Sun, 11-Jun-2017 06:14:08 GMT"

Iodine::Rack.rfc2109(0)      => "Sun, 11-Jun-2017 06:14:08 GMT"

Since Iodine uses time caching within it’s reactor, using the default value (by passing 0) will be faster than providing an explicit time using ‘Time.now`.



194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'ext/iodine/iodine_helpers.c', line 194

static VALUE iodine_rfc2109(VALUE self, VALUE rtm) {
  time_t last_tick;
  rtm = rb_funcallv(rtm, iodine_to_i_func_id, 0, NULL);
  last_tick = FIX2ULONG(rtm) ? FIX2ULONG(rtm) : facil_last_tick();
  VALUE str = rb_str_buf_new(32);
  struct tm tm;

  http_gmtime(&last_tick, &tm);
  size_t len = http_date2rfc2109(RSTRING_PTR(str), &tm);
  rb_str_set_len(str, len);
  return str;
  (void)self;
}

.rfc2822(rtm) ⇒ Object

Takes ‘time` and returns a faster (though less localized) HTTP Date formatted String.

Iodine::Rack.rfc2822(Time.now) => "Sun, 11 Jun 2017 06:14:08 -0000"

Iodine::Rack.rfc2822(0)      => "Sun, 11 Jun 2017 06:14:08 -0000"

Since Iodine uses time caching within it’s reactor, using the default value (by passing 0) will be faster than providing an explicit time using ‘Time.now`.



168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'ext/iodine/iodine_helpers.c', line 168

static VALUE iodine_rfc2822(VALUE self, VALUE rtm) {
  time_t last_tick;
  rtm = rb_funcallv(rtm, iodine_to_i_func_id, 0, NULL);
  last_tick = FIX2ULONG(rtm) ? FIX2ULONG(rtm) : facil_last_tick();
  VALUE str = rb_str_buf_new(34);
  struct tm tm;

  http_gmtime(&last_tick, &tm);
  size_t len = http_date2rfc2822(RSTRING_PTR(str), &tm);
  rb_str_set_len(str, len);
  return str;
  (void)self;
}

.unescape(*args) ⇒ Object

Decodes a URL encoded String, returning a new String with the decoded data.

This variation matches the Rack::Utils.unescape signature by accepting and mostly ignoring an optional Encoding argument.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'ext/iodine/iodine_helpers.c', line 94

static VALUE unescape(int argc, VALUE *argv, VALUE self) {
  if (argc < 1 || argc > 2)
    rb_raise(rb_eArgError,
             "wrong number of arguments (given %d, expected 1..2).", argc);
  VALUE str = argv[0];
  Check_Type(str, T_STRING);
  VALUE str2 = rb_str_buf_new(RSTRING_LEN(str));
  ssize_t len =
      http_decode_url(RSTRING_PTR(str2), RSTRING_PTR(str), RSTRING_LEN(str));
  if (len < 0)
    rb_raise(rb_eRuntimeError, "Malformed URL path string - couldn't decode.");
  rb_str_set_len(str2, len);
  rb_encoding *enc = IodineUTF8Encoding;
  if (argc == 2 && argv[1] != Qnil && argv[1] != Qfalse) {
    enc = rb_enc_get(argv[1]);
    if (!enc)
      enc = IodineUTF8Encoding;
  }
  rb_enc_associate(str2, enc);
  return str2;
  (void)self;
}

.unescape_path(str) ⇒ Object

Decodes a percent encoded String (normally the “path” of a request), returning a new String with the decoded data.



76
77
78
79
80
81
82
83
84
85
86
# File 'ext/iodine/iodine_helpers.c', line 76

static VALUE path_decode(VALUE self, VALUE str) {
  Check_Type(str, T_STRING);
  VALUE str2 = rb_str_buf_new(RSTRING_LEN(str));
  ssize_t len =
      http_decode_path(RSTRING_PTR(str2), RSTRING_PTR(str), RSTRING_LEN(str));
  if (len < 0)
    rb_raise(rb_eRuntimeError, "Malformed URL path string - couldn't decode.");
  rb_str_set_len(str2, len);
  return str2;
  (void)self;
}

Instance Method Details

#rfc2109(rtm) ⇒ Object

Takes ‘time` and returns a faster (though less localized) HTTP Date formatted String.

Iodine::Rack.rfc2109(Time.now) => "Sun, 11-Jun-2017 06:14:08 GMT"

Iodine::Rack.rfc2109(0)      => "Sun, 11-Jun-2017 06:14:08 GMT"

Since Iodine uses time caching within it’s reactor, using the default value (by passing 0) will be faster than providing an explicit time using ‘Time.now`.



194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'ext/iodine/iodine_helpers.c', line 194

static VALUE iodine_rfc2109(VALUE self, VALUE rtm) {
  time_t last_tick;
  rtm = rb_funcallv(rtm, iodine_to_i_func_id, 0, NULL);
  last_tick = FIX2ULONG(rtm) ? FIX2ULONG(rtm) : facil_last_tick();
  VALUE str = rb_str_buf_new(32);
  struct tm tm;

  http_gmtime(&last_tick, &tm);
  size_t len = http_date2rfc2109(RSTRING_PTR(str), &tm);
  rb_str_set_len(str, len);
  return str;
  (void)self;
}

#rfc2822(rtm) ⇒ Object

Takes ‘time` and returns a faster (though less localized) HTTP Date formatted String.

Iodine::Rack.rfc2822(Time.now) => "Sun, 11 Jun 2017 06:14:08 -0000"

Iodine::Rack.rfc2822(0)      => "Sun, 11 Jun 2017 06:14:08 -0000"

Since Iodine uses time caching within it’s reactor, using the default value (by passing 0) will be faster than providing an explicit time using ‘Time.now`.



168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'ext/iodine/iodine_helpers.c', line 168

static VALUE iodine_rfc2822(VALUE self, VALUE rtm) {
  time_t last_tick;
  rtm = rb_funcallv(rtm, iodine_to_i_func_id, 0, NULL);
  last_tick = FIX2ULONG(rtm) ? FIX2ULONG(rtm) : facil_last_tick();
  VALUE str = rb_str_buf_new(34);
  struct tm tm;

  http_gmtime(&last_tick, &tm);
  size_t len = http_date2rfc2822(RSTRING_PTR(str), &tm);
  rb_str_set_len(str, len);
  return str;
  (void)self;
}

#unescape(*args) ⇒ Object

Decodes a URL encoded String, returning a new String with the decoded data.

This variation matches the Rack::Utils.unescape signature by accepting and mostly ignoring an optional Encoding argument.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'ext/iodine/iodine_helpers.c', line 94

static VALUE unescape(int argc, VALUE *argv, VALUE self) {
  if (argc < 1 || argc > 2)
    rb_raise(rb_eArgError,
             "wrong number of arguments (given %d, expected 1..2).", argc);
  VALUE str = argv[0];
  Check_Type(str, T_STRING);
  VALUE str2 = rb_str_buf_new(RSTRING_LEN(str));
  ssize_t len =
      http_decode_url(RSTRING_PTR(str2), RSTRING_PTR(str), RSTRING_LEN(str));
  if (len < 0)
    rb_raise(rb_eRuntimeError, "Malformed URL path string - couldn't decode.");
  rb_str_set_len(str2, len);
  rb_encoding *enc = IodineUTF8Encoding;
  if (argc == 2 && argv[1] != Qnil && argv[1] != Qfalse) {
    enc = rb_enc_get(argv[1]);
    if (!enc)
      enc = IodineUTF8Encoding;
  }
  rb_enc_associate(str2, enc);
  return str2;
  (void)self;
}

#unescape_path(str) ⇒ Object

Decodes a percent encoded String (normally the “path” of a request), returning a new String with the decoded data.



76
77
78
79
80
81
82
83
84
85
86
# File 'ext/iodine/iodine_helpers.c', line 76

static VALUE path_decode(VALUE self, VALUE str) {
  Check_Type(str, T_STRING);
  VALUE str2 = rb_str_buf_new(RSTRING_LEN(str));
  ssize_t len =
      http_decode_path(RSTRING_PTR(str2), RSTRING_PTR(str), RSTRING_LEN(str));
  if (len < 0)
    rb_raise(rb_eRuntimeError, "Malformed URL path string - couldn't decode.");
  rb_str_set_len(str2, len);
  return str2;
  (void)self;
}