tipi 0.37.2 → 0.38

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 945640dfdad7948a782f37168282335b8183a2109da5b28070f152a8d57090ab
4
- data.tar.gz: 4b3ae61bddd8d51fa429f747f493a93ef16a8ae4e466210878b48827f3280fe6
3
+ metadata.gz: 6a8c075ce0b769f014a20587dd061f17e32361f211aad5741f655dafe6687e37
4
+ data.tar.gz: d14c0fe026a7db1aa46edded54e5ee6f1a0f8598f626dd1aff342ad07b5cec39
5
5
  SHA512:
6
- metadata.gz: a67714ea433353c56a2c68dbfee36a654511e99a910f11868bb1844dbccd024ac2d2cb2779d588be1238fdb90e49f1341093cf3cdb1e2518f6c3fabfbce1de70
7
- data.tar.gz: 356b55c653ec4949c651784b6acc032c41db5cb6262f8b80f488586541c9a9dc789215a1306dd4257599f1fe4a618cd5ed678ddffa4379b52b21b655b2eb4eba
6
+ metadata.gz: e306783fc83d9d7ebd0678c4d68a13f6f9bd77e4b9d83fc84d745e5cc3f53eb27b69286fb1ba9f1ca54fe57358009a4c11dc9374c8a8d9046dc4330e359dc988
7
+ data.tar.gz: 789c3b4e1374cc57e04e3bce4aa8d12022cfd7e31c9cba4f5777302f57943da0a967f17f8cb2f91551357deac1bbd07fe514c2cb2e002331f525d341c6b7f0e9
data/CHANGELOG.md CHANGED
@@ -1,76 +1,80 @@
1
+ ## 0.38 2021-03-09
2
+
3
+ - Don't use chunked transfer encoding for non-streaming responses
4
+
1
5
  ## 0.37.2 2021-03-08
2
6
 
3
- * Fix header formatting when header value is an array
7
+ - Fix header formatting when header value is an array
4
8
 
5
9
  ## 0.37 2021-02-15
6
10
 
7
- * Update upgrade mechanism to work with updated Qeweney API
11
+ - Update upgrade mechanism to work with updated Qeweney API
8
12
 
9
13
  ## 0.36 2021-02-12
10
14
 
11
- * Use `Qeweney::Status` constants
15
+ - Use `Qeweney::Status` constants
12
16
 
13
17
  ## 0.35 2021-02-10
14
18
 
15
- * Extract Request class into separate [qeweney](https://github.com/digital-fabric/qeweney) gem
19
+ - Extract Request class into separate [qeweney](https://github.com/digital-fabric/qeweney) gem
16
20
 
17
21
  ## 0.34 2021-02-07
18
22
 
19
- * Implement digital fabric service and agents
20
- * Add multipart and urlencoded form data parsing
21
- * Improve request body reading behaviour
22
- * Add more `Request` information methods
23
- * Add access to connection for HTTP2 requests
24
- * Allow calling `Request#send_chunk` with empty chunk
25
- * Add support for handling protocol upgrades from within request handler
23
+ - Implement digital fabric service and agents
24
+ - Add multipart and urlencoded form data parsing
25
+ - Improve request body reading behaviour
26
+ - Add more `Request` information methods
27
+ - Add access to connection for HTTP2 requests
28
+ - Allow calling `Request#send_chunk` with empty chunk
29
+ - Add support for handling protocol upgrades from within request handler
26
30
 
27
31
  ## 0.33 2020-11-20
28
32
 
29
- * Update code for Polyphony 0.47.5
30
- * Add support for Rack::File body to Tipi::RackAdapter
33
+ - Update code for Polyphony 0.47.5
34
+ - Add support for Rack::File body to Tipi::RackAdapter
31
35
 
32
36
  ## 0.32 2020-08-14
33
37
 
34
- * Respond with array of strings instead of concatenating for HTTP 1
35
- * Use read_loop instead of readpartial
36
- * Fix http upgrade test
38
+ - Respond with array of strings instead of concatenating for HTTP 1
39
+ - Use read_loop instead of readpartial
40
+ - Fix http upgrade test
37
41
 
38
42
  ## 0.31 2020-07-28
39
43
 
40
- * Fix websocket server code
41
- * Implement configuration layer (WIP)
42
- * Improve performance of rack adapter
44
+ - Fix websocket server code
45
+ - Implement configuration layer (WIP)
46
+ - Improve performance of rack adapter
43
47
 
44
48
  ## 0.30 2020-07-15
45
49
 
46
- * Rename project to Tipi
47
- * Rearrange source code
48
- * Remove HTTP client code (to be developed eventually into a separate gem)
49
- * Fix header rendering in rack adapter (#2)
50
+ - Rename project to Tipi
51
+ - Rearrange source code
52
+ - Remove HTTP client code (to be developed eventually into a separate gem)
53
+ - Fix header rendering in rack adapter (#2)
50
54
 
51
55
  ## 0.29 2020-07-06
52
56
 
53
- * Use IO#read_loop
57
+ - Use IO#read_loop
54
58
 
55
59
  ## 0.28 2020-07-03
56
60
 
57
- * Update with API changes from Polyphony >= 0.41
61
+ - Update with API changes from Polyphony >= 0.41
58
62
 
59
63
  ## 0.27 2020-04-14
60
64
 
61
- * Remove modulation dependency
65
+ - Remove modulation dependency
62
66
 
63
67
  ## 0.26 2020-03-03
64
68
 
65
- * Fix `Server#listen`
69
+ - Fix `Server#listen`
66
70
 
67
71
  ## 0.25 2020-02-19
68
72
 
69
- * Ensure server socket is closed upon stopping loop
70
- * Fix `Request#format_header_lines`
73
+ - Ensure server socket is closed upon stopping loop
74
+ - Fix `Request#format_header_lines`
71
75
 
72
76
  ## 0.24 2020-01-08
73
77
 
74
- * Move HTTP to separate polyphony-http gem
78
+ - Move HTTP to separate polyphony-http gem
75
79
 
76
80
  For earlier changes look at the Polyphony changelog.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tipi (0.37.2)
4
+ tipi (0.38)
5
5
  http-2 (~> 0.10.0)
6
6
  http_parser.rb (~> 0.6.0)
7
7
  msgpack (~> 1.4.2)
@@ -13,9 +13,17 @@ puts 'Listening on port 4411...'
13
13
 
14
14
  spin do
15
15
  Tipi.serve('0.0.0.0', 4411, opts) do |req|
16
- req.respond("Hello world!\n")
17
- rescue Exception => e
18
- p e
16
+ p path: req.path
17
+ if req.path == '/stream'
18
+ req.send_headers('Foo' => 'Bar')
19
+ sleep 1
20
+ req.send_chunk("foo\n")
21
+ sleep 1
22
+ req.send_chunk("bar\n")
23
+ req.finish
24
+ else
25
+ req.respond("Hello world!\n")
26
+ end
19
27
  end
20
28
  p 'done...'
21
29
  end.await
@@ -16,7 +16,17 @@ opts = {
16
16
  puts "pid: #{Process.pid}"
17
17
  puts 'Listening on port 1234...'
18
18
  Tipi.serve('0.0.0.0', 1234, opts) do |req|
19
- req.respond("Hello world!\n")
19
+ p path: req.path
20
+ if req.path == '/stream'
21
+ req.send_headers('Foo' => 'Bar')
22
+ sleep 1
23
+ req.send_chunk("foo\n")
24
+ sleep 1
25
+ req.send_chunk("bar\n")
26
+ req.finish
27
+ else
28
+ req.respond("Hello world!\n")
29
+ end
20
30
  # req.send_headers
21
31
  # req.send_chunk("Method: #{req.method}\n")
22
32
  # req.send_chunk("Path: #{req.path}\n")
@@ -150,9 +150,14 @@ module DigitalFabric
150
150
  headers = message['headers']
151
151
  body = message['body']
152
152
  done = message['complete']
153
- req.send_headers(headers) if headers && !req.headers_sent?
154
- req.send_chunk(body, done: done) if body or done
155
- done
153
+ if !req.headers_sent? && done
154
+ req.respond(body, headers|| {})
155
+ true
156
+ else
157
+ req.send_headers(headers) if headers && !req.headers_sent?
158
+ req.send_chunk(body, done: done) if body or done
159
+ done
160
+ end
156
161
  else
157
162
  # invalid message
158
163
  true
@@ -204,31 +204,28 @@ module Tipi
204
204
  # @param headers
205
205
  def respond(body, headers)
206
206
  consume_request if @parsing
207
- data = [format_headers(headers, body)]
208
- if body
209
- if @parser.http_minor == 0
210
- data << body
211
- else
212
- # data << body.bytesize.to_s(16) << CRLF << body << CRLF_ZERO_CRLF_CRLF
213
- data << "#{body.bytesize.to_s(16)}\r\n#{body}\r\n0\r\n\r\n"
214
- end
215
- end
207
+ data = [format_headers(headers, body, false), body]
208
+
209
+ # if body
210
+ # if @parser.http_minor == 0
211
+ # data << body
212
+ # else
213
+ # # data << body.bytesize.to_s(16) << CRLF << body << CRLF_ZERO_CRLF_CRLF
214
+ # data << "#{body.bytesize.to_s(16)}\r\n#{body}\r\n0\r\n\r\n"
215
+ # end
216
+ # end
216
217
  # Polyphony.backend_sendv(@conn, data, 0)
217
218
  @conn.write(*data)
218
219
  end
219
220
 
220
- DEFAULT_HEADERS_OPTS = {
221
- empty_response: false,
222
- consume_request: true
223
- }.freeze
224
-
225
221
  # Sends response headers. If empty_response is truthy, the response status
226
222
  # code will default to 204, otherwise to 200.
227
223
  # @param headers [Hash] response headers
228
224
  # @param empty_response [boolean] whether a response body will be sent
225
+ # @param chunked [boolean] whether to use chunked transfer encoding
229
226
  # @return [void]
230
- def send_headers(headers, opts = DEFAULT_HEADERS_OPTS)
231
- data = format_headers(headers, true)
227
+ def send_headers(headers, empty_response: false, chunked: true)
228
+ data = format_headers(headers, !empty_response, @parser.http_minor == 1 && chunked)
232
229
  @conn.write(data)
233
230
  end
234
231
 
@@ -261,12 +258,13 @@ module Tipi
261
258
  # Formats response headers into an array. If empty_response is true(thy),
262
259
  # the response status code will default to 204, otherwise to 200.
263
260
  # @param headers [Hash] response headers
264
- # @param empty_response [boolean] whether a response body will be sent
261
+ # @param body [boolean] whether a response body will be sent
262
+ # @param chunked [boolean] whether to use chunked transfer encoding
265
263
  # @return [String] formatted response headers
266
- def format_headers(headers, body)
264
+ def format_headers(headers, body, chunked)
267
265
  status = headers[':status']
268
266
  status ||= (body ? Qeweney::Status::OK : Qeweney::Status::NO_CONTENT)
269
- lines = format_status_line(body, status)
267
+ lines = format_status_line(body, status, chunked)
270
268
  headers.each do |k, v|
271
269
  next if k =~ /^:/
272
270
 
@@ -276,11 +274,11 @@ module Tipi
276
274
  lines
277
275
  end
278
276
 
279
- def format_status_line(body, status)
277
+ def format_status_line(body, status, chunked)
280
278
  if !body
281
279
  empty_status_line(status)
282
280
  else
283
- with_body_status_line(status, body)
281
+ with_body_status_line(status, body, chunked)
284
282
  end
285
283
  end
286
284
 
@@ -292,11 +290,11 @@ module Tipi
292
290
  end
293
291
  end
294
292
 
295
- def with_body_status_line(status, body)
296
- if @parser.http_minor == 0
297
- +"HTTP/1.0 #{status}\r\nContent-Length: #{body.bytesize}\r\n"
298
- else
293
+ def with_body_status_line(status, body, chunked)
294
+ if chunked
299
295
  +"HTTP/1.1 #{status}\r\nTransfer-Encoding: chunked\r\n"
296
+ else
297
+ +"HTTP/1.1 #{status}\r\nContent-Length: #{body.bytesize}\r\n"
300
298
  end
301
299
  end
302
300
 
data/lib/tipi/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tipi
4
- VERSION = '0.37.2'
4
+ VERSION = '0.38'
5
5
  end
@@ -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.0 200
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
- Transfer-Encoding: chunked
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.0 200\r\nContent-Length: 2\r\n\r\nHi", response)
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
- Transfer-Encoding: chunked
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.0 200\r\nContent-Length: 2\r\n\r\nHi", response)
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
- 2.times { snooze }
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
- Transfer-Encoding: chunked
139
-
140
- d
141
- Hello, world!
142
- 0
132
+ Content-Length: 13
143
133
 
144
- HTTP/1.1 200
145
- Transfer-Encoding: chunked
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
- 20.times { snooze }
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
- 20.times { snooze }
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
- 20.times { snooze }
173
+ sleep 0.01
187
174
  assert_equal %w[foobar bazbud], chunks
188
175
  assert request.complete?
189
176
 
190
- 2.times { snooze }
177
+ sleep 0.01
191
178
 
192
179
  response = connection.readpartial(8192)
193
180
 
@@ -232,14 +219,11 @@ class HTTP1ServerTest < MiniTest::Test
232
219
  connection << "GET / HTTP/1.1\r\n\r\n"
233
220
  response = connection.readpartial(8192)
234
221
  assert !connection.eof?
235
- expected = <<~HTTP.http_lines
222
+ expected = <<~HTTP.http_lines.chomp
236
223
  HTTP/1.1 200
237
- Transfer-Encoding: chunked
224
+ Content-Length: 2
238
225
 
239
- 2
240
226
  Hi
241
- 0
242
-
243
227
  HTTP
244
228
  assert_equal(expected, response)
245
229
 
@@ -272,7 +256,7 @@ class HTTP1ServerTest < MiniTest::Test
272
256
  connection.close
273
257
  assert !done
274
258
 
275
- 12.times { snooze }
259
+ sleep 0.01
276
260
  assert done
277
261
  end
278
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
- snooze
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
- snooze
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
- snooze
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
- snooze
105
+ sleep 0.01
106
106
  assert_equal 'foobar', req.upgrade_protocol
107
107
  end
108
108
  end
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.37.2
4
+ version: '0.38'
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-03-08 00:00:00.000000000 Z
11
+ date: 2021-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: polyphony