protocol-http 0.16.3 → 0.20.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 +4 -4
- data/.editorconfig +0 -1
- data/.github/workflows/development.yml +44 -0
- data/.gitignore +2 -1
- data/README.md +13 -13
- data/bake.rb +37 -0
- data/{Gemfile → gems.rb} +5 -0
- data/lib/protocol/http/body/buffered.rb +6 -10
- data/lib/protocol/http/body/digestable.rb +67 -0
- data/lib/protocol/http/body/file.rb +4 -0
- data/lib/protocol/http/body/head.rb +4 -0
- data/lib/protocol/http/body/readable.rb +7 -0
- data/lib/protocol/http/body/rewindable.rb +4 -11
- data/lib/protocol/http/body/wrapper.rb +10 -0
- data/lib/protocol/http/cookie.rb +1 -1
- data/lib/protocol/http/header/authorization.rb +15 -13
- data/lib/protocol/http/header/etag.rb +0 -2
- data/lib/protocol/http/headers.rb +52 -43
- data/lib/protocol/http/methods.rb +2 -2
- data/lib/protocol/http/middleware.rb +8 -0
- data/lib/protocol/http/reference.rb +1 -3
- data/lib/protocol/http/request.rb +2 -7
- data/lib/protocol/http/response.rb +3 -8
- data/lib/protocol/http/version.rb +1 -1
- data/protocol-http.gemspec +1 -2
- metadata +12 -24
- data/.travis.yml +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f14e6a0192840efd07d2ba8e8e3a8bd9312eb5fa8b976f1e12baaf14ee49696
|
4
|
+
data.tar.gz: 2548bc880b20a5e162cad7fdcbbece9a0cdfae429861b8a5f1bbd68cf904cb9b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1e6692c96818aed1ed11c02b976169598ba9df9afc1f73109745168f62d85a75b6bf9abe530cac1daa39a3a40b5a815e06280581d8912b6c32f7e488f35fac0
|
7
|
+
data.tar.gz: 747e961c97c027258a46fbbd70f9845eead55d0c3dc6d108dae0083b99693bf5384f3868c9d50e5270d06337341879d265dc362a7907a16d22ecca73149e8223
|
data/.editorconfig
CHANGED
@@ -0,0 +1,44 @@
|
|
1
|
+
name: Development
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
test:
|
7
|
+
runs-on: ${{matrix.os}}-latest
|
8
|
+
continue-on-error: ${{matrix.experimental}}
|
9
|
+
|
10
|
+
strategy:
|
11
|
+
matrix:
|
12
|
+
os:
|
13
|
+
- ubuntu
|
14
|
+
- macos
|
15
|
+
|
16
|
+
ruby:
|
17
|
+
- 2.5
|
18
|
+
- 2.6
|
19
|
+
- 2.7
|
20
|
+
|
21
|
+
experimental: [false]
|
22
|
+
env: [""]
|
23
|
+
|
24
|
+
include:
|
25
|
+
- os: ubuntu
|
26
|
+
ruby: truffleruby
|
27
|
+
experimental: true
|
28
|
+
- os: ubuntu
|
29
|
+
ruby: jruby
|
30
|
+
experimental: true
|
31
|
+
- os: ubuntu
|
32
|
+
ruby: head
|
33
|
+
experimental: true
|
34
|
+
|
35
|
+
steps:
|
36
|
+
- uses: actions/checkout@v2
|
37
|
+
- uses: ioquatix/setup-ruby@master
|
38
|
+
with:
|
39
|
+
ruby-version: ${{matrix.ruby}}
|
40
|
+
bundler-cache: true
|
41
|
+
|
42
|
+
- name: Run tests
|
43
|
+
timeout-minutes: 5
|
44
|
+
run: ${{matrix.env}} bundle exec rspec
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -2,29 +2,29 @@
|
|
2
2
|
|
3
3
|
Provides abstractions for working with the HTTP protocol.
|
4
4
|
|
5
|
-
[](https://github.com/socketry/protocol-http/actions?workflow=Development)
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
9
9
|
Add this line to your application's Gemfile:
|
10
10
|
|
11
|
-
```ruby
|
11
|
+
``` ruby
|
12
12
|
gem 'protocol-http'
|
13
13
|
```
|
14
14
|
|
15
15
|
And then execute:
|
16
16
|
|
17
|
-
|
17
|
+
$ bundle
|
18
18
|
|
19
19
|
Or install it yourself as:
|
20
20
|
|
21
|
-
|
21
|
+
$ gem install protocol-http
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
25
|
### Headers
|
26
26
|
|
27
|
-
```ruby
|
27
|
+
``` ruby
|
28
28
|
require 'protocol/http/headers'
|
29
29
|
|
30
30
|
headers = Protocol::HTTP::Headers.new
|
@@ -37,7 +37,7 @@ headers['content-type']
|
|
37
37
|
|
38
38
|
### Reference
|
39
39
|
|
40
|
-
```ruby
|
40
|
+
``` ruby
|
41
41
|
require 'protocol/http/reference'
|
42
42
|
|
43
43
|
reference = Protocol::HTTP::Reference.new("/search", q: 'kittens')
|
@@ -48,7 +48,7 @@ reference.to_s
|
|
48
48
|
|
49
49
|
### URL
|
50
50
|
|
51
|
-
```ruby
|
51
|
+
``` ruby
|
52
52
|
require 'protocol/http/url'
|
53
53
|
|
54
54
|
reference = Protocol::HTTP::Reference.parse("/search?q=kittens")
|
@@ -59,17 +59,17 @@ parameters = Protocol::HTTP::URL.decode(reference.query_string)
|
|
59
59
|
|
60
60
|
## Contributing
|
61
61
|
|
62
|
-
1.
|
63
|
-
2.
|
64
|
-
3.
|
65
|
-
4.
|
66
|
-
5.
|
62
|
+
1. Fork it
|
63
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
64
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
65
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
66
|
+
5. Create new Pull Request
|
67
67
|
|
68
68
|
## License
|
69
69
|
|
70
70
|
Released under the MIT license.
|
71
71
|
|
72
|
-
Copyright, 2019, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
|
72
|
+
Copyright, 2019, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
|
73
73
|
|
74
74
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
75
75
|
of this software and associated documentation files (the "Software"), to deal
|
data/bake.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
def external
|
4
|
+
require 'bundler'
|
5
|
+
|
6
|
+
Bundler.with_unbundled_env do
|
7
|
+
clone_and_test("protocol-http1")
|
8
|
+
clone_and_test("protocol-http2")
|
9
|
+
clone_and_test("async-websocket")
|
10
|
+
clone_and_test("async-http")
|
11
|
+
clone_and_test("async-rest")
|
12
|
+
clone_and_test("falcon")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def clone_and_test(name)
|
19
|
+
path = "external/#{name}"
|
20
|
+
|
21
|
+
unless File.exist?(path)
|
22
|
+
system("git", "clone", "https://git@github.com/socketry/#{name}", path)
|
23
|
+
end
|
24
|
+
|
25
|
+
gemfile = [
|
26
|
+
File.join(path, "gems.rb"),
|
27
|
+
File.join(path, "Gemfile"),
|
28
|
+
].find{|path| File.exist?(path)}
|
29
|
+
|
30
|
+
system("git", "checkout", "-f", File.basename(gemfile), chdir: path)
|
31
|
+
|
32
|
+
File.open(gemfile, "a") do |file|
|
33
|
+
file.puts('', 'gem "protocol-http", path: "../../"')
|
34
|
+
end
|
35
|
+
|
36
|
+
system("bundle install && bundle exec rspec", chdir: path)
|
37
|
+
end
|
data/{Gemfile → gems.rb}
RENAMED
@@ -22,8 +22,6 @@
|
|
22
22
|
|
23
23
|
require_relative 'readable'
|
24
24
|
|
25
|
-
require 'digest/sha2'
|
26
|
-
|
27
25
|
module Protocol
|
28
26
|
module HTTP
|
29
27
|
module Body
|
@@ -61,14 +59,7 @@ module Protocol
|
|
61
59
|
@digest = nil
|
62
60
|
end
|
63
61
|
|
64
|
-
|
65
|
-
if @digest.nil?
|
66
|
-
@digest = Digest::SHA256.new
|
67
|
-
@chunks.each{|chunk| @digest.update(chunk)}
|
68
|
-
end
|
69
|
-
|
70
|
-
@digest.hexdigest
|
71
|
-
end
|
62
|
+
attr :chunks
|
72
63
|
|
73
64
|
def finish
|
74
65
|
self
|
@@ -82,6 +73,11 @@ module Protocol
|
|
82
73
|
@index >= @chunks.length
|
83
74
|
end
|
84
75
|
|
76
|
+
# A buffered response is always ready.
|
77
|
+
def ready?
|
78
|
+
true
|
79
|
+
end
|
80
|
+
|
85
81
|
def read
|
86
82
|
if chunk = @chunks[@index]
|
87
83
|
@index += 1
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
# THE SOFTWARE.
|
22
|
+
|
23
|
+
require_relative 'wrapper'
|
24
|
+
|
25
|
+
require 'digest/sha2'
|
26
|
+
|
27
|
+
module Protocol
|
28
|
+
module HTTP
|
29
|
+
module Body
|
30
|
+
# Invokes a callback once the body has finished reading.
|
31
|
+
class Digestable < Wrapper
|
32
|
+
def self.wrap(message, digest = Digest::SHA256.new, &block)
|
33
|
+
if body = message&.body and !body.empty?
|
34
|
+
message.body = self.new(message.body, digest, block)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(body, digest = Digest::SHA256.new, callback = nil)
|
39
|
+
super(body)
|
40
|
+
|
41
|
+
@digest = digest
|
42
|
+
@callback = callback
|
43
|
+
end
|
44
|
+
|
45
|
+
def digest
|
46
|
+
@digest
|
47
|
+
end
|
48
|
+
|
49
|
+
def etag
|
50
|
+
@digest.hexdigest.dump
|
51
|
+
end
|
52
|
+
|
53
|
+
def read
|
54
|
+
if chunk = super
|
55
|
+
@digest.update(chunk)
|
56
|
+
|
57
|
+
return chunk
|
58
|
+
else
|
59
|
+
@callback&.call(self)
|
60
|
+
|
61
|
+
return nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -33,22 +33,16 @@ module Protocol
|
|
33
33
|
|
34
34
|
@chunks = []
|
35
35
|
@index = 0
|
36
|
-
@digest = nil
|
37
|
-
end
|
38
|
-
|
39
|
-
def digest
|
40
|
-
if @digest.nil?
|
41
|
-
@digest = Digest::SHA256.new
|
42
|
-
@chunks.each{|chunk| @digest.update(chunk)}
|
43
|
-
end
|
44
|
-
|
45
|
-
@digest.hexdigest
|
46
36
|
end
|
47
37
|
|
48
38
|
def empty?
|
49
39
|
(@index >= @chunks.size) && super
|
50
40
|
end
|
51
41
|
|
42
|
+
def ready?
|
43
|
+
(@index < @chunks.size) || super
|
44
|
+
end
|
45
|
+
|
52
46
|
# A rewindable body wraps some other body. Convert it to a buffered body
|
53
47
|
def buffered
|
54
48
|
Buffered.new(@chunks)
|
@@ -61,7 +55,6 @@ module Protocol
|
|
61
55
|
else
|
62
56
|
if chunk = super
|
63
57
|
@chunks << chunk
|
64
|
-
@digest&.update(chunk)
|
65
58
|
@index += 1
|
66
59
|
end
|
67
60
|
end
|
@@ -27,6 +27,12 @@ module Protocol
|
|
27
27
|
module Body
|
28
28
|
# Wrapping body instance. Typically you'd override `#read`.
|
29
29
|
class Wrapper < Readable
|
30
|
+
def self.wrap(message)
|
31
|
+
if body = message.body
|
32
|
+
message.body = self.new(body)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
30
36
|
def initialize(body)
|
31
37
|
@body = body
|
32
38
|
end
|
@@ -49,6 +55,10 @@ module Protocol
|
|
49
55
|
@body.empty?
|
50
56
|
end
|
51
57
|
|
58
|
+
def ready?
|
59
|
+
@body.ready?
|
60
|
+
end
|
61
|
+
|
52
62
|
def length
|
53
63
|
@body.length
|
54
64
|
end
|
data/lib/protocol/http/cookie.rb
CHANGED
@@ -26,21 +26,23 @@ module Protocol
|
|
26
26
|
module HTTP
|
27
27
|
module Header
|
28
28
|
# Used for basic authorization.
|
29
|
-
#
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
def encoded
|
39
|
-
"#{@username}:#{@password}"
|
29
|
+
#
|
30
|
+
# ~~~ ruby
|
31
|
+
# headers.add('authorization', Authorization.basic("my_username", "my_password"))
|
32
|
+
# ~~~
|
33
|
+
class Authorization < String
|
34
|
+
# Splits the header and
|
35
|
+
# @return [Tuple(String, String)]
|
36
|
+
def credentials
|
37
|
+
self.split(/\s+/, 2)
|
40
38
|
end
|
41
39
|
|
42
|
-
def
|
43
|
-
|
40
|
+
def self.basic(username, password)
|
41
|
+
encoded = "#{username}:#{password}"
|
42
|
+
|
43
|
+
self.new(
|
44
|
+
"Basic #{Base64.strict_encode64(encoded)}"
|
45
|
+
)
|
44
46
|
end
|
45
47
|
end
|
46
48
|
end
|
@@ -28,6 +28,7 @@ require_relative 'header/cache_control'
|
|
28
28
|
require_relative 'header/etag'
|
29
29
|
require_relative 'header/etags'
|
30
30
|
require_relative 'header/vary'
|
31
|
+
require_relative 'header/authorization'
|
31
32
|
|
32
33
|
module Protocol
|
33
34
|
module HTTP
|
@@ -35,16 +36,31 @@ module Protocol
|
|
35
36
|
class Headers
|
36
37
|
Split = Header::Split
|
37
38
|
Multiple = Header::Multiple
|
39
|
+
|
38
40
|
TRAILERS = 'trailers'
|
39
41
|
|
40
|
-
# Construct an instance from a headers Array or Hash. No-op if already an instance of `Headers`.
|
42
|
+
# Construct an instance from a headers Array or Hash. No-op if already an instance of `Headers`. If the underlying array is frozen, it will be duped.
|
41
43
|
# @return [Headers] an instance of headers.
|
42
44
|
def self.[] headers
|
45
|
+
if headers.nil?
|
46
|
+
return self.new
|
47
|
+
end
|
48
|
+
|
43
49
|
if headers.is_a?(self)
|
44
|
-
headers
|
45
|
-
|
46
|
-
|
50
|
+
if headers.frozen?
|
51
|
+
return headers.dup
|
52
|
+
else
|
53
|
+
return headers
|
54
|
+
end
|
47
55
|
end
|
56
|
+
|
57
|
+
fields = headers.to_a
|
58
|
+
|
59
|
+
if fields.frozen?
|
60
|
+
fields = fields.dup
|
61
|
+
end
|
62
|
+
|
63
|
+
return self.new(fields)
|
48
64
|
end
|
49
65
|
|
50
66
|
def initialize(fields = [], indexed = nil)
|
@@ -53,7 +69,6 @@ module Protocol
|
|
53
69
|
|
54
70
|
# Marks where trailers start in the @fields array.
|
55
71
|
@tail = nil
|
56
|
-
@deferred = []
|
57
72
|
end
|
58
73
|
|
59
74
|
def initialize_dup(other)
|
@@ -61,47 +76,53 @@ module Protocol
|
|
61
76
|
|
62
77
|
@fields = @fields.dup
|
63
78
|
@indexed = @indexed.dup
|
64
|
-
@deferred = @deferred.dup
|
65
79
|
end
|
66
80
|
|
67
81
|
def clear
|
68
82
|
@fields.clear
|
69
83
|
@indexed = nil
|
70
84
|
@tail = nil
|
71
|
-
@deferred.clear
|
72
85
|
end
|
73
86
|
|
74
|
-
#
|
75
|
-
|
87
|
+
# Flatten trailers into the headers.
|
88
|
+
def flatten!
|
89
|
+
if @tail
|
90
|
+
self.delete(TRAILERS)
|
91
|
+
@tail = nil
|
92
|
+
end
|
93
|
+
|
94
|
+
return self
|
95
|
+
end
|
76
96
|
|
77
|
-
|
78
|
-
|
79
|
-
@tail ||= @fields.size
|
97
|
+
def flatten
|
98
|
+
self.dup.flatten!
|
80
99
|
end
|
81
100
|
|
101
|
+
# An array of `[key, value]` pairs.
|
102
|
+
attr :fields
|
103
|
+
|
82
104
|
# @return the trailers if there are any.
|
83
105
|
def trailers?
|
84
106
|
@tail != nil
|
85
107
|
end
|
86
108
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
109
|
+
# Record the current headers, and prepare to receive trailers.
|
110
|
+
def trailers!(&block)
|
111
|
+
return nil unless self.include?(TRAILERS)
|
112
|
+
|
113
|
+
@tail ||= @fields.size
|
114
|
+
|
115
|
+
return to_enum(:trailers!) unless block_given?
|
116
|
+
|
117
|
+
if @tail
|
118
|
+
@fields.drop(@tail).each(&block)
|
94
119
|
end
|
95
120
|
end
|
96
121
|
|
97
|
-
# Enumerate all trailers,
|
122
|
+
# Enumerate all trailers, if there are any.
|
98
123
|
def trailers(&block)
|
99
|
-
return nil unless self.include?(TRAILERS)
|
100
|
-
|
101
124
|
return to_enum(:trailers) unless block_given?
|
102
125
|
|
103
|
-
flatten!
|
104
|
-
|
105
126
|
if @tail
|
106
127
|
@fields.drop(@tail).each(&block)
|
107
128
|
end
|
@@ -110,18 +131,9 @@ module Protocol
|
|
110
131
|
def freeze
|
111
132
|
return if frozen?
|
112
133
|
|
113
|
-
# Ensure all deferred headers are evaluated:
|
114
|
-
self.flatten!
|
115
|
-
|
116
134
|
# Ensure @indexed is generated:
|
117
135
|
self.to_h
|
118
136
|
|
119
|
-
# Remove all trailers:
|
120
|
-
self.delete(TRAILERS)
|
121
|
-
|
122
|
-
# No longer has stateful trailers:
|
123
|
-
@tail = nil
|
124
|
-
|
125
137
|
@fields.freeze
|
126
138
|
@indexed.freeze
|
127
139
|
|
@@ -159,16 +171,11 @@ module Protocol
|
|
159
171
|
end
|
160
172
|
|
161
173
|
# Add the specified header key value pair.
|
174
|
+
#
|
162
175
|
# @param key [String] the header key.
|
163
176
|
# @param value [String] the header value to assign.
|
164
|
-
|
165
|
-
|
166
|
-
if block_given?
|
167
|
-
@deferred << [key, block]
|
168
|
-
self[TRAILERS] = key
|
169
|
-
else
|
170
|
-
self[key] = value
|
171
|
-
end
|
177
|
+
def add(key, value)
|
178
|
+
self[key] = value
|
172
179
|
end
|
173
180
|
|
174
181
|
# Set the specified header key to the specified value, replacing any existing header keys with the same name.
|
@@ -211,8 +218,6 @@ module Protocol
|
|
211
218
|
'user-agent' => false,
|
212
219
|
'referer' => false,
|
213
220
|
'host' => false,
|
214
|
-
'authorization' => false,
|
215
|
-
'proxy-authorization' => false,
|
216
221
|
'if-modified-since' => false,
|
217
222
|
'if-unmodified-since' => false,
|
218
223
|
'from' => false,
|
@@ -228,6 +233,10 @@ module Protocol
|
|
228
233
|
'via' => Split,
|
229
234
|
'x-forwarded-for' => Split,
|
230
235
|
|
236
|
+
# Authorization headers:
|
237
|
+
'authorization' => Header::Authorization,
|
238
|
+
'proxy-authorization' => Header::Authorization,
|
239
|
+
|
231
240
|
# Cache validations:
|
232
241
|
'etag' => Header::ETag,
|
233
242
|
'if-match' => Header::ETags,
|
@@ -51,9 +51,9 @@ module Protocol
|
|
51
51
|
|
52
52
|
# Use Methods.constants to get all constants.
|
53
53
|
self.each do |name, value|
|
54
|
-
define_method(name.downcase) do |location, headers =
|
54
|
+
define_method(name.downcase) do |location, headers = nil, body = nil|
|
55
55
|
self.call(
|
56
|
-
Request[value, location.
|
56
|
+
Request[value, location.to_s, Headers[headers], body]
|
57
57
|
)
|
58
58
|
end
|
59
59
|
end
|
@@ -28,6 +28,14 @@ require_relative 'response'
|
|
28
28
|
module Protocol
|
29
29
|
module HTTP
|
30
30
|
class Middleware < Methods
|
31
|
+
# Convert a block to a middleware delegate.
|
32
|
+
def self.for(&block)
|
33
|
+
def block.close
|
34
|
+
end
|
35
|
+
|
36
|
+
return self.new(block)
|
37
|
+
end
|
38
|
+
|
31
39
|
def initialize(delegate)
|
32
40
|
@delegate = delegate
|
33
41
|
end
|
@@ -110,12 +110,10 @@ module Protocol
|
|
110
110
|
return buffer
|
111
111
|
end
|
112
112
|
|
113
|
-
def
|
113
|
+
def to_s
|
114
114
|
append(String.new)
|
115
115
|
end
|
116
116
|
|
117
|
-
alias to_s to_str
|
118
|
-
|
119
117
|
# Merges two references as specified by RFC2396, similar to `URI.join`.
|
120
118
|
def + other
|
121
119
|
other = self.class[other]
|
@@ -28,7 +28,7 @@ module Protocol
|
|
28
28
|
class Request
|
29
29
|
prepend Body::Reader
|
30
30
|
|
31
|
-
def initialize(scheme = nil, authority = nil, method = nil, path = nil, version = nil, headers =
|
31
|
+
def initialize(scheme = nil, authority = nil, method = nil, path = nil, version = nil, headers = Headers.new, body = nil, protocol = nil)
|
32
32
|
@scheme = scheme
|
33
33
|
@authority = authority
|
34
34
|
@method = method
|
@@ -48,12 +48,6 @@ module Protocol
|
|
48
48
|
attr_accessor :body
|
49
49
|
attr_accessor :protocol
|
50
50
|
|
51
|
-
def trailers
|
52
|
-
if @headers.respond_to?(:trailers)
|
53
|
-
@headers.trailers
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
51
|
# Send the request to the given connection.
|
58
52
|
def call(connection)
|
59
53
|
connection.call(self)
|
@@ -69,6 +63,7 @@ module Protocol
|
|
69
63
|
|
70
64
|
def self.[](method, path, headers, body)
|
71
65
|
body = Body::Buffered.wrap(body)
|
66
|
+
headers = ::Protocol::HTTP::Headers[headers]
|
72
67
|
|
73
68
|
self.new(nil, nil, method, path, nil, headers, body)
|
74
69
|
end
|
@@ -28,7 +28,7 @@ module Protocol
|
|
28
28
|
class Response
|
29
29
|
prepend Body::Reader
|
30
30
|
|
31
|
-
def initialize(version = nil, status = 200, headers =
|
31
|
+
def initialize(version = nil, status = 200, headers = Headers.new, body = nil, protocol = nil)
|
32
32
|
@version = version
|
33
33
|
@status = status
|
34
34
|
@headers = headers
|
@@ -42,12 +42,6 @@ module Protocol
|
|
42
42
|
attr_accessor :body
|
43
43
|
attr_accessor :protocol
|
44
44
|
|
45
|
-
def trailers
|
46
|
-
if @headers.respond_to?(:trailers)
|
47
|
-
@headers.trailers
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
45
|
def hijack?
|
52
46
|
false
|
53
47
|
end
|
@@ -88,8 +82,9 @@ module Protocol
|
|
88
82
|
@status == 500
|
89
83
|
end
|
90
84
|
|
91
|
-
def self.[](status, headers =
|
85
|
+
def self.[](status, headers = nil, body = nil, protocol = nil)
|
92
86
|
body = Body::Buffered.wrap(body)
|
87
|
+
headers = ::Protocol::HTTP::Headers[headers]
|
93
88
|
|
94
89
|
self.new(nil, status, headers, body, protocol)
|
95
90
|
end
|
data/protocol-http.gemspec
CHANGED
@@ -15,12 +15,11 @@ Gem::Specification.new do |spec|
|
|
15
15
|
f.match(%r{^(test|spec|features)/})
|
16
16
|
end
|
17
17
|
|
18
|
-
spec.required_ruby_version = '
|
18
|
+
spec.required_ruby_version = '>= 2.5'
|
19
19
|
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
22
|
spec.add_development_dependency "covered"
|
23
23
|
spec.add_development_dependency "bundler"
|
24
|
-
spec.add_development_dependency "bake-bundler"
|
25
24
|
spec.add_development_dependency "rspec"
|
26
25
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protocol-http
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.20.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: covered
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: bake-bundler
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: rspec
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,7 +52,7 @@ dependencies:
|
|
66
52
|
- - ">="
|
67
53
|
- !ruby/object:Gem::Version
|
68
54
|
version: '0'
|
69
|
-
description:
|
55
|
+
description:
|
70
56
|
email:
|
71
57
|
- samuel.williams@oriontransfer.co.nz
|
72
58
|
executables: []
|
@@ -74,15 +60,17 @@ extensions: []
|
|
74
60
|
extra_rdoc_files: []
|
75
61
|
files:
|
76
62
|
- ".editorconfig"
|
63
|
+
- ".github/workflows/development.yml"
|
77
64
|
- ".gitignore"
|
78
65
|
- ".rspec"
|
79
|
-
- ".travis.yml"
|
80
|
-
- Gemfile
|
81
66
|
- README.md
|
67
|
+
- bake.rb
|
68
|
+
- gems.rb
|
82
69
|
- lib/protocol/http.rb
|
83
70
|
- lib/protocol/http/accept_encoding.rb
|
84
71
|
- lib/protocol/http/body/buffered.rb
|
85
72
|
- lib/protocol/http/body/deflate.rb
|
73
|
+
- lib/protocol/http/body/digestable.rb
|
86
74
|
- lib/protocol/http/body/file.rb
|
87
75
|
- lib/protocol/http/body/head.rb
|
88
76
|
- lib/protocol/http/body/inflate.rb
|
@@ -118,13 +106,13 @@ homepage: https://github.com/socketry/protocol-http
|
|
118
106
|
licenses:
|
119
107
|
- MIT
|
120
108
|
metadata: {}
|
121
|
-
post_install_message:
|
109
|
+
post_install_message:
|
122
110
|
rdoc_options: []
|
123
111
|
require_paths:
|
124
112
|
- lib
|
125
113
|
required_ruby_version: !ruby/object:Gem::Requirement
|
126
114
|
requirements:
|
127
|
-
- - "
|
115
|
+
- - ">="
|
128
116
|
- !ruby/object:Gem::Version
|
129
117
|
version: '2.5'
|
130
118
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
@@ -133,8 +121,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
133
121
|
- !ruby/object:Gem::Version
|
134
122
|
version: '0'
|
135
123
|
requirements: []
|
136
|
-
rubygems_version: 3.
|
137
|
-
signing_key:
|
124
|
+
rubygems_version: 3.0.3
|
125
|
+
signing_key:
|
138
126
|
specification_version: 4
|
139
127
|
summary: Provides abstractions to handle HTTP protocols.
|
140
128
|
test_files: []
|
data/.travis.yml
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
dist: xenial
|
3
|
-
cache: bundler
|
4
|
-
|
5
|
-
script: bundle exec rspec
|
6
|
-
|
7
|
-
matrix:
|
8
|
-
include:
|
9
|
-
- rvm: 2.5
|
10
|
-
- rvm: 2.6
|
11
|
-
- rvm: 2.7
|
12
|
-
- rvm: 2.6
|
13
|
-
env: COVERAGE=PartialSummary,Coveralls
|
14
|
-
- rvm: 2.7
|
15
|
-
- rvm: truffleruby
|
16
|
-
- rvm: jruby-head
|
17
|
-
env: JRUBY_OPTS="--debug -X+O"
|
18
|
-
- rvm: ruby-head
|
19
|
-
allow_failures:
|
20
|
-
- rvm: truffleruby
|
21
|
-
- rvm: ruby-head
|
22
|
-
- rvm: jruby-head
|