tipi 0.36 → 0.39
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 +4 -4
- data/.github/workflows/test.yml +1 -1
- data/.gitignore +1 -0
- data/CHANGELOG.md +49 -28
- data/Gemfile.lock +5 -5
- data/TODO.md +79 -5
- data/df/sample_agent.rb +1 -1
- data/df/server.rb +46 -4
- data/e +0 -0
- data/examples/http_request_ws_server.rb +2 -1
- data/examples/http_server.rb +11 -3
- data/examples/http_server_forked.rb +2 -0
- data/examples/http_server_throttled.rb +3 -2
- data/examples/https_server.rb +10 -1
- data/examples/https_wss_server.rb +2 -1
- data/examples/rack_server.rb +5 -0
- data/examples/rack_server_https.rb +1 -1
- data/examples/rack_server_https_forked.rb +4 -3
- data/examples/routing_server.rb +5 -4
- data/lib/tipi/digital_fabric/agent.rb +16 -13
- data/lib/tipi/digital_fabric/agent_proxy.rb +79 -27
- data/lib/tipi/digital_fabric/protocol.rb +71 -14
- data/lib/tipi/digital_fabric/request_adapter.rb +7 -7
- data/lib/tipi/digital_fabric/service.rb +10 -8
- data/lib/tipi/http1_adapter.rb +63 -35
- data/lib/tipi/http2_adapter.rb +35 -4
- data/lib/tipi/http2_stream.rb +64 -21
- data/lib/tipi/version.rb +1 -1
- data/lib/tipi/websocket.rb +9 -22
- data/test/test_http_server.rb +22 -37
- data/test/test_request.rb +4 -4
- data/tipi.gemspec +2 -2
- metadata +7 -6
data/lib/tipi/version.rb
CHANGED
data/lib/tipi/websocket.rb
CHANGED
|
@@ -7,32 +7,17 @@ module Tipi
|
|
|
7
7
|
# Websocket connection
|
|
8
8
|
class Websocket
|
|
9
9
|
def self.handler(&block)
|
|
10
|
-
proc
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
proc do |adapter, headers|
|
|
11
|
+
req = Qeweney::Request.new(headers, adapter)
|
|
12
|
+
websocket = req.upgrade_to_websocket
|
|
13
|
+
block.(websocket)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
14
16
|
|
|
15
17
|
def initialize(conn, headers)
|
|
16
18
|
@conn = conn
|
|
17
19
|
@headers = headers
|
|
18
|
-
setup(headers)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
S_WS_GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
|
|
22
|
-
UPGRADE_RESPONSE = <<~HTTP.gsub("\n", "\r\n")
|
|
23
|
-
HTTP/1.1 101 Switching Protocols
|
|
24
|
-
Upgrade: websocket
|
|
25
|
-
Connection: Upgrade
|
|
26
|
-
Sec-WebSocket-Accept: %<accept>s
|
|
27
|
-
|
|
28
|
-
HTTP
|
|
29
|
-
|
|
30
|
-
def setup(headers)
|
|
31
|
-
key = headers['sec-websocket-key']
|
|
32
20
|
@version = headers['sec-websocket-version'].to_i
|
|
33
|
-
accept = Digest::SHA1.base64digest([key, S_WS_GUID].join)
|
|
34
|
-
@conn << format(UPGRADE_RESPONSE, accept: accept)
|
|
35
|
-
|
|
36
21
|
@reader = ::WebSocket::Frame::Incoming::Server.new(version: @version)
|
|
37
22
|
end
|
|
38
23
|
|
|
@@ -64,8 +49,10 @@ module Tipi
|
|
|
64
49
|
end
|
|
65
50
|
end
|
|
66
51
|
|
|
52
|
+
OutgoingFrame = ::WebSocket::Frame::Outgoing::Server
|
|
53
|
+
|
|
67
54
|
def send(data)
|
|
68
|
-
frame =
|
|
55
|
+
frame = OutgoingFrame.new(
|
|
69
56
|
version: @version, data: data, type: :text
|
|
70
57
|
)
|
|
71
58
|
@conn << frame.to_s
|
data/test/test_http_server.rb
CHANGED
|
@@ -60,8 +60,8 @@ class HTTP1ServerTest < MiniTest::Test
|
|
|
60
60
|
connection << "GET / HTTP/1.0\r\n\r\n"
|
|
61
61
|
|
|
62
62
|
response = connection.readpartial(8192)
|
|
63
|
-
expected = <<~HTTP.chomp.http_lines
|
|
64
|
-
HTTP/1.
|
|
63
|
+
expected = <<~HTTP.chomp.http_lines.chomp
|
|
64
|
+
HTTP/1.1 200
|
|
65
65
|
Content-Length: 13
|
|
66
66
|
|
|
67
67
|
Hello, world!
|
|
@@ -78,14 +78,11 @@ class HTTP1ServerTest < MiniTest::Test
|
|
|
78
78
|
connection << "GET / HTTP/1.1\r\n\r\n"
|
|
79
79
|
|
|
80
80
|
response = connection.readpartial(8192)
|
|
81
|
-
expected = <<~HTTP.http_lines
|
|
81
|
+
expected = <<~HTTP.http_lines.chomp
|
|
82
82
|
HTTP/1.1 200
|
|
83
|
-
|
|
83
|
+
Content-Length: 13
|
|
84
84
|
|
|
85
|
-
d
|
|
86
85
|
Hello, world!
|
|
87
|
-
0
|
|
88
|
-
|
|
89
86
|
HTTP
|
|
90
87
|
assert_equal(expected, response)
|
|
91
88
|
end
|
|
@@ -98,26 +95,23 @@ class HTTP1ServerTest < MiniTest::Test
|
|
|
98
95
|
connection << "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n"
|
|
99
96
|
response = connection.readpartial(8192)
|
|
100
97
|
assert !connection.eof?
|
|
101
|
-
assert_equal("HTTP/1.
|
|
98
|
+
assert_equal("HTTP/1.1 200\r\nContent-Length: 2\r\n\r\nHi", response)
|
|
102
99
|
|
|
103
100
|
connection << "GET / HTTP/1.1\r\n\r\n"
|
|
104
101
|
response = connection.readpartial(8192)
|
|
105
102
|
assert !connection.eof?
|
|
106
|
-
expected = <<~HTTP.http_lines
|
|
103
|
+
expected = <<~HTTP.http_lines.chomp
|
|
107
104
|
HTTP/1.1 200
|
|
108
|
-
|
|
105
|
+
Content-Length: 2
|
|
109
106
|
|
|
110
|
-
2
|
|
111
107
|
Hi
|
|
112
|
-
0
|
|
113
|
-
|
|
114
108
|
HTTP
|
|
115
109
|
assert_equal(expected, response)
|
|
116
110
|
|
|
117
111
|
connection << "GET / HTTP/1.0\r\n\r\n"
|
|
118
112
|
response = connection.readpartial(8192)
|
|
119
113
|
assert connection.eof?
|
|
120
|
-
assert_equal("HTTP/1.
|
|
114
|
+
assert_equal("HTTP/1.1 200\r\nContent-Length: 2\r\n\r\nHi", response)
|
|
121
115
|
end
|
|
122
116
|
|
|
123
117
|
def test_pipelining_client
|
|
@@ -130,24 +124,17 @@ class HTTP1ServerTest < MiniTest::Test
|
|
|
130
124
|
end
|
|
131
125
|
|
|
132
126
|
connection << "GET / HTTP/1.1\r\n\r\nGET / HTTP/1.1\r\nFoo: bar\r\n\r\n"
|
|
133
|
-
|
|
127
|
+
sleep 0.01
|
|
134
128
|
response = connection.readpartial(8192)
|
|
135
129
|
|
|
136
|
-
expected = <<~HTTP.http_lines
|
|
130
|
+
expected = <<~HTTP.http_lines.chomp
|
|
137
131
|
HTTP/1.1 200
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
d
|
|
141
|
-
Hello, world!
|
|
142
|
-
0
|
|
132
|
+
Content-Length: 13
|
|
143
133
|
|
|
144
|
-
HTTP/1.1 200
|
|
145
|
-
|
|
134
|
+
Hello, world!HTTP/1.1 200
|
|
135
|
+
Content-Length: 14
|
|
146
136
|
|
|
147
|
-
e
|
|
148
137
|
Hello, foobar!
|
|
149
|
-
0
|
|
150
|
-
|
|
151
138
|
HTTP
|
|
152
139
|
assert_equal(expected, response)
|
|
153
140
|
end
|
|
@@ -172,22 +159,22 @@ class HTTP1ServerTest < MiniTest::Test
|
|
|
172
159
|
6
|
|
173
160
|
foobar
|
|
174
161
|
HTTP
|
|
175
|
-
|
|
162
|
+
sleep 0.01
|
|
176
163
|
assert request
|
|
177
164
|
assert_equal %w[foobar], chunks
|
|
178
165
|
assert !request.complete?
|
|
179
166
|
|
|
180
167
|
connection << "6\r\nbazbud\r\n"
|
|
181
|
-
|
|
168
|
+
sleep 0.01
|
|
182
169
|
assert_equal %w[foobar bazbud], chunks
|
|
183
170
|
assert !request.complete?
|
|
184
171
|
|
|
185
172
|
connection << "0\r\n\r\n"
|
|
186
|
-
|
|
173
|
+
sleep 0.01
|
|
187
174
|
assert_equal %w[foobar bazbud], chunks
|
|
188
175
|
assert request.complete?
|
|
189
176
|
|
|
190
|
-
|
|
177
|
+
sleep 0.01
|
|
191
178
|
|
|
192
179
|
response = connection.readpartial(8192)
|
|
193
180
|
|
|
@@ -210,7 +197,8 @@ class HTTP1ServerTest < MiniTest::Test
|
|
|
210
197
|
|
|
211
198
|
opts = {
|
|
212
199
|
upgrade: {
|
|
213
|
-
echo: lambda do |
|
|
200
|
+
echo: lambda do |adapter, _headers|
|
|
201
|
+
conn = adapter.conn
|
|
214
202
|
conn << <<~HTTP.http_lines
|
|
215
203
|
HTTP/1.1 101 Switching Protocols
|
|
216
204
|
Upgrade: echo
|
|
@@ -231,14 +219,11 @@ class HTTP1ServerTest < MiniTest::Test
|
|
|
231
219
|
connection << "GET / HTTP/1.1\r\n\r\n"
|
|
232
220
|
response = connection.readpartial(8192)
|
|
233
221
|
assert !connection.eof?
|
|
234
|
-
expected = <<~HTTP.http_lines
|
|
222
|
+
expected = <<~HTTP.http_lines.chomp
|
|
235
223
|
HTTP/1.1 200
|
|
236
|
-
|
|
224
|
+
Content-Length: 2
|
|
237
225
|
|
|
238
|
-
2
|
|
239
226
|
Hi
|
|
240
|
-
0
|
|
241
|
-
|
|
242
227
|
HTTP
|
|
243
228
|
assert_equal(expected, response)
|
|
244
229
|
|
|
@@ -271,7 +256,7 @@ class HTTP1ServerTest < MiniTest::Test
|
|
|
271
256
|
connection.close
|
|
272
257
|
assert !done
|
|
273
258
|
|
|
274
|
-
|
|
259
|
+
sleep 0.01
|
|
275
260
|
assert done
|
|
276
261
|
end
|
|
277
262
|
|
data/test/test_request.rb
CHANGED
|
@@ -60,7 +60,7 @@ class RequestHeadersTest < MiniTest::Test
|
|
|
60
60
|
|
|
61
61
|
connection << "GET /titi HTTP/1.1\r\nHost: blah.com\r\nFoo: bar\r\nhi: 1\r\nHi: 2\r\nhi: 3\r\n\r\n"
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
sleep 0.01
|
|
64
64
|
|
|
65
65
|
assert_kind_of Qeweney::Request, req
|
|
66
66
|
assert_equal 'blah.com', req.headers['host']
|
|
@@ -78,7 +78,7 @@ class RequestHeadersTest < MiniTest::Test
|
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
connection << "GET /titi HTTP/1.1\nHost: blah.com\nFoo: bar\nhi: 1\nHi: 2\nhi: 3\n\n"
|
|
81
|
-
|
|
81
|
+
sleep 0.01
|
|
82
82
|
assert_equal 'blah.com', req.host
|
|
83
83
|
end
|
|
84
84
|
|
|
@@ -90,7 +90,7 @@ class RequestHeadersTest < MiniTest::Test
|
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
connection << "GET /titi HTTP/1.1\nConnection: keep-alive\nFoo: bar\nhi: 1\nHi: 2\nhi: 3\n\n"
|
|
93
|
-
|
|
93
|
+
sleep 0.01
|
|
94
94
|
assert_equal 'keep-alive', req.connection
|
|
95
95
|
end
|
|
96
96
|
|
|
@@ -102,7 +102,7 @@ class RequestHeadersTest < MiniTest::Test
|
|
|
102
102
|
end
|
|
103
103
|
|
|
104
104
|
connection << "GET /titi HTTP/1.1\nConnection: upgrade\nUpgrade: foobar\n\n"
|
|
105
|
-
|
|
105
|
+
sleep 0.01
|
|
106
106
|
assert_equal 'foobar', req.upgrade_protocol
|
|
107
107
|
end
|
|
108
108
|
end
|
data/tipi.gemspec
CHANGED
|
@@ -19,8 +19,8 @@ Gem::Specification.new do |s|
|
|
|
19
19
|
|
|
20
20
|
s.executables = ['tipi']
|
|
21
21
|
|
|
22
|
-
s.add_runtime_dependency 'polyphony', '~>0.
|
|
23
|
-
s.add_runtime_dependency 'qeweney', '~>0.
|
|
22
|
+
s.add_runtime_dependency 'polyphony', '~>0.55.0'
|
|
23
|
+
s.add_runtime_dependency 'qeweney', '~>0.9.1'
|
|
24
24
|
|
|
25
25
|
s.add_runtime_dependency 'http_parser.rb', '~>0.6.0'
|
|
26
26
|
s.add_runtime_dependency 'http-2', '~>0.10.0'
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tipi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: '0.
|
|
4
|
+
version: '0.39'
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sharon Rosner
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-06-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: polyphony
|
|
@@ -16,28 +16,28 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.
|
|
19
|
+
version: 0.55.0
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.
|
|
26
|
+
version: 0.55.0
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: qeweney
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version:
|
|
33
|
+
version: 0.9.1
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version:
|
|
40
|
+
version: 0.9.1
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: http_parser.rb
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -214,6 +214,7 @@ files:
|
|
|
214
214
|
- df/ws_page.html
|
|
215
215
|
- docs/README.md
|
|
216
216
|
- docs/tipi-logo.png
|
|
217
|
+
- e
|
|
217
218
|
- examples/cuba.ru
|
|
218
219
|
- examples/hanami-api.ru
|
|
219
220
|
- examples/hello.ru
|