qeweney 0.14 → 0.15
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/FUNDING.yml +1 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +3 -3
- data/examples/routing_benchmark.rb +1 -1
- data/lib/qeweney/rack.rb +5 -5
- data/lib/qeweney/request.rb +10 -11
- data/lib/qeweney/request_info.rb +16 -16
- data/lib/qeweney/response.rb +2 -2
- data/lib/qeweney/routing.rb +13 -8
- data/lib/qeweney/status.rb +1 -1
- data/lib/qeweney/test_adapter.rb +26 -0
- data/lib/qeweney/version.rb +1 -1
- data/lib/qeweney.rb +0 -1
- data/test/helper.rb +0 -5
- data/test/test_response.rb +4 -4
- data/test/test_routing.rb +1 -1
- data/test/test_test_adapter.rb +15 -0
- metadata +10 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a776c09a368fd3b348a685f43dcffb40320e6d181529427f7659e56815994735
|
4
|
+
data.tar.gz: 9ba936914a124c9a21923c147cf5d90b76cb6ea4dde46cbeeb558d99909a9d86
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f49f57a3c037646789565e1adb8c5ba129b1ed7e3f7b2ddbc3ec6a11c150d9e946728fcb2912af84c69070c1cefab00be707aed104b5eda2a7a9845cc14c5b8
|
7
|
+
data.tar.gz: 214702b726cb0c4c18fd380f3d4d985955002bad65a7e80ac0072da78d2014eea8a0c604256deefaab9c5adbb77fec0c155397df9dbcd868b2410f13a884e89a
|
data/.github/FUNDING.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
github: ciconia
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
qeweney (0.
|
4
|
+
qeweney (0.15)
|
5
5
|
escape_utils (~> 1.2.1)
|
6
6
|
|
7
7
|
GEM
|
@@ -21,7 +21,7 @@ GEM
|
|
21
21
|
ruby-progressbar (1.11.0)
|
22
22
|
|
23
23
|
PLATFORMS
|
24
|
-
|
24
|
+
x86_64-linux
|
25
25
|
|
26
26
|
DEPENDENCIES
|
27
27
|
benchmark-ips (~> 2.8.3)
|
@@ -31,4 +31,4 @@ DEPENDENCIES
|
|
31
31
|
rake (~> 12.3.3)
|
32
32
|
|
33
33
|
BUNDLED WITH
|
34
|
-
2.
|
34
|
+
2.3.3
|
data/lib/qeweney/rack.rb
CHANGED
@@ -74,15 +74,15 @@ module Qeweney
|
|
74
74
|
def initialize(request)
|
75
75
|
@request = request
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
def gets; end
|
79
|
-
|
79
|
+
|
80
80
|
def read(length = nil, outbuf = nil); end
|
81
|
-
|
81
|
+
|
82
82
|
def each(&block)
|
83
83
|
@request.each_chunk(&block)
|
84
84
|
end
|
85
|
-
|
85
|
+
|
86
86
|
def rewind; end
|
87
87
|
end
|
88
88
|
|
@@ -110,7 +110,7 @@ module Qeweney
|
|
110
110
|
'rack.multipart.buffer_size' => nil,
|
111
111
|
'rack.multipar.tempfile_factory' => nil
|
112
112
|
}
|
113
|
-
|
113
|
+
|
114
114
|
HTTP_HEADER_RE = /^HTTP_(.+)$/.freeze
|
115
115
|
|
116
116
|
def self.rack_env_value_from_request(request, key)
|
data/lib/qeweney/request.rb
CHANGED
@@ -15,13 +15,12 @@ module Qeweney
|
|
15
15
|
extend RequestInfoClassMethods
|
16
16
|
|
17
17
|
attr_reader :headers, :adapter
|
18
|
-
|
19
|
-
|
18
|
+
|
20
19
|
def initialize(headers, adapter)
|
21
20
|
@headers = headers
|
22
21
|
@adapter = adapter
|
23
22
|
end
|
24
|
-
|
23
|
+
|
25
24
|
def buffer_body_chunk(chunk)
|
26
25
|
@buffered_body_chunks ||= []
|
27
26
|
@buffered_body_chunks << chunk
|
@@ -38,7 +37,7 @@ module Qeweney
|
|
38
37
|
|
39
38
|
@adapter.get_body_chunk(self, buffered_only)
|
40
39
|
end
|
41
|
-
|
40
|
+
|
42
41
|
def each_chunk
|
43
42
|
if @buffered_body_chunks
|
44
43
|
while (chunk = @buffered_body_chunks.shift)
|
@@ -68,29 +67,29 @@ module Qeweney
|
|
68
67
|
def complete?
|
69
68
|
@adapter.complete?(self)
|
70
69
|
end
|
71
|
-
|
70
|
+
|
72
71
|
def respond(body, headers = {})
|
73
72
|
@adapter.respond(self, body, headers)
|
74
73
|
@headers_sent = true
|
75
74
|
end
|
76
|
-
|
75
|
+
|
77
76
|
def send_headers(headers = {}, empty_response = false)
|
78
77
|
return if @headers_sent
|
79
|
-
|
78
|
+
|
80
79
|
@headers_sent = true
|
81
80
|
@adapter.send_headers(self, headers, empty_response: empty_response)
|
82
81
|
end
|
83
|
-
|
82
|
+
|
84
83
|
def send_chunk(body, done: false)
|
85
84
|
send_headers({}) unless @headers_sent
|
86
|
-
|
85
|
+
|
87
86
|
@adapter.send_chunk(self, body, done: done)
|
88
87
|
end
|
89
88
|
alias_method :<<, :send_chunk
|
90
|
-
|
89
|
+
|
91
90
|
def finish
|
92
91
|
send_headers({}) unless @headers_sent
|
93
|
-
|
92
|
+
|
94
93
|
@adapter.finish(self)
|
95
94
|
end
|
96
95
|
|
data/lib/qeweney/request_info.rb
CHANGED
@@ -25,39 +25,39 @@ module Qeweney
|
|
25
25
|
def protocol
|
26
26
|
@protocol ||= @adapter.protocol
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
def method
|
30
30
|
@method ||= @headers[':method'].downcase
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def scheme
|
34
34
|
@scheme ||= @headers[':scheme']
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def uri
|
38
38
|
@uri ||= URI.parse(@headers[':path'] || '')
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
def full_uri
|
42
42
|
@full_uri = "#{scheme}://#{host}#{uri}"
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
def path
|
46
46
|
@path ||= uri.path
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
def query_string
|
50
50
|
@query_string ||= uri.query
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
def query
|
54
54
|
return @query if @query
|
55
|
-
|
55
|
+
|
56
56
|
@query = (q = uri.query) ? parse_query(q) : {}
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
QUERY_KV_REGEXP = /([^=]+)(?:=(.*))?/
|
60
|
-
|
60
|
+
|
61
61
|
def parse_query(query)
|
62
62
|
query.split('&').each_with_object({}) do |kv, h|
|
63
63
|
k, v = kv.match(QUERY_KV_REGEXP)[1..2]
|
@@ -89,13 +89,13 @@ module Qeweney
|
|
89
89
|
|
90
90
|
COOKIE_RE = /^([^=]+)=(.*)$/.freeze
|
91
91
|
SEMICOLON = ';'
|
92
|
-
|
92
|
+
|
93
93
|
def parse_cookies(cookies)
|
94
94
|
return {} unless cookies
|
95
95
|
|
96
96
|
cookies.split(SEMICOLON).each_with_object({}) do |c, h|
|
97
97
|
raise BadRequestError, 'Invalid cookie format' unless c.strip =~ COOKIE_RE
|
98
|
-
|
98
|
+
|
99
99
|
key, value = Regexp.last_match[1..2]
|
100
100
|
h[key] = EscapeUtils.unescape_uri(value)
|
101
101
|
end
|
@@ -151,7 +151,7 @@ module Qeweney
|
|
151
151
|
break if header.empty?
|
152
152
|
|
153
153
|
next unless header =~ /^([^\:]+)\:\s?(.+)$/
|
154
|
-
|
154
|
+
|
155
155
|
headers[Regexp.last_match(1).downcase] = Regexp.last_match(2)
|
156
156
|
end
|
157
157
|
# remove trailing \r\n
|
@@ -169,13 +169,13 @@ module Qeweney
|
|
169
169
|
body.force_encoding(Encoding::UTF_8) unless body.encoding == Encoding::UTF_8
|
170
170
|
body.split('&').each_with_object({}) do |i, m|
|
171
171
|
raise 'Invalid parameter format' unless i =~ PARAMETER_RE
|
172
|
-
|
172
|
+
|
173
173
|
k = Regexp.last_match(1)
|
174
174
|
raise 'Invalid parameter size' if k.size > MAX_PARAMETER_NAME_SIZE
|
175
|
-
|
175
|
+
|
176
176
|
v = Regexp.last_match(2)
|
177
177
|
raise 'Invalid parameter size' if v.size > MAX_PARAMETER_VALUE_SIZE
|
178
|
-
|
178
|
+
|
179
179
|
m[EscapeUtils.unescape_uri(k)] = EscapeUtils.unescape_uri(v)
|
180
180
|
end
|
181
181
|
end
|
data/lib/qeweney/response.rb
CHANGED
@@ -14,7 +14,7 @@ module Qeweney
|
|
14
14
|
def file_stat_to_etag(stat)
|
15
15
|
"#{stat.mtime.to_i.to_s(36)}#{stat.size.to_s(36)}"
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def file_stat_to_last_modified(stat)
|
19
19
|
stat.mtime.httpdate
|
20
20
|
end
|
@@ -114,7 +114,7 @@ module Qeweney
|
|
114
114
|
if (modified_since = headers['if-modified-since'])
|
115
115
|
return true if modified_since == last_modified
|
116
116
|
end
|
117
|
-
|
117
|
+
|
118
118
|
false
|
119
119
|
end
|
120
120
|
|
data/lib/qeweney/routing.rb
CHANGED
@@ -10,7 +10,7 @@ module Qeweney
|
|
10
10
|
(@path_parts ||= path.split('/'))[@path_parts_idx ||= 1]
|
11
11
|
res = catch(:stop) { yield self }
|
12
12
|
return if res == :found
|
13
|
-
|
13
|
+
|
14
14
|
respond(nil, ':status' => 404)
|
15
15
|
end
|
16
16
|
|
@@ -39,11 +39,11 @@ module Qeweney
|
|
39
39
|
|
40
40
|
def on(route, &block)
|
41
41
|
return route_found(&block) unless route
|
42
|
-
|
42
|
+
|
43
43
|
route_parts = route.split('/')
|
44
44
|
route_length = route_parts.size
|
45
45
|
return unless @path_parts[@path_parts_idx, route_length] == route_parts
|
46
|
-
|
46
|
+
|
47
47
|
enter_route(route_length)
|
48
48
|
route_found(&block)
|
49
49
|
leave_route(route_length)
|
@@ -72,22 +72,22 @@ module Qeweney
|
|
72
72
|
|
73
73
|
route_found(&block)
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
def on_get(route = nil, &block)
|
77
77
|
return unless method == 'get'
|
78
|
-
|
78
|
+
|
79
79
|
on(route, &block)
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
def on_post(route = nil, &block)
|
83
83
|
return unless method == 'post'
|
84
|
-
|
84
|
+
|
85
85
|
on(route, &block)
|
86
86
|
end
|
87
87
|
|
88
88
|
def on_options(route = nil, &block)
|
89
89
|
return unless method == 'options'
|
90
|
-
|
90
|
+
|
91
91
|
on(route, &block)
|
92
92
|
end
|
93
93
|
|
@@ -124,6 +124,11 @@ module Qeweney
|
|
124
124
|
on_upgrade('websocket', &block)
|
125
125
|
end
|
126
126
|
|
127
|
+
def reject(body, status)
|
128
|
+
respond(body, ':status' => status)
|
129
|
+
throw :stop, :found
|
130
|
+
end
|
131
|
+
|
127
132
|
def stop_routing
|
128
133
|
throw :stop, :found
|
129
134
|
end
|
data/lib/qeweney/status.rb
CHANGED
@@ -5,7 +5,7 @@ module Qeweney
|
|
5
5
|
module Status
|
6
6
|
# translated from https://golang.org/pkg/net/http/#pkg-constants
|
7
7
|
# https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
8
|
-
|
8
|
+
|
9
9
|
CONTINUE = 100 # RFC 7231, 6.2.1
|
10
10
|
SWITCHING_PROTOCOLS = 101 # RFC 7231, 6.2.2
|
11
11
|
PROCESSING = 102 # RFC 2518, 10.1
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Qeweney
|
4
|
+
class TestAdapter
|
5
|
+
attr_reader :body, :headers
|
6
|
+
|
7
|
+
def get_body_chunk
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def respond(req, body, headers)
|
12
|
+
@body = body
|
13
|
+
@headers = headers
|
14
|
+
end
|
15
|
+
|
16
|
+
def status
|
17
|
+
headers[':status']
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.mock(headers = {})
|
21
|
+
headers[':method'] ||= ''
|
22
|
+
headers[':path'] ||= ''
|
23
|
+
Request.new(headers, new)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/qeweney/version.rb
CHANGED
data/lib/qeweney.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -8,7 +8,6 @@ require 'fileutils'
|
|
8
8
|
require_relative './coverage' if ENV['COVERAGE']
|
9
9
|
|
10
10
|
require 'minitest/autorun'
|
11
|
-
require 'minitest/reporters'
|
12
11
|
|
13
12
|
module Qeweney
|
14
13
|
class MockAdapter
|
@@ -35,7 +34,3 @@ module Qeweney
|
|
35
34
|
end
|
36
35
|
end
|
37
36
|
end
|
38
|
-
|
39
|
-
Minitest::Reporters.use! [
|
40
|
-
Minitest::Reporters::SpecReporter.new
|
41
|
-
]
|
data/test/test_response.rb
CHANGED
@@ -73,7 +73,7 @@ class StaticFileResponeTest < MiniTest::Test
|
|
73
73
|
|
74
74
|
deflate = Zlib::Deflate.new
|
75
75
|
deflated_content = deflate.deflate(@content, Zlib::FINISH)
|
76
|
-
|
76
|
+
|
77
77
|
assert_equal [
|
78
78
|
[:respond, r, deflated_content, {
|
79
79
|
'etag' => @etag,
|
@@ -94,7 +94,7 @@ class StaticFileResponeTest < MiniTest::Test
|
|
94
94
|
z.flush
|
95
95
|
z.close
|
96
96
|
gzipped_content = buf.string
|
97
|
-
|
97
|
+
|
98
98
|
assert_equal [
|
99
99
|
[:respond, r, gzipped_content, {
|
100
100
|
'etag' => @etag,
|
@@ -127,7 +127,7 @@ class UpgradeTest < MiniTest::Test
|
|
127
127
|
}]
|
128
128
|
], r.response_calls
|
129
129
|
|
130
|
-
|
130
|
+
|
131
131
|
r = Qeweney.mock
|
132
132
|
r.upgrade('df', { 'foo' => 'bar' })
|
133
133
|
|
@@ -148,7 +148,7 @@ class UpgradeTest < MiniTest::Test
|
|
148
148
|
'sec-websocket-version' => '23',
|
149
149
|
'sec-websocket-key' => 'abcdefghij'
|
150
150
|
)
|
151
|
-
|
151
|
+
|
152
152
|
assert_equal 'websocket', r.upgrade_protocol
|
153
153
|
|
154
154
|
r.upgrade_to_websocket('foo' => 'baz')
|
data/test/test_routing.rb
CHANGED
@@ -81,7 +81,7 @@ class RoutingTest < MiniTest::Test
|
|
81
81
|
default_relative_path = r.route_relative_path
|
82
82
|
r.on_root { r.respond(File.join('ROOT', r.route_relative_path)) }
|
83
83
|
r.on('foo') { r.respond(File.join('FOO', r.route_relative_path)) }
|
84
|
-
r.on('bar') {
|
84
|
+
r.on('bar') {
|
85
85
|
r.on('baz') { r.respond(File.join('BAR/BAZ', r.route_relative_path)) }
|
86
86
|
r.default { r.respond(File.join('BAR', r.route_relative_path)) }
|
87
87
|
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helper'
|
4
|
+
require 'qeweney/test_adapter'
|
5
|
+
|
6
|
+
class TestAdapterTest < MiniTest::Test
|
7
|
+
def test_test_adapter
|
8
|
+
adapter = Qeweney::TestAdapter.new
|
9
|
+
req = Qeweney::Request.new({ ':path' => '/foo' }, adapter)
|
10
|
+
req.respond('bar', 'Content-Type' => 'baz')
|
11
|
+
|
12
|
+
assert_equal 'bar', adapter.body
|
13
|
+
assert_equal({'Content-Type' => 'baz'}, adapter.headers)
|
14
|
+
end
|
15
|
+
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.
|
4
|
+
version: '0.15'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: escape_utils
|
@@ -80,13 +80,14 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 2.8.3
|
83
|
-
description:
|
83
|
+
description:
|
84
84
|
email: sharon@noteflakes.com
|
85
85
|
executables: []
|
86
86
|
extensions: []
|
87
87
|
extra_rdoc_files:
|
88
88
|
- README.md
|
89
89
|
files:
|
90
|
+
- ".github/FUNDING.yml"
|
90
91
|
- ".github/workflows/test.yml"
|
91
92
|
- ".gitignore"
|
92
93
|
- CHANGELOG.md
|
@@ -105,6 +106,7 @@ files:
|
|
105
106
|
- lib/qeweney/response.rb
|
106
107
|
- lib/qeweney/routing.rb
|
107
108
|
- lib/qeweney/status.rb
|
109
|
+
- lib/qeweney/test_adapter.rb
|
108
110
|
- lib/qeweney/version.rb
|
109
111
|
- qeweney.gemspec
|
110
112
|
- test/helper.rb
|
@@ -112,12 +114,13 @@ files:
|
|
112
114
|
- test/test_request_info.rb
|
113
115
|
- test/test_response.rb
|
114
116
|
- test/test_routing.rb
|
117
|
+
- test/test_test_adapter.rb
|
115
118
|
homepage: http://github.com/digital-fabric/qeweney
|
116
119
|
licenses:
|
117
120
|
- MIT
|
118
121
|
metadata:
|
119
122
|
source_code_uri: https://github.com/digital-fabric/qeweney
|
120
|
-
post_install_message:
|
123
|
+
post_install_message:
|
121
124
|
rdoc_options:
|
122
125
|
- "--title"
|
123
126
|
- Qeweney
|
@@ -136,8 +139,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
136
139
|
- !ruby/object:Gem::Version
|
137
140
|
version: '0'
|
138
141
|
requirements: []
|
139
|
-
rubygems_version: 3.
|
140
|
-
signing_key:
|
142
|
+
rubygems_version: 3.3.3
|
143
|
+
signing_key:
|
141
144
|
specification_version: 4
|
142
145
|
summary: Qeweney - cross library HTTP request / response API
|
143
146
|
test_files: []
|