isomorfeus-iodine 0.7.49 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +1 -1
- data/CHANGELOG.md +17 -3
- data/Rakefile +1 -9
- data/examples/etag.ru +16 -0
- data/exe/iodine +14 -227
- data/ext/{iodine → iodine_ext}/extconf.rb +1 -1
- data/ext/{iodine → iodine_ext}/fio.c +0 -0
- data/ext/{iodine → iodine_ext}/fio.h +0 -0
- data/ext/{iodine → iodine_ext}/fio_cli.c +0 -0
- data/ext/{iodine → iodine_ext}/fio_cli.h +189 -189
- data/ext/{iodine → iodine_ext}/fio_json_parser.h +687 -687
- data/ext/{iodine → iodine_ext}/fio_siphash.c +157 -157
- data/ext/{iodine → iodine_ext}/fio_siphash.h +37 -37
- data/ext/{iodine → iodine_ext}/fio_tls.h +129 -129
- data/ext/{iodine → iodine_ext}/fio_tls_missing.c +0 -0
- data/ext/{iodine → iodine_ext}/fio_tls_openssl.c +0 -0
- data/ext/{iodine → iodine_ext}/fio_tmpfile.h +0 -0
- data/ext/{iodine → iodine_ext}/fiobj.h +44 -44
- data/ext/{iodine → iodine_ext}/fiobj4fio.h +21 -21
- data/ext/{iodine → iodine_ext}/fiobj_ary.c +333 -333
- data/ext/{iodine → iodine_ext}/fiobj_ary.h +139 -139
- data/ext/{iodine → iodine_ext}/fiobj_data.c +0 -0
- data/ext/{iodine → iodine_ext}/fiobj_data.h +0 -0
- data/ext/{iodine → iodine_ext}/fiobj_hash.c +0 -0
- data/ext/{iodine → iodine_ext}/fiobj_hash.h +176 -176
- data/ext/{iodine → iodine_ext}/fiobj_json.c +622 -622
- data/ext/{iodine → iodine_ext}/fiobj_json.h +68 -68
- data/ext/{iodine → iodine_ext}/fiobj_mem.h +71 -71
- data/ext/{iodine → iodine_ext}/fiobj_mustache.c +0 -0
- data/ext/{iodine → iodine_ext}/fiobj_mustache.h +62 -62
- data/ext/{iodine → iodine_ext}/fiobj_numbers.c +0 -0
- data/ext/{iodine → iodine_ext}/fiobj_numbers.h +127 -127
- data/ext/{iodine → iodine_ext}/fiobj_str.c +0 -0
- data/ext/{iodine → iodine_ext}/fiobj_str.h +172 -172
- data/ext/{iodine → iodine_ext}/fiobject.c +0 -0
- data/ext/{iodine → iodine_ext}/fiobject.h +0 -0
- data/ext/{iodine → iodine_ext}/hpack.h +1923 -1923
- data/ext/{iodine → iodine_ext}/http.c +14 -27
- data/ext/{iodine → iodine_ext}/http.h +1002 -1002
- data/ext/{iodine → iodine_ext}/http1.c +0 -0
- data/ext/{iodine → iodine_ext}/http1.h +29 -29
- data/ext/{iodine → iodine_ext}/http1_parser.h +0 -0
- data/ext/{iodine → iodine_ext}/http_internal.c +0 -0
- data/ext/{iodine → iodine_ext}/http_internal.h +0 -0
- data/ext/{iodine → iodine_ext}/http_mime_parser.h +350 -350
- data/ext/{iodine → iodine_ext}/iodine.c +1 -1
- data/ext/{iodine → iodine_ext}/iodine.h +0 -0
- data/ext/{iodine → iodine_ext}/iodine_caller.c +0 -0
- data/ext/{iodine → iodine_ext}/iodine_caller.h +0 -0
- data/ext/{iodine → iodine_ext}/iodine_connection.c +0 -0
- data/ext/{iodine → iodine_ext}/iodine_connection.h +55 -55
- data/ext/{iodine → iodine_ext}/iodine_defer.c +0 -0
- data/ext/{iodine → iodine_ext}/iodine_defer.h +6 -6
- data/ext/{iodine → iodine_ext}/iodine_fiobj2rb.h +120 -120
- data/ext/{iodine → iodine_ext}/iodine_helpers.c +0 -0
- data/ext/{iodine → iodine_ext}/iodine_helpers.h +12 -12
- data/ext/{iodine → iodine_ext}/iodine_http.c +0 -2
- data/ext/{iodine → iodine_ext}/iodine_http.h +23 -23
- data/ext/{iodine → iodine_ext}/iodine_json.c +302 -302
- data/ext/{iodine → iodine_ext}/iodine_json.h +6 -6
- data/ext/{iodine → iodine_ext}/iodine_mustache.c +0 -0
- data/ext/{iodine → iodine_ext}/iodine_mustache.h +6 -6
- data/ext/{iodine → iodine_ext}/iodine_pubsub.c +0 -0
- data/ext/{iodine → iodine_ext}/iodine_pubsub.h +26 -26
- data/ext/{iodine → iodine_ext}/iodine_rack_io.c +0 -0
- data/ext/{iodine → iodine_ext}/iodine_rack_io.h +20 -20
- data/ext/{iodine → iodine_ext}/iodine_store.c +0 -0
- data/ext/{iodine → iodine_ext}/iodine_store.h +20 -20
- data/ext/{iodine → iodine_ext}/iodine_tcp.c +0 -0
- data/ext/{iodine → iodine_ext}/iodine_tcp.h +0 -0
- data/ext/{iodine → iodine_ext}/iodine_tls.c +0 -0
- data/ext/{iodine → iodine_ext}/iodine_tls.h +13 -13
- data/ext/{iodine → iodine_ext}/mustache_parser.h +0 -0
- data/ext/{iodine → iodine_ext}/redis_engine.c +0 -0
- data/ext/{iodine → iodine_ext}/redis_engine.h +0 -0
- data/ext/{iodine → iodine_ext}/resp_parser.h +0 -0
- data/ext/{iodine → iodine_ext}/websocket_parser.h +505 -505
- data/ext/{iodine → iodine_ext}/websockets.c +0 -0
- data/ext/{iodine → iodine_ext}/websockets.h +185 -185
- data/isomorfeus-iodine.gemspec +3 -2
- data/lib/iodine/version.rb +1 -1
- data/lib/iodine.rb +1 -1
- data/lib/rack/handler/iodine.rb +4 -2
- metadata +107 -78
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d50f8965211cbcbbd9ea83e2caf5bbe9bb2c82699fcf9f70d401ccfe436af4c
|
4
|
+
data.tar.gz: e5703c8ea79c04d5389d115e62da6bebc1c28357868fd2df47207500a7a48325
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b4245d04c37d3fe90dd1d88fec0aa7ecba5ce2e7b52066a2c9a8608dbc6a8d1be60b61f9c941fcf00014fd6206ff63229976a42d614262cedae5abf6c440521
|
7
|
+
data.tar.gz: e38cca54a7203adbab3d82a60e994e265f1f53e0effd1209e7b680bd042d31495e8640eba6e3f4d65322efd173262e8ffca674180b1b5fa8e329241458985fb8
|
data/.github/workflows/ruby.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,20 @@ Please notice that this change log contains changes for upcoming releases as wel
|
|
6
6
|
|
7
7
|
## Changes:
|
8
8
|
|
9
|
+
#### Change log v.0.7.47 (2022-05-11)
|
10
|
+
|
11
|
+
**Fix**: Fixes an issue that causes `Rack::Lint` to complain about `SERVER_PORT` being an empty string. Credit to @adam12 (Adam Daniels) for PR #108 and issue #107.
|
12
|
+
|
13
|
+
#### Change log v.0.7.46 (2022-05-06)
|
14
|
+
|
15
|
+
**Fix**: Fixes the (erroneous) default insertion of the `last-modified` header in order to both better express the intent of RFC 2616 and prevent conflict with the `Rack::ETag` middleware. Credit to @raxoft (Patrik Rak) for opening issue #122.
|
16
|
+
|
17
|
+
#### Change log v.0.7.45 (2021-11-26)
|
18
|
+
|
19
|
+
**Security**: Fixes a number of issues with the HTTP parser that could have been leveraged in potential exploit attempts such as request smuggling. Credit to @dcepelik (David Čepelík).
|
20
|
+
|
21
|
+
**Compatibility**: This release adds experimental Windows support (I don't have Windows, nor Intel, I cannot test this). Credit for a lot of work by @janbiedermann (Jan Biedermann).
|
22
|
+
|
9
23
|
#### Change log v.0.7.44 (2021-02-28)
|
10
24
|
|
11
25
|
**Fix**: Fixes issue #103 where an empty String response would result in the word "null" being returned (no String object was created, which routed the NULL object to facil.io's JSON interpreter). Credit to @waghanza (Marwan Rabbâa) for exposing the issue.
|
@@ -82,7 +96,7 @@ Please notice that this change log contains changes for upcoming releases as wel
|
|
82
96
|
|
83
97
|
#### Change log v.0.7.31
|
84
98
|
|
85
|
-
**Security**: a heap-overflow vulnerability was fixed in the WebSocket parser. This attack could have been triggered remotely by a maliciously crafted message-header. Credit to Dane (4cad@silvertoque) for exposing this issue and providing a Python script demonstrating the attack.
|
99
|
+
**Security**: a heap-overflow vulnerability was fixed in the WebSocket parser. This attack could have been triggered remotely by a maliciously crafted message-header. Credit to Dane (4cad@silvertoque) for exposing this issue and providing a Python script demonstrating the attack.
|
86
100
|
|
87
101
|
It's recommended that all iodine users update to the latest version.
|
88
102
|
|
@@ -148,7 +162,7 @@ It's recommended that all iodine users update to the latest version.
|
|
148
162
|
|
149
163
|
#### Change log v.0.7.20
|
150
164
|
|
151
|
-
**Security**: (`fio`) lower and smarter Slowloris detection limits (backlog limit is now 1,024 responses / messages per client).
|
165
|
+
**Security**: (`fio`) lower and smarter Slowloris detection limits (backlog limit is now 1,024 responses / messages per client).
|
152
166
|
|
153
167
|
**Security**: (`http`) HTTP/1.1 slow client throttling - new requests will not be consumed until pending responses were sent. Since HTTP/1.1 is a response-request protocol, this protocol specific approach should protect the HTTP application against slow clients.
|
154
168
|
|
@@ -332,7 +346,7 @@ It's recommended that all iodine users update to the latest version.
|
|
332
346
|
|
333
347
|
#### Change log v.0.7.0
|
334
348
|
|
335
|
-
This version bump is performed because the internal engine changed significantly and might be considered less mature. The public API remains unbroken.
|
349
|
+
This version bump is performed because the internal engine changed significantly and might be considered less mature. The public API remains unbroken.
|
336
350
|
|
337
351
|
**Fix**: Fixed a documentation error. Credit to @Fonsan (Erik Fonselius) for PR #41.
|
338
352
|
|
data/Rakefile
CHANGED
@@ -32,13 +32,5 @@ end
|
|
32
32
|
|
33
33
|
task :default => [:compile, :spec]
|
34
34
|
|
35
|
-
Rake::ExtensionTask.new
|
36
|
-
ext.lib_dir = "lib/iodine"
|
37
|
-
end
|
35
|
+
Rake::ExtensionTask.new :iodine_ext
|
38
36
|
|
39
|
-
# Rake::ExtensionTask.new "iodine_http" do |ext|
|
40
|
-
# ext.name = 'iodine_http'
|
41
|
-
# ext.lib_dir = "lib/iodine"
|
42
|
-
# ext.ext_dir = 'ext/iodine'
|
43
|
-
# ext.config_script = 'extconf-http.rb'
|
44
|
-
# end
|
data/examples/etag.ru
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# This example uses Rack::ETag to allow for response caching.
|
2
|
+
|
3
|
+
require 'rack'
|
4
|
+
require 'iodine'
|
5
|
+
|
6
|
+
App = Proc.new do |env|
|
7
|
+
[200,
|
8
|
+
{ "Content-Type" => "text/html".freeze,
|
9
|
+
"Content-Length" => "16".freeze },
|
10
|
+
['Hello from Rack!'.freeze] ]
|
11
|
+
end
|
12
|
+
|
13
|
+
use Rack::ConditionalGet
|
14
|
+
use Rack::ETag, 'public'
|
15
|
+
|
16
|
+
run App
|
data/exe/iodine
CHANGED
@@ -3,208 +3,9 @@
|
|
3
3
|
IODINE_PARSE_CLI = true
|
4
4
|
require 'iodine'
|
5
5
|
|
6
|
-
# Load Rack if available (assume it will be used)
|
7
|
-
#
|
8
|
-
# Remember, code costs memory. Duplicating the Rack::Builder module and functions can be avoided.
|
9
|
-
begin
|
10
|
-
require 'rack'
|
11
|
-
module Iodine
|
12
|
-
module Base
|
13
|
-
module Rack
|
14
|
-
Builder = ::Rack::Builder
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
rescue LoadError
|
19
|
-
module Iodine
|
20
|
-
module Base
|
21
|
-
module Rack
|
22
|
-
# The Rack::Builder code is used when Rack isn't available.
|
23
|
-
#
|
24
|
-
# The code was copied (with minor adjustments) from the Rack source code and is licensed under the MIT license.
|
25
|
-
# Copyright (C) 2007-2019 Leah Neukirchen <http://leahneukirchen.org/infopage.html>
|
26
|
-
#
|
27
|
-
# ====
|
28
|
-
#
|
29
|
-
# Rack::Builder implements a small DSL to iteratively construct Rack
|
30
|
-
# applications.
|
31
|
-
#
|
32
|
-
# Example:
|
33
|
-
#
|
34
|
-
# require 'rack/lobster'
|
35
|
-
# app = Rack::Builder.new do
|
36
|
-
# use Rack::CommonLogger
|
37
|
-
# use Rack::ShowExceptions
|
38
|
-
# map "/lobster" do
|
39
|
-
# use Rack::Lint
|
40
|
-
# run Rack::Lobster.new
|
41
|
-
# end
|
42
|
-
# end
|
43
|
-
#
|
44
|
-
# run app
|
45
|
-
#
|
46
|
-
# Or
|
47
|
-
#
|
48
|
-
# app = Rack::Builder.app do
|
49
|
-
# use Rack::CommonLogger
|
50
|
-
# run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['OK']] }
|
51
|
-
# end
|
52
|
-
#
|
53
|
-
# run app
|
54
|
-
#
|
55
|
-
# +use+ adds middleware to the stack, +run+ dispatches to an application.
|
56
|
-
# You can use +map+ to construct a Rack::URLMap in a convenient way.
|
57
|
-
class Builder
|
58
|
-
# https://stackoverflow.com/questions/2223882/whats-the-difference-between-utf-8-and-utf-8-without-bom
|
59
|
-
UTF_8_BOM = '\xef\xbb\xbf'
|
60
|
-
|
61
|
-
def self.parse_file(config, opts = Hash.new)
|
62
|
-
if config =~ /\.ru$/
|
63
|
-
return self.load_file(config, opts)
|
64
|
-
else
|
65
|
-
require config
|
66
|
-
app = Object.const_get(::File.basename(config, '.rb').split('_').map(&:capitalize).join(''))
|
67
|
-
return app, {}
|
68
|
-
end
|
69
|
-
end
|
6
|
+
# Load Rack if available (assume it will be used)
|
70
7
|
|
71
|
-
|
72
|
-
cfgfile = ::File.read(path)
|
73
|
-
cfgfile.slice!(/\A#{UTF_8_BOM}/) if cfgfile.encoding == Encoding::UTF_8
|
74
|
-
|
75
|
-
cfgfile.sub!(/^__END__\n.*\Z/m, '')
|
76
|
-
app = new_from_string cfgfile, path
|
77
|
-
|
78
|
-
return app, options
|
79
|
-
end
|
80
|
-
|
81
|
-
def self.new_from_string(builder_script, file = "(rackup)")
|
82
|
-
eval "Iodine::Base::Rack::Builder.new {\n" + builder_script + "\n}.to_app",
|
83
|
-
TOPLEVEL_BINDING, file, 0
|
84
|
-
end
|
85
|
-
|
86
|
-
def initialize(default_app = nil, &block)
|
87
|
-
@use, @map, @run, @warmup, @freeze_app = [], nil, default_app, nil, false
|
88
|
-
instance_eval(&block) if block_given?
|
89
|
-
end
|
90
|
-
|
91
|
-
def self.app(default_app = nil, &block)
|
92
|
-
self.new(default_app, &block).to_app
|
93
|
-
end
|
94
|
-
|
95
|
-
# Specifies middleware to use in a stack.
|
96
|
-
#
|
97
|
-
# class Middleware
|
98
|
-
# def initialize(app)
|
99
|
-
# @app = app
|
100
|
-
# end
|
101
|
-
#
|
102
|
-
# def call(env)
|
103
|
-
# env["rack.some_header"] = "setting an example"
|
104
|
-
# @app.call(env)
|
105
|
-
# end
|
106
|
-
# end
|
107
|
-
#
|
108
|
-
# use Middleware
|
109
|
-
# run lambda { |env| [200, { "Content-Type" => "text/plain" }, ["OK"]] }
|
110
|
-
#
|
111
|
-
# All requests through to this application will first be processed by the middleware class.
|
112
|
-
# The +call+ method in this example sets an additional environment key which then can be
|
113
|
-
# referenced in the application if required.
|
114
|
-
def use(middleware, *args, &block)
|
115
|
-
if @map
|
116
|
-
mapping, @map = @map, nil
|
117
|
-
@use << proc { |app| generate_map(app, mapping) }
|
118
|
-
end
|
119
|
-
@use << proc { |app| middleware.new(app, *args, &block) }
|
120
|
-
end
|
121
|
-
|
122
|
-
# Takes an argument that is an object that responds to #call and returns a Rack response.
|
123
|
-
# The simplest form of this is a lambda object:
|
124
|
-
#
|
125
|
-
# run lambda { |env| [200, { "Content-Type" => "text/plain" }, ["OK"]] }
|
126
|
-
#
|
127
|
-
# However this could also be a class:
|
128
|
-
#
|
129
|
-
# class Heartbeat
|
130
|
-
# def self.call(env)
|
131
|
-
# [200, { "Content-Type" => "text/plain" }, ["OK"]]
|
132
|
-
# end
|
133
|
-
# end
|
134
|
-
#
|
135
|
-
# run Heartbeat
|
136
|
-
def run(app)
|
137
|
-
@run = app
|
138
|
-
end
|
139
|
-
|
140
|
-
# Takes a lambda or block that is used to warm-up the application.
|
141
|
-
#
|
142
|
-
# warmup do |app|
|
143
|
-
# client = Rack::MockRequest.new(app)
|
144
|
-
# client.get('/')
|
145
|
-
# end
|
146
|
-
#
|
147
|
-
# use SomeMiddleware
|
148
|
-
# run MyApp
|
149
|
-
def warmup(prc = nil, &block)
|
150
|
-
@warmup = prc || block
|
151
|
-
end
|
152
|
-
|
153
|
-
# Creates a route within the application.
|
154
|
-
#
|
155
|
-
# Rack::Builder.app do
|
156
|
-
# map '/' do
|
157
|
-
# run Heartbeat
|
158
|
-
# end
|
159
|
-
# end
|
160
|
-
#
|
161
|
-
# The +use+ method can also be used here to specify middleware to run under a specific path:
|
162
|
-
#
|
163
|
-
# Rack::Builder.app do
|
164
|
-
# map '/' do
|
165
|
-
# use Middleware
|
166
|
-
# run Heartbeat
|
167
|
-
# end
|
168
|
-
# end
|
169
|
-
#
|
170
|
-
# This example includes a piece of middleware which will run before requests hit +Heartbeat+.
|
171
|
-
#
|
172
|
-
def map(path, &block)
|
173
|
-
@map ||= {}
|
174
|
-
@map[path] = block
|
175
|
-
end
|
176
|
-
|
177
|
-
# Freeze the app (set using run) and all middleware instances when building the application
|
178
|
-
# in to_app.
|
179
|
-
def freeze_app
|
180
|
-
@freeze_app = true
|
181
|
-
end
|
182
|
-
|
183
|
-
def to_app
|
184
|
-
app = @map ? generate_map(@run, @map) : @run
|
185
|
-
fail "missing run or map statement" unless app
|
186
|
-
app.freeze if @freeze_app
|
187
|
-
app = @use.reverse.inject(app) { |a, e| e[a].tap { |x| x.freeze if @freeze_app } }
|
188
|
-
@warmup.call(app) if @warmup
|
189
|
-
app
|
190
|
-
end
|
191
|
-
|
192
|
-
def call(env)
|
193
|
-
to_app.call(env)
|
194
|
-
end
|
195
|
-
|
196
|
-
private
|
197
|
-
|
198
|
-
def generate_map(default_app, mapping)
|
199
|
-
mapped = default_app ? { '/' => default_app } : {}
|
200
|
-
mapping.each { |r, b| mapped[r] = self.class.new(default_app, &b).to_app }
|
201
|
-
URLMap.new(mapped)
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
8
|
+
require 'rack'
|
208
9
|
|
209
10
|
module Iodine
|
210
11
|
# The Iodine::Base namespace is reserved for internal use and is NOT part of the public API.
|
@@ -214,37 +15,23 @@ module Iodine
|
|
214
15
|
|
215
16
|
def self.try_file filename
|
216
17
|
return nil unless File.exist? filename
|
217
|
-
|
18
|
+
::Rack::Builder.parse_file filename
|
218
19
|
end
|
219
20
|
|
220
|
-
def self.
|
221
|
-
app
|
21
|
+
def self.get_app
|
22
|
+
app = nil
|
222
23
|
filename = Iodine::DEFAULT_SETTINGS[:filename_]
|
223
24
|
if filename
|
224
|
-
app
|
225
|
-
app
|
226
|
-
unless
|
25
|
+
app = try_file filename
|
26
|
+
app = try_file "#{filename}.ru" unless app
|
27
|
+
unless app
|
227
28
|
puts "* Couldn't find #{filename}\n testing for config.ru\n"
|
228
|
-
app
|
29
|
+
app = try_file "config.ru"
|
229
30
|
end
|
230
31
|
else
|
231
|
-
app
|
232
|
-
end
|
233
|
-
|
234
|
-
unless opt
|
235
|
-
puts "WARNING: Ruby application not found#{ filename ? " - missing both #{filename} and config.ru" : " - missing config.ru"}."
|
236
|
-
if Iodine::DEFAULT_SETTINGS[:public]
|
237
|
-
puts " Running only static file service."
|
238
|
-
opt = Hash.new
|
239
|
-
app = Proc.new { [404, {}, "Not Found!"] }
|
240
|
-
else
|
241
|
-
puts "\nERROR: Couldn't run Ruby application, check command line arguments."
|
242
|
-
ARGV << "-?"
|
243
|
-
Iodine::Base::CLI.parse
|
244
|
-
exit(0);
|
245
|
-
end
|
32
|
+
app = try_file "config.ru";
|
246
33
|
end
|
247
|
-
|
34
|
+
app
|
248
35
|
end
|
249
36
|
|
250
37
|
def self.perform_warmup(app)
|
@@ -256,7 +43,7 @@ module Iodine
|
|
256
43
|
rescue StandardError => _e
|
257
44
|
end
|
258
45
|
end
|
259
|
-
|
46
|
+
::Rack::Builder.new(app) do |r|
|
260
47
|
r.warmup do |a|
|
261
48
|
client = ::Rack::MockRequest.new(a)
|
262
49
|
client.get('/')
|
@@ -266,9 +53,9 @@ module Iodine
|
|
266
53
|
end
|
267
54
|
|
268
55
|
def self.call
|
269
|
-
app
|
56
|
+
app = get_app
|
270
57
|
perform_warmup(app) if Iodine::DEFAULT_SETTINGS[:warmup_]
|
271
|
-
Iodine::Rack.run(app
|
58
|
+
Iodine::Rack.run(app)
|
272
59
|
end
|
273
60
|
end
|
274
61
|
end
|
File without changes
|
File without changes
|
File without changes
|