iodine 0.1.15 → 0.1.16
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of iodine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -1
- data/lib/iodine/core.rb +1 -1
- data/lib/iodine/http/http1.rb +17 -19
- data/lib/iodine/http/http2.rb +9 -9
- data/lib/iodine/http/websockets.rb +1 -1
- data/lib/iodine/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4d5413250301e7bf147d2768d9989815d00ea67
|
4
|
+
data.tar.gz: a4225e75c91425af46c034a37db12fdfca468a3c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8e41378d248d5607120b26d96c2b94ad85de20ced37e9ac2091afe4dd8c618e04ffe427a319cd70febae126bfcb79a3a33e7979d5ca291141fac1263a2b7399e
|
7
|
+
data.tar.gz: a6b209fc737a540af696e11c85a981fae392e83e46325e2b3b10dd6fcea9bbc111043313a3ae4af3c3ab7480092458b381074693aa293adfa69d2047b328ab57
|
data/CHANGELOG.md
CHANGED
@@ -8,6 +8,12 @@ Please notice that this change log contains changes for upcoming releases as wel
|
|
8
8
|
|
9
9
|
***
|
10
10
|
|
11
|
+
Change log v.0.1.16
|
12
|
+
|
13
|
+
**Performance**: Http/1 and Http/2 connections now share and recycle their write buffer when while reading the response body and writing it to the IO. This (hopefuly) prevents excess `malloc` calls by the interperter.
|
14
|
+
|
15
|
+
***
|
16
|
+
|
11
17
|
Change log v.0.1.15
|
12
18
|
|
13
19
|
**Update**: IO reactor will now update IO status even when tasks are pending. IO will still be read only when there are no more tasks to handle, but this allows chained tasks to relate to the updated IO status. i.e. this should improve websocket availability for broadcasting (delay from connection to availability might occure until IO is registered).
|
@@ -20,7 +26,7 @@ Change log v.0.1.14
|
|
20
26
|
|
21
27
|
**Update**: the Response now supports `redirect_to` for both permanent and temporary redirection, with an optional `flash` cookie setup.
|
22
28
|
|
23
|
-
**Performance**: the Protocol class now recycles the data string as a thread global socket buffer (different threads have different buffer strings), preventing
|
29
|
+
**Performance**: the Protocol class now recycles the data string as a thread global socket buffer (different threads have different buffer strings), preventing excessive `malloc` calls by the Ruby interpreter. To keep the `data` (in `on_message(data)`) past the `on_message` method's scope, be sure to duplicate it using `data.dup`, or the string's buffer will be recycled.
|
24
30
|
|
25
31
|
***
|
26
32
|
|
data/lib/iodine/core.rb
CHANGED
@@ -72,7 +72,7 @@ module Iodine
|
|
72
72
|
def startup use_rescue = false, hide_message = false
|
73
73
|
@force_running = true
|
74
74
|
threads = []
|
75
|
-
(@thread_count ||= 1).times { threads << Thread.new { Thread.current[:buffer] ||= String.new; cycle } }
|
75
|
+
(@thread_count ||= 1).times { threads << Thread.new { Thread.current[:buffer] ||= String.new; Thread.current[:write_buffer] ||= String.new; cycle } }
|
76
76
|
unless @stop
|
77
77
|
if use_rescue
|
78
78
|
sleep rescue true
|
data/lib/iodine/http/http1.rb
CHANGED
@@ -17,13 +17,13 @@ module Iodine
|
|
17
17
|
unless request[:method]
|
18
18
|
l = data.gets.strip
|
19
19
|
if l.bytesize > 16_384
|
20
|
-
write "HTTP/1.0 414 Request-URI Too Long\r\ncontent-length: 20\r\n\r\nRequest URI too Long"
|
21
|
-
Iodine.warn "Http/1 URI too long, closing connection."
|
20
|
+
write "HTTP/1.0 414 Request-URI Too Long\r\ncontent-length: 20\r\n\r\nRequest URI too Long".freeze
|
21
|
+
Iodine.warn "Http/1 URI too long, closing connection.".freeze
|
22
22
|
return close
|
23
23
|
end
|
24
24
|
next if l.empty?
|
25
25
|
request[:method], request[:query], request[:version] = l.split(/[\s]+/.freeze, 3)
|
26
|
-
return (Iodine.warn('Htt1 Protocol Error, closing connection.') && close) unless request[:method] =~ HTTP_METHODS_REGEXP
|
26
|
+
return (Iodine.warn('Htt1 Protocol Error, closing connection.'.freeze) && close) unless request[:method] =~ HTTP_METHODS_REGEXP
|
27
27
|
request[:version] = (request[:version] || '1.1'.freeze).match(/[\d\.]+/.freeze)[0]
|
28
28
|
request[:time_recieved] = Time.now
|
29
29
|
end
|
@@ -41,12 +41,12 @@ module Iodine
|
|
41
41
|
request[:headers_complete] = true
|
42
42
|
else
|
43
43
|
#protocol error
|
44
|
-
Iodine.warn 'Protocol Error, closing connection.'
|
44
|
+
Iodine.warn 'Protocol Error, closing connection.'.freeze
|
45
45
|
return close
|
46
46
|
end
|
47
47
|
if request.length > 2096 || request[:headers_size] > 262_144
|
48
|
-
write "HTTP/1.0 431 Request Header Fields Too Large\r\ncontent-length: 31\r\n\r\nRequest Header Fields Too Large"
|
49
|
-
return (Iodine.warn('Http1 header overloading, closing connection.') && close)
|
48
|
+
write "HTTP/1.0 431 Request Header Fields Too Large\r\ncontent-length: 31\r\n\r\nRequest Header Fields Too Large".freeze
|
49
|
+
return (Iodine.warn('Http1 header overloading, closing connection.'.freeze) && close)
|
50
50
|
end
|
51
51
|
end
|
52
52
|
until request[:body_complete] && request[:headers_complete]
|
@@ -56,7 +56,7 @@ module Iodine
|
|
56
56
|
chunk = data.gets
|
57
57
|
return false unless chunk
|
58
58
|
@parser[:length] = chunk.to_i(16)
|
59
|
-
return (Iodine.warn('Protocol Error, closing connection.') && close) unless @parser[:length]
|
59
|
+
return (Iodine.warn('Protocol Error, closing connection.'.freeze) && close) unless @parser[:length]
|
60
60
|
request[:body_complete] = true && break if @parser[:length] == 0
|
61
61
|
@parser[:act_length] = 0
|
62
62
|
request[:body] ||= Tempfile.new('iodine'.freeze, :encoding => 'binary'.freeze)
|
@@ -73,7 +73,7 @@ module Iodine
|
|
73
73
|
request[:body] << packet
|
74
74
|
request[:body_complete] = true if request['content-length'.freeze].to_i - request[:body].size <= 0
|
75
75
|
elsif request['content-type'.freeze]
|
76
|
-
Iodine.warn 'Body type protocol error.' unless request[:body]
|
76
|
+
Iodine.warn 'Body type protocol error.'.freeze unless request[:body]
|
77
77
|
line = data.gets
|
78
78
|
return false unless line
|
79
79
|
(request[:body] ||= Tempfile.new('iodine'.freeze, :encoding => 'binary'.freeze) ) << line
|
@@ -85,7 +85,7 @@ module Iodine
|
|
85
85
|
if request[:body] && request[:body].size > ::Iodine::Http.max_http_buffer
|
86
86
|
Iodine.warn("Http1 message body too big, closing connection (Iodine::Http.max_http_buffer == #{::Iodine::Http.max_http_buffer} bytes) - #{request[:body].size} bytes.")
|
87
87
|
request.delete(:body).tap {|f| f.close unless f.closed? } rescue false
|
88
|
-
write "HTTP/1.0 413 Payload Too Large\r\ncontent-length: 17\r\n\r\nPayload Too Large"
|
88
|
+
write "HTTP/1.0 413 Payload Too Large\r\ncontent-length: 17\r\n\r\nPayload Too Large".freeze
|
89
89
|
return close
|
90
90
|
end
|
91
91
|
(@request = ::Iodine::Http::Request.new(self)) && ( (::Iodine::Http.http2 && ::Iodine::Http::Http2.handshake(request, self, data)) || dispatch(request, data) ) if request.delete :body_complete
|
@@ -109,17 +109,15 @@ module Iodine
|
|
109
109
|
else
|
110
110
|
headers['connection'.freeze] ||= 'close'.freeze
|
111
111
|
end
|
112
|
-
|
113
112
|
send_headers response
|
114
113
|
return log_finished(response) && (body && body.close) if request.head? || body.nil?
|
115
|
-
|
114
|
+
|
116
115
|
until body.eof?
|
117
|
-
written = write(body.read 65_536,
|
116
|
+
written = write(body.read 65_536, Thread.current[:write_buffer])
|
118
117
|
return Iodine.warn("Http/1 couldn't send response because connection was lost.".freeze) && body.close unless written
|
119
118
|
response.bytes_written += written
|
120
119
|
end
|
121
120
|
body.close
|
122
|
-
buffer.clear
|
123
121
|
close unless keep_alive
|
124
122
|
log_finished response
|
125
123
|
end
|
@@ -133,9 +131,8 @@ module Iodine
|
|
133
131
|
end
|
134
132
|
return if response.request.head?
|
135
133
|
body = response.extract_body
|
136
|
-
buffer = String.new
|
137
134
|
until body.eof?
|
138
|
-
written = stream_data(body.read 65_536,
|
135
|
+
written = stream_data(body.read 65_536, Thread.current[:write_buffer])
|
139
136
|
return Iodine.warn("Http/1 couldn't send response because connection was lost.".freeze) && body.close unless written
|
140
137
|
response.bytes_written += written
|
141
138
|
end if body
|
@@ -144,7 +141,6 @@ module Iodine
|
|
144
141
|
log_finished response
|
145
142
|
close unless response.keep_alive
|
146
143
|
end
|
147
|
-
buffer.clear
|
148
144
|
body.close if body
|
149
145
|
true
|
150
146
|
end
|
@@ -197,8 +193,9 @@ module Iodine
|
|
197
193
|
headers = response.headers
|
198
194
|
|
199
195
|
# response['date'.freeze] ||= request[:time_recieved].httpdate
|
196
|
+
(out = (Thread.current[:headers_buffer] ||= String.new)).clear
|
200
197
|
|
201
|
-
out
|
198
|
+
out << "HTTP/#{request[:version]} #{response.status} #{::Iodine::Http::Response::STATUS_CODES[response.status] || 'unknown'}\r\n"
|
202
199
|
|
203
200
|
out << request[:time_recieved].utc.strftime("Date: %a, %d %b %Y %H:%M:%S GMT\r\n".freeze) unless headers['date'.freeze]
|
204
201
|
|
@@ -209,7 +206,6 @@ module Iodine
|
|
209
206
|
out << "\r\n"
|
210
207
|
|
211
208
|
response.bytes_written += (write(out) || 0)
|
212
|
-
out.clear
|
213
209
|
headers.freeze
|
214
210
|
response.raw_cookies.freeze
|
215
211
|
end
|
@@ -222,7 +218,9 @@ module Iodine
|
|
222
218
|
request = response.request
|
223
219
|
return if Iodine.logger.nil? || request[:no_log]
|
224
220
|
t_n = Time.now
|
225
|
-
|
221
|
+
(Thread.current[:log_buffer] ||= String.new).clear
|
222
|
+
Thread.current[:log_buffer] << "#{request[:client_ip]} [#{t_n.utc}] \"#{request[:method]} #{request[:original_path]} #{request[:scheme]}\/#{request[:version]}\" #{response.status} #{response.bytes_written.to_s} #{((t_n - request[:time_recieved])*1000).round(2)}ms\n"
|
223
|
+
Iodine.log(Thread.current[:log_buffer])
|
226
224
|
end
|
227
225
|
end
|
228
226
|
end
|
data/lib/iodine/http/http2.rb
CHANGED
@@ -57,7 +57,6 @@ module Iodine
|
|
57
57
|
data = ::StringIO.new data
|
58
58
|
parse_preface data unless @connected
|
59
59
|
true while parse_frame data
|
60
|
-
data.string.clear
|
61
60
|
end
|
62
61
|
|
63
62
|
def send_response response
|
@@ -67,12 +66,10 @@ module Iodine
|
|
67
66
|
return body && body.close unless send_headers response, request
|
68
67
|
return log_finished(response) && body && body.close if request.head?
|
69
68
|
if body
|
70
|
-
buffer = String.new
|
71
69
|
until body.eof?
|
72
|
-
response.bytes_written += emit_payload(body.read(@settings[SETTINGS_MAX_FRAME_SIZE],
|
70
|
+
response.bytes_written += emit_payload(body.read(@settings[SETTINGS_MAX_FRAME_SIZE], Thread.current[:write_buffer]), request[:sid], 0, (body.eof? ? 1 : 0))
|
73
71
|
end
|
74
72
|
body.close
|
75
|
-
buffer.clear
|
76
73
|
else
|
77
74
|
emit_payload(''.freeze, request[:sid], 0, 1)
|
78
75
|
end
|
@@ -85,11 +82,9 @@ module Iodine
|
|
85
82
|
send_headers response, request
|
86
83
|
return body && body.close if request.head?
|
87
84
|
if body
|
88
|
-
buffer = String.new
|
89
85
|
until body.eof?
|
90
|
-
response.bytes_written += emit_payload(body.read(@settings[SETTINGS_MAX_FRAME_SIZE],
|
86
|
+
response.bytes_written += emit_payload(body.read(@settings[SETTINGS_MAX_FRAME_SIZE], Thread.current[:write_buffer]), request[:sid], 0, ((finish && body.eof?) ? 1 : 0))
|
91
87
|
end
|
92
|
-
buffer.clear
|
93
88
|
body.close
|
94
89
|
elsif finish
|
95
90
|
emit_payload(''.freeze, request[:sid], 0, 1)
|
@@ -146,7 +141,9 @@ module Iodine
|
|
146
141
|
request = response.request
|
147
142
|
return if Iodine.logger.nil? || request[:no_log]
|
148
143
|
t_n = Time.now
|
149
|
-
|
144
|
+
(Thread.current[:log_buffer] ||= String.new).clear
|
145
|
+
Thread.current[:log_buffer] << "#{request[:client_ip]} [#{t_n.utc}] #{request[:method]} #{request[:original_path]} #{request[:scheme]}\/2 #{response.status} #{response.bytes_written.to_s} #{((t_n - request[:time_recieved])*1000).round(2)}ms\n"
|
146
|
+
Iodine.log Thread.current[:log_buffer]
|
150
147
|
end
|
151
148
|
|
152
149
|
def send_headers response, request
|
@@ -155,7 +152,10 @@ module Iodine
|
|
155
152
|
# headers[:status] = response.status.to_s
|
156
153
|
headers['set-cookie'] = response.extract_cookies
|
157
154
|
headers.freeze
|
158
|
-
|
155
|
+
(out = (Thread.current[:headers_buffer] ||= String.new)).clear
|
156
|
+
out << @hpack.encode(headers)
|
157
|
+
emit_payload (out), request[:sid], 1, (request.head? ? 1 : 0)
|
158
|
+
out.clear
|
159
159
|
return true
|
160
160
|
end
|
161
161
|
|
@@ -16,7 +16,7 @@ module Iodine
|
|
16
16
|
end
|
17
17
|
# handle broadcasts.
|
18
18
|
def on_broadcast data
|
19
|
-
@locker.synchronize { @handler.on_broadcast(data) if @handler.respond_to? :on_broadcast
|
19
|
+
@locker.synchronize { @handler.on_broadcast(data) } if @handler.respond_to? :on_broadcast
|
20
20
|
end
|
21
21
|
# cleanup after closing.
|
22
22
|
def on_close
|
data/lib/iodine/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: iodine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.16
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Boaz Segev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-11-
|
11
|
+
date: 2015-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|