qeweney 0.7.2 → 0.8.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 693c85b30e907232ff7bfa77a8c058a8ef1155a108b7b554ecaf68482b6bfe9a
4
- data.tar.gz: 13a9d1c4d6277f90346193b4c56cae0cf44735947268136a7d853071535b3241
3
+ metadata.gz: 43b284ffdbd86680bb9e5c34738006fa8b3e0d48f36ce45df533e8afcd3f2961
4
+ data.tar.gz: 5d69cc440ed42251b6970a86e9b63ec3419aa0fad946f9353d29ec58526c6d0f
5
5
  SHA512:
6
- metadata.gz: 9e34c036534ec0899b251628f666e0f5752c10d38bb98c07765a3149ae901be85a56128880889f71148fec4e90aa2324cce78817f311b79b52b9f2cefb2b19c1
7
- data.tar.gz: ccbd53e40b78a60a5665c187c2dd65b4330c1c68c13eb15209f49551df3b0c35c070251662538a3de63cfb56ae507c170c88e767da95178e896a72d5835492ef
6
+ metadata.gz: 5fd5ce37b83afc129ae262d8dcfc0288bd206e6b3c260577c00a89a5bcc7b44a3337d67087a9b05c281f49aa9f35b6202d44c8c5f535023c9c30929232e5bee5
7
+ data.tar.gz: cb7636b76961093665c6cf92c882a377ed028d0afa2a048dfd92da51fae88ca2815353287de5f2c34f75f81ddf056fc434c9cc71c34c4b6429f594c6b1c30068
data/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
1
+ ## 0.8.1 2021-03-10
2
+
3
+ - Add `Request#transfer_counts`, `Request#total_transfer`
4
+ - Fix `Request#rx_incr`
5
+
6
+ ## 0.8 2021-03-10
7
+
8
+ - Pass request as first argument to all adapter methods
9
+
10
+ ## 0.7.5 2021-03-08
11
+
12
+ - Set content-type header in `#serve_file`
13
+
14
+ ## 0.7.4 2021-03-07
15
+
16
+ - Add `Request#cookies`
17
+ - Add `Request#full_uri`
18
+
19
+ ## 0.7.3 2021-03-05
20
+
21
+ - Fix `parse_urlencoded_form_data`
22
+
1
23
  ## 0.7.2 2021-03-04
2
24
 
3
25
  - Add `#route_relative_path` method
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- qeweney (0.7.2)
4
+ qeweney (0.8.1)
5
5
  escape_utils (~> 1.2.1)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -1,11 +1,71 @@
1
1
  # Qeweney
2
2
 
3
- ## Cross-library feature rich HTTP request / response API
3
+ ## Cross-library HTTP request / response API for servers
4
4
 
5
- Qeweney provides a uniform API for dealing with HTTP requests and responses.
5
+ Qeweney provides a uniform API for dealing with HTTP requests and responses on
6
+ the server side. Qeweney defines a uniform adapter interface that allows
7
+ handling incoming HTTP requests and sending HTTP responses over any protocol or
8
+ transport, be it HTTP/1, HTTP/2 or a Rack interface.
9
+
10
+ Qeweney is primarily designed to work with
11
+ [Tipi](https://github.com/digital-fabric/tipi), but can also be used directly
12
+ inside Rack apps, or to drive Rack apps.
6
13
 
7
14
  ## Features
8
15
 
9
- - Works with different web server APIs, notably Tipi, Digital Fabric, and Rack
10
- - Transport-agnostic
11
- - High-performance routing API inspired by Roda
16
+ - Works with different web server APIs, notably Tipi, Digital Fabric, and Rack.
17
+ - Transport-agnostic.
18
+ - High-performance routing API inspired by Roda.
19
+ - Rich API for extracting data from HTTP requests: form parsing, cookies, file
20
+ uploads, etc.
21
+ - Rich API for constructing HTTP responses: streaming responses, HTTP upgrades,
22
+ static file serving, delate and gzip encoding, caching etc.
23
+ - Suitable for both blocking and non-blocking concurrency models.
24
+ - Allows working with request before request body is read and parsed.
25
+
26
+ ## Overview
27
+
28
+ In Qeweney, the main class developers will interact with is `Qeweney::Request`,
29
+ which encapsulates an HTTP request (from the server's point of view), and offers
30
+ an API for extracting request information and responding to that request.
31
+
32
+ A request is always associated with an _adapter_, an object that implements the
33
+ Qeweney adapter interface, and that allows reading request bodies (for uploads
34
+ and form submissions) and sending responses.
35
+
36
+ ## The Qeweney Adapter Interface
37
+
38
+ ```ruby
39
+ class AdapterInterface
40
+ # Reads a chunk from the request body
41
+ # @req [Qeweney::Request] request for which the chunk is to be read
42
+ def get_body_chunk(req)
43
+ end
44
+
45
+ # Send a non-streaming response
46
+ # @req [Qeweney::Request] request for which the response is sent
47
+ # @body [String, nil] response body
48
+ # @headers [Hash] response headers
49
+ def respond(req, body, headers)
50
+ end
51
+
52
+ # Send only headers
53
+ # @req [Qeweney::Request] request for which the response is sent
54
+ # @headers [Hash] response headers
55
+ # @empty_response [boolean] whether response is empty
56
+ def send_headers(req, headers, empty_response: nil)
57
+ end
58
+
59
+ # Send a body chunk (this implies chunked transfer encoding)
60
+ # @req [Qeweney::Request] request for which the response is sent
61
+ # @body [String, nil] chunk
62
+ # @done [boolean] whether response is finished
63
+ def send_chunk(req, body, done: false)
64
+ end
65
+
66
+ # Finishes response
67
+ # @req [Qeweney::Request] request for which the response is sent
68
+ def finish(req)
69
+ end
70
+ end
71
+ ```
@@ -7,7 +7,7 @@ module Qeweney
7
7
  'html' => 'text/html',
8
8
  'css' => 'text/css',
9
9
  'js' => 'application/javascript',
10
- 'txt' => 'text/plain'
10
+ 'txt' => 'text/plain',
11
11
 
12
12
  'gif' => 'image/gif',
13
13
  'jpg' => 'image/jpeg',
@@ -19,7 +19,7 @@ module Qeweney
19
19
  'json' => 'application/json',
20
20
  }.freeze
21
21
 
22
- def [](ref)
22
+ def self.[](ref)
23
23
  case ref
24
24
  when Symbol
25
25
  TYPES[ref.to_s]
data/lib/qeweney/rack.rb CHANGED
@@ -32,20 +32,20 @@ module Qeweney
32
32
  headers
33
33
  end
34
34
 
35
- def respond(body, headers)
35
+ def respond(req, body, headers)
36
36
  @response_body << body
37
37
  @response_headers = headers
38
38
  end
39
39
 
40
- def send_headers(headers, empty_response: nil)
40
+ def send_headers(req, headers, empty_response: nil)
41
41
  @response_headers = headers
42
42
  end
43
43
 
44
- def send_chunk(body, done: false)
44
+ def send_chunk(req, body, done: false)
45
45
  @response_body << body
46
46
  end
47
47
 
48
- def finish
48
+ def finish(req)
49
49
  end
50
50
 
51
51
  def rack_response
@@ -34,7 +34,7 @@ module Qeweney
34
34
  return chunk
35
35
  end
36
36
 
37
- @message_complete ? nil : @adapter.get_body_chunk
37
+ @message_complete ? nil : @adapter.get_body_chunk(self)
38
38
  end
39
39
 
40
40
  def each_chunk
@@ -44,7 +44,7 @@ module Qeweney
44
44
  end
45
45
  @buffered_body_chunks = nil
46
46
  end
47
- while !@message_complete && (chunk = @adapter.get_body_chunk)
47
+ while !@message_complete && (chunk = @adapter.get_body_chunk(self))
48
48
  yield chunk
49
49
  end
50
50
  end
@@ -59,7 +59,7 @@ module Qeweney
59
59
  end
60
60
 
61
61
  def consume
62
- @adapter.consume_request
62
+ @adapter.consume_request(self)
63
63
  end
64
64
 
65
65
  def keep_alive?
@@ -68,7 +68,7 @@ module Qeweney
68
68
 
69
69
  def read
70
70
  buf = @buffered_body_chunks ? @buffered_body_chunks.join : nil
71
- while (chunk = @adapter.get_body_chunk)
71
+ while (chunk = @adapter.get_body_chunk(self))
72
72
  (buf ||= +'') << chunk
73
73
  end
74
74
  @buffered_body_chunks = nil
@@ -77,7 +77,7 @@ module Qeweney
77
77
  alias_method :body, :read
78
78
 
79
79
  def respond(body, headers = {})
80
- @adapter.respond(body, headers)
80
+ @adapter.respond(self, body, headers)
81
81
  @headers_sent = true
82
82
  end
83
83
 
@@ -85,24 +85,40 @@ module Qeweney
85
85
  return if @headers_sent
86
86
 
87
87
  @headers_sent = true
88
- @adapter.send_headers(headers, empty_response: empty_response)
88
+ @adapter.send_headers(self, headers, empty_response: empty_response)
89
89
  end
90
90
 
91
91
  def send_chunk(body, done: false)
92
92
  send_headers({}) unless @headers_sent
93
93
 
94
- @adapter.send_chunk(body, done: done)
94
+ @adapter.send_chunk(self, body, done: done)
95
95
  end
96
96
  alias_method :<<, :send_chunk
97
97
 
98
98
  def finish
99
99
  send_headers({}) unless @headers_sent
100
100
 
101
- @adapter.finish
101
+ @adapter.finish(self)
102
102
  end
103
103
 
104
104
  def headers_sent?
105
105
  @headers_sent
106
106
  end
107
+
108
+ def rx_incr(count)
109
+ headers[':rx'] ? headers[':rx'] += count : headers[':rx'] = count
110
+ end
111
+
112
+ def tx_incr(count)
113
+ headers[':tx'] ? headers[':tx'] += count : headers[':tx'] = count
114
+ end
115
+
116
+ def transfer_counts
117
+ [headers[':rx'], headers[':tx']]
118
+ end
119
+
120
+ def total_transfer
121
+ (headers[':rx'] || 0) + (headers[':tx'] || 0)
122
+ end
107
123
  end
108
124
  end
@@ -37,6 +37,10 @@ module Qeweney
37
37
  @uri ||= URI.parse(@headers[':path'] || '')
38
38
  end
39
39
 
40
+ def full_uri
41
+ @full_uri = "#{scheme}://#{host}#{uri}"
42
+ end
43
+
40
44
  def path
41
45
  @path ||= uri.path
42
46
  end
@@ -54,6 +58,7 @@ module Qeweney
54
58
  def split_query_string(query)
55
59
  query.split('&').each_with_object({}) do |kv, h|
56
60
  k, v = kv.split('=')
61
+ p split_query_string: { k: k, v: v }
57
62
  h[k.to_sym] = URI.decode_www_form_component(v)
58
63
  end
59
64
  end
@@ -74,6 +79,24 @@ module Qeweney
74
79
 
75
80
  encoding.split(',').map { |i| i.strip }
76
81
  end
82
+
83
+ def cookies
84
+ @cookies ||= parse_cookies(headers['cookie'])
85
+ end
86
+
87
+ COOKIE_RE = /^([^=]+)=(.*)$/.freeze
88
+ SEMICOLON = ';'
89
+
90
+ def parse_cookies(cookies)
91
+ return {} unless cookies
92
+
93
+ cookies.split(SEMICOLON).each_with_object({}) do |c, h|
94
+ raise BadRequestError, 'Invalid cookie format' unless c.strip =~ COOKIE_RE
95
+
96
+ key, value = Regexp.last_match[1..2]
97
+ h[key] = EscapeUtils.unescape_uri(value)
98
+ end
99
+ end
77
100
  end
78
101
 
79
102
  module RequestInfoClassMethods
@@ -138,7 +161,7 @@ module Qeweney
138
161
  MAX_PARAMETER_VALUE_SIZE = 2**20 # 1MB
139
162
 
140
163
  def parse_urlencoded_form_data(body)
141
- body.force_encoding(UTF_8) unless body.encoding == Encoding::UTF_8
164
+ body.force_encoding(Encoding::UTF_8) unless body.encoding == Encoding::UTF_8
142
165
  body.split('&').each_with_object({}) do |i, m|
143
166
  raise 'Invalid parameter format' unless i =~ PARAMETER_RE
144
167
 
@@ -6,6 +6,7 @@ require 'stringio'
6
6
  require 'digest/sha1'
7
7
 
8
8
  require_relative 'status'
9
+ require_relative 'mime_types'
9
10
 
10
11
  module Qeweney
11
12
  module StaticFileCaching
@@ -59,7 +60,7 @@ module Qeweney
59
60
  redirect(secure_uri, status)
60
61
  end
61
62
 
62
- def serve_file(path, opts)
63
+ def serve_file(path, opts = {})
63
64
  full_path = file_full_path(path, opts)
64
65
  stat = File.stat(full_path)
65
66
  etag = StaticFileCaching.file_stat_to_etag(stat)
@@ -72,17 +73,25 @@ module Qeweney
72
73
  })
73
74
  end
74
75
 
76
+ mime_type = Qeweney::MimeTypes[File.extname(path)]
77
+ (opts[:headers] ||= {})['Content-Type'] ||= mime_type if mime_type
78
+
75
79
  respond_with_static_file(full_path, etag, last_modified, opts)
76
80
  rescue Errno::ENOENT => e
77
81
  respond(nil, ':status' => Status::NOT_FOUND)
78
82
  end
79
83
 
80
84
  def respond_with_static_file(path, etag, last_modified, opts)
85
+ cache_headers = {
86
+ 'etag' => etag,
87
+ 'last-modified' => last_modified,
88
+ }
81
89
  File.open(path, 'r') do |f|
82
- opts = opts.merge(headers: {
83
- 'etag' => etag,
84
- 'last-modified' => last_modified,
85
- })
90
+ if opts[:headers]
91
+ opts[:headers].merge!(cache_headers)
92
+ else
93
+ opts[:headers] = cache_headers
94
+ end
86
95
 
87
96
  # accept_encoding should return encodings in client's order of preference
88
97
  accept_encoding.each do |encoding|
@@ -150,6 +159,7 @@ module Qeweney
150
159
 
151
160
  # TODO: send separate chunks for multi-part body
152
161
  # TODO: add support for streaming body
162
+ # TODO: add support for websocket
153
163
  end
154
164
  end
155
165
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Qeweney
4
- VERSION = '0.7.2'
4
+ VERSION = '0.8.1'
5
5
  end
@@ -20,4 +20,30 @@ class RequestInfoTest < MiniTest::Test
20
20
  r = Qeweney.mock('host' => 'my.example.com')
21
21
  assert_equal 'my.example.com', r.host
22
22
  end
23
+
24
+ def test_full_uri
25
+ r = Qeweney.mock(
26
+ ':scheme' => 'https',
27
+ 'host' => 'foo.bar',
28
+ ':path' => '/hey?a=b&c=d'
29
+ )
30
+
31
+ assert_equal 'https://foo.bar/hey?a=b&c=d', r.full_uri
32
+ end
33
+
34
+ def test_cookies
35
+ r = Qeweney.mock
36
+
37
+ assert_equal({}, r.cookies)
38
+
39
+ r = Qeweney.mock(
40
+ 'cookie' => 'uaid=a%2Fb; lastLocus=settings; signin_ref=/'
41
+ )
42
+
43
+ assert_equal({
44
+ 'uaid' => 'a/b',
45
+ 'lastLocus' => 'settings',
46
+ 'signin_ref' => '/'
47
+ }, r.cookies)
48
+ end
23
49
  end
@@ -8,7 +8,7 @@ class RedirectTest < MiniTest::Test
8
8
  r.redirect('/foo')
9
9
 
10
10
  assert_equal [
11
- [:respond, nil, {":status"=>302, "Location"=>"/foo"}]
11
+ [:respond, r, nil, {":status"=>302, "Location"=>"/foo"}]
12
12
  ], r.response_calls
13
13
  end
14
14
 
@@ -17,7 +17,7 @@ class RedirectTest < MiniTest::Test
17
17
  r.redirect('/bar', Qeweney::Status::MOVED_PERMANENTLY)
18
18
 
19
19
  assert_equal [
20
- [:respond, nil, {":status"=>301, "Location"=>"/bar"}]
20
+ [:respond, r, nil, {":status"=>301, "Location"=>"/bar"}]
21
21
  ], r.response_calls
22
22
  end
23
23
  end
@@ -37,7 +37,7 @@ class StaticFileResponeTest < MiniTest::Test
37
37
  r.serve_file('helper.rb', base_path: __dir__)
38
38
 
39
39
  assert_equal [
40
- [:respond, @content, { 'etag' => @etag, 'last-modified' => @last_modified }]
40
+ [:respond, r, @content, { 'etag' => @etag, 'last-modified' => @last_modified }]
41
41
  ], r.response_calls
42
42
  end
43
43
 
@@ -45,25 +45,25 @@ class StaticFileResponeTest < MiniTest::Test
45
45
  r = Qeweney.mock('if-none-match' => @etag)
46
46
  r.serve_file('helper.rb', base_path: __dir__)
47
47
  assert_equal [
48
- [:respond, nil, { 'etag' => @etag, ':status' => Qeweney::Status::NOT_MODIFIED }]
48
+ [:respond, r, nil, { 'etag' => @etag, ':status' => Qeweney::Status::NOT_MODIFIED }]
49
49
  ], r.response_calls
50
50
 
51
51
  r = Qeweney.mock('if-modified-since' => @last_modified)
52
52
  r.serve_file('helper.rb', base_path: __dir__)
53
53
  assert_equal [
54
- [:respond, nil, { 'etag' => @etag, ':status' => Qeweney::Status::NOT_MODIFIED }]
54
+ [:respond, r, nil, { 'etag' => @etag, ':status' => Qeweney::Status::NOT_MODIFIED }]
55
55
  ], r.response_calls
56
56
 
57
57
  r = Qeweney.mock('if-none-match' => 'foobar')
58
58
  r.serve_file('helper.rb', base_path: __dir__)
59
59
  assert_equal [
60
- [:respond, @content, { 'etag' => @etag, 'last-modified' => @last_modified }]
60
+ [:respond, r, @content, { 'etag' => @etag, 'last-modified' => @last_modified }]
61
61
  ], r.response_calls
62
62
 
63
63
  r = Qeweney.mock('if-modified-since' => Time.now.httpdate)
64
64
  r.serve_file('helper.rb', base_path: __dir__)
65
65
  assert_equal [
66
- [:respond, @content, { 'etag' => @etag, 'last-modified' => @last_modified }]
66
+ [:respond, r, @content, { 'etag' => @etag, 'last-modified' => @last_modified }]
67
67
  ], r.response_calls
68
68
  end
69
69
 
@@ -75,7 +75,7 @@ class StaticFileResponeTest < MiniTest::Test
75
75
  deflated_content = deflate.deflate(@content, Zlib::FINISH)
76
76
 
77
77
  assert_equal [
78
- [:respond, deflated_content, {
78
+ [:respond, r, deflated_content, {
79
79
  'etag' => @etag,
80
80
  'last-modified' => @last_modified,
81
81
  'vary' => 'Accept-Encoding',
@@ -96,7 +96,7 @@ class StaticFileResponeTest < MiniTest::Test
96
96
  gzipped_content = buf.string
97
97
 
98
98
  assert_equal [
99
- [:respond, gzipped_content, {
99
+ [:respond, r, gzipped_content, {
100
100
  'etag' => @etag,
101
101
  'last-modified' => @last_modified,
102
102
  'vary' => 'Accept-Encoding',
@@ -109,7 +109,7 @@ class StaticFileResponeTest < MiniTest::Test
109
109
  r = Qeweney.mock
110
110
  r.serve_file('foo.rb', base_path: __dir__)
111
111
  assert_equal [
112
- [:respond, nil, { ':status' => Qeweney::Status::NOT_FOUND }]
112
+ [:respond, r, nil, { ':status' => Qeweney::Status::NOT_FOUND }]
113
113
  ], r.response_calls
114
114
  end
115
115
  end
@@ -120,7 +120,7 @@ class UpgradeTest < MiniTest::Test
120
120
  r.upgrade('df')
121
121
 
122
122
  assert_equal [
123
- [:respond, nil, {
123
+ [:respond, r, nil, {
124
124
  ':status' => 101,
125
125
  'Upgrade' => 'df',
126
126
  'Connection' => 'upgrade'
@@ -132,7 +132,7 @@ class UpgradeTest < MiniTest::Test
132
132
  r.upgrade('df', { 'foo' => 'bar' })
133
133
 
134
134
  assert_equal [
135
- [:respond, nil, {
135
+ [:respond, r, nil, {
136
136
  ':status' => 101,
137
137
  'Upgrade' => 'df',
138
138
  'Connection' => 'upgrade',
@@ -155,7 +155,7 @@ class UpgradeTest < MiniTest::Test
155
155
  accept = Digest::SHA1.base64digest('abcdefghij258EAFA5-E914-47DA-95CA-C5AB0DC85B11')
156
156
 
157
157
  assert_equal [
158
- [:respond, nil, {
158
+ [:respond, r, nil, {
159
159
  ':status' => 101,
160
160
  'Upgrade' => 'websocket',
161
161
  'Connection' => 'upgrade',
@@ -179,7 +179,7 @@ class ServeRackTest < MiniTest::Test
179
179
  })
180
180
 
181
181
  assert_equal [
182
- [:respond, "get /foo/bar", {':status' => 404, 'Foo' => 'Bar' }]
182
+ [:respond, r, 'get /foo/bar', {':status' => 404, 'Foo' => 'Bar' }]
183
183
  ], r.response_calls
184
184
  end
185
185
  end
data/test/test_routing.rb CHANGED
@@ -19,27 +19,27 @@ class RoutingTest < MiniTest::Test
19
19
  def test_app1
20
20
  r = Qeweney.mock(':path' => '/foo')
21
21
  App1.(r)
22
- assert_equal [[:respond, nil, { ':status' => 404 }]], r.response_calls
22
+ assert_equal [[:respond, r, nil, { ':status' => 404 }]], r.response_calls
23
23
 
24
24
  r = Qeweney.mock(':path' => '/')
25
25
  App1.(r)
26
- assert_equal [[:respond, nil, { ':status' => 302, 'Location' => '/hello' }]], r.response_calls
26
+ assert_equal [[:respond, r, nil, { ':status' => 302, 'Location' => '/hello' }]], r.response_calls
27
27
 
28
28
  r = Qeweney.mock(':path' => '/hello', ':method' => 'foo')
29
29
  App1.(r)
30
- assert_equal [[:respond, nil, { ':status' => 404 }]], r.response_calls
30
+ assert_equal [[:respond, r, nil, { ':status' => 404 }]], r.response_calls
31
31
 
32
32
  r = Qeweney.mock(':path' => '/hello', ':method' => 'get')
33
33
  App1.(r)
34
- assert_equal [[:respond, 'Hello', {}]], r.response_calls
34
+ assert_equal [[:respond, r, 'Hello', {}]], r.response_calls
35
35
 
36
36
  r = Qeweney.mock(':path' => '/hello', ':method' => 'post')
37
37
  App1.(r)
38
- assert_equal [[:respond, nil, { ':status' => 302, 'Location' => '/' }]], r.response_calls
38
+ assert_equal [[:respond, r, nil, { ':status' => 302, 'Location' => '/' }]], r.response_calls
39
39
 
40
40
  r = Qeweney.mock(':path' => '/hello/world', ':method' => 'get')
41
41
  App1.(r)
42
- assert_equal [[:respond, 'Hello world', {}]], r.response_calls
42
+ assert_equal [[:respond, r, 'Hello world', {}]], r.response_calls
43
43
  end
44
44
 
45
45
  def test_on_root
@@ -58,19 +58,19 @@ class RoutingTest < MiniTest::Test
58
58
 
59
59
  r = Qeweney.mock(':path' => '/')
60
60
  app.(r)
61
- assert_equal [[:respond, 'root', {}]], r.response_calls
61
+ assert_equal [[:respond, r, 'root', {}]], r.response_calls
62
62
 
63
63
  r = Qeweney.mock(':path' => '/foo')
64
64
  app.(r)
65
- assert_equal [[:respond, 'foo root', {}]], r.response_calls
65
+ assert_equal [[:respond, r, 'foo root', {}]], r.response_calls
66
66
 
67
67
  r = Qeweney.mock(':path' => '/foo/bar')
68
68
  app.(r)
69
- assert_equal [[:respond, 'bar root', {}]], r.response_calls
69
+ assert_equal [[:respond, r, 'bar root', {}]], r.response_calls
70
70
 
71
71
  r = Qeweney.mock(':path' => '/foo/bar/baz')
72
72
  app.(r)
73
- assert_equal [[:respond, 'baz root', {}]], r.response_calls
73
+ assert_equal [[:respond, r, 'baz root', {}]], r.response_calls
74
74
  end
75
75
 
76
76
  def test_relative_path
@@ -90,27 +90,27 @@ class RoutingTest < MiniTest::Test
90
90
  r = Qeweney.mock(':path' => '/')
91
91
  app.(r)
92
92
  assert_equal '/', default_relative_path
93
- assert_equal [[:respond, 'ROOT/', {}]], r.response_calls
93
+ assert_equal [[:respond, r, 'ROOT/', {}]], r.response_calls
94
94
 
95
95
 
96
96
  r = Qeweney.mock(':path' => '/foo/bar/baz')
97
97
  app.(r)
98
98
  assert_equal '/foo/bar/baz', default_relative_path
99
- assert_equal [[:respond, 'FOO/bar/baz', {}]], r.response_calls
99
+ assert_equal [[:respond, r, 'FOO/bar/baz', {}]], r.response_calls
100
100
 
101
101
  r = Qeweney.mock(':path' => '/bar/a/b/c')
102
102
  app.(r)
103
103
  assert_equal '/bar/a/b/c', default_relative_path
104
- assert_equal [[:respond, 'BAR/a/b/c', {}]], r.response_calls
104
+ assert_equal [[:respond, r, 'BAR/a/b/c', {}]], r.response_calls
105
105
 
106
106
  r = Qeweney.mock(':path' => '/bar/baz/b/c')
107
107
  app.(r)
108
108
  assert_equal '/bar/baz/b/c', default_relative_path
109
- assert_equal [[:respond, 'BAR/BAZ/b/c', {}]], r.response_calls
109
+ assert_equal [[:respond, r, 'BAR/BAZ/b/c', {}]], r.response_calls
110
110
 
111
111
  r = Qeweney.mock(':path' => '/baz/d/e/f')
112
112
  app.(r)
113
113
  assert_equal '/baz/d/e/f', default_relative_path
114
- assert_equal [[:respond, '/d/e/f', {}]], r.response_calls
114
+ assert_equal [[:respond, r, '/d/e/f', {}]], r.response_calls
115
115
  end
116
116
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qeweney
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.8.1
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-04 00:00:00.000000000 Z
11
+ date: 2021-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: escape_utils
@@ -136,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
136
136
  - !ruby/object:Gem::Version
137
137
  version: '0'
138
138
  requirements: []
139
- rubygems_version: 3.1.4
139
+ rubygems_version: 3.0.8
140
140
  signing_key:
141
141
  specification_version: 4
142
142
  summary: Qeweney - cross library HTTP request / response API