protocol-http 0.21.0 → 0.22.4

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: 01dc23ef2870a6572cc986fd3dac2de5902ec3283fb5a380d9f24b1193516d68
4
- data.tar.gz: ca6bf9694e01884a6d2c2e9ab5e85c54d64c4f150881cf57fb2ba1ed80fa0b9c
3
+ metadata.gz: a5ce664c282254446c2a0630171f738e1f2649f79610357c6516278bb1daa8b8
4
+ data.tar.gz: 6e279c9da31e55d441e2bdc95bd1802ac89688e03d80a6f7a6bfe1d6b3b505ee
5
5
  SHA512:
6
- metadata.gz: d71145aa0b55861140b181c2351501cd9eec840b747abd4d5d48841a4e8d2df0bb5d2e5fa0c0c83be98a51775e92160cd52690806c5b1443808f7d6386cdc568
7
- data.tar.gz: f2f603776458e27ed0b2148fce7c9f9ac419417c001e2ea42270248df651c34f524b6646926847a8aa93139509b8bd72d86c875a3b341e9c16eb0a124ecfd6a5
6
+ metadata.gz: febde12794a4c38af66b3578af6ffeb5ffdbf8bf606b9c7c413e6b4f4e2cd65452100fbe8ec33794be2f5cb044c4db1bb151763ff7a3f30bda7b9e766ee3738d
7
+ data.tar.gz: 96ce0f77a34495f5ee10c4b00099db58be7fbaceaef65249ed5e3abaa931cc7f7bb6df048a901923fc7113624fb7bd21becae6263e28ee3000cc617fc662b3ae
@@ -32,6 +32,10 @@ module Protocol
32
32
  @directives = directives
33
33
  end
34
34
 
35
+ attr :name
36
+ attr :value
37
+ attr :directives
38
+
35
39
  def encoded_name
36
40
  URL.escape(@name)
37
41
  end
@@ -61,11 +65,11 @@ module Protocol
61
65
  return buffer
62
66
  end
63
67
 
64
- def self.parse string
65
- head, *options = string.split(/\s*;\s*/)
68
+ def self.parse(string)
69
+ head, *directives = string.split(/\s*;\s*/)
66
70
 
67
71
  key, value = head.split('=')
68
- directives.collect{|directive| directive.split('=', 2)}.to_h
72
+ directives = self.parse_directives(directives)
69
73
 
70
74
  self.new(
71
75
  URI.decode(key),
@@ -73,6 +77,13 @@ module Protocol
73
77
  directives,
74
78
  )
75
79
  end
80
+
81
+ def self.parse_directives(strings)
82
+ strings.collect do |string|
83
+ key, value = string.split('=', 2)
84
+ [key, value || true]
85
+ end.to_h
86
+ end
76
87
  end
77
88
  end
78
89
  end
@@ -21,6 +21,7 @@
21
21
  # THE SOFTWARE.
22
22
 
23
23
  require_relative 'multiple'
24
+ require_relative '../cookie'
24
25
 
25
26
  module Protocol
26
27
  module HTTP
@@ -37,7 +37,7 @@ module Protocol
37
37
  Split = Header::Split
38
38
  Multiple = Header::Multiple
39
39
 
40
- TRAILERS = 'trailers'
40
+ TRAILER = 'trailer'
41
41
 
42
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.
43
43
  # @return [Headers] an instance of headers.
@@ -67,7 +67,7 @@ module Protocol
67
67
  @fields = fields
68
68
  @indexed = indexed
69
69
 
70
- # Marks where trailers start in the @fields array.
70
+ # Marks where trailer start in the @fields array.
71
71
  @tail = nil
72
72
  end
73
73
 
@@ -84,10 +84,10 @@ module Protocol
84
84
  @tail = nil
85
85
  end
86
86
 
87
- # Flatten trailers into the headers.
87
+ # Flatten trailer into the headers.
88
88
  def flatten!
89
89
  if @tail
90
- self.delete(TRAILERS)
90
+ self.delete(TRAILER)
91
91
  @tail = nil
92
92
  end
93
93
 
@@ -101,27 +101,27 @@ module Protocol
101
101
  # An array of `[key, value]` pairs.
102
102
  attr :fields
103
103
 
104
- # @return the trailers if there are any.
105
- def trailers?
104
+ # @return the trailer if there are any.
105
+ def trailer?
106
106
  @tail != nil
107
107
  end
108
108
 
109
- # Record the current headers, and prepare to receive trailers.
110
- def trailers!(&block)
111
- return nil unless self.include?(TRAILERS)
109
+ # Record the current headers, and prepare to receive trailer.
110
+ def trailer!(&block)
111
+ return nil unless self.include?(TRAILER)
112
112
 
113
113
  @tail ||= @fields.size
114
114
 
115
- return to_enum(:trailers!) unless block_given?
115
+ return to_enum(:trailer!) unless block_given?
116
116
 
117
117
  if @tail
118
118
  @fields.drop(@tail).each(&block)
119
119
  end
120
120
  end
121
121
 
122
- # Enumerate all trailers, if there are any.
123
- def trailers(&block)
124
- return to_enum(:trailers) unless block_given?
122
+ # Enumerate all headers in the trailer, if there are any.
123
+ def trailer(&block)
124
+ return to_enum(:trailer) unless block_given?
125
125
 
126
126
  if @tail
127
127
  @fields.drop(@tail).each(&block)
@@ -35,17 +35,17 @@ module Protocol
35
35
  end
36
36
 
37
37
  class Builder
38
- def initialize(default_app = NotFound, &block)
38
+ def initialize(default_app = NotFound)
39
39
  @use = []
40
40
  @app = default_app
41
-
42
- instance_eval(&block) if block_given?
43
41
  end
44
42
 
45
- def use(middleware, *args, &block)
46
- @use << proc {|app| middleware.new(app, *args, &block)}
43
+ def use(middleware, *arguments, &block)
44
+ @use << proc {|app| middleware.new(app, *arguments, &block)}
47
45
  end
48
46
 
47
+ ruby2_keywords(:use) if respond_to?(:ruby2_keywords, true)
48
+
49
49
  def run(app)
50
50
  @app = app
51
51
  end
@@ -56,7 +56,11 @@ module Protocol
56
56
  end
57
57
 
58
58
  def self.build(&block)
59
- Builder.new(&block).to_app
59
+ builder = Builder.new
60
+
61
+ builder.instance_eval(&block)
62
+
63
+ return builder.to_app
60
64
  end
61
65
  end
62
66
  end
@@ -22,6 +22,6 @@
22
22
 
23
23
  module Protocol
24
24
  module HTTP
25
- VERSION = "0.21.0"
25
+ VERSION = "0.22.4"
26
26
  end
27
27
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protocol-http
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.0
4
+ version: 0.22.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-14 00:00:00.000000000 Z
11
+ date: 2021-06-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: covered
14
+ name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: bundler
28
+ name: covered
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -54,19 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  description:
56
56
  email:
57
- - samuel.williams@oriontransfer.co.nz
58
57
  executables: []
59
58
  extensions: []
60
59
  extra_rdoc_files: []
61
60
  files:
62
- - ".editorconfig"
63
- - ".github/workflows/development.yml"
64
- - ".gitignore"
65
- - ".rspec"
66
- - README.md
67
- - STREAMING.md
68
- - bake.rb
69
- - gems.rb
70
61
  - lib/protocol/http.rb
71
62
  - lib/protocol/http/accept_encoding.rb
72
63
  - lib/protocol/http/body/buffered.rb
@@ -102,7 +93,6 @@ files:
102
93
  - lib/protocol/http/response.rb
103
94
  - lib/protocol/http/url.rb
104
95
  - lib/protocol/http/version.rb
105
- - protocol-http.gemspec
106
96
  homepage: https://github.com/socketry/protocol-http
107
97
  licenses:
108
98
  - MIT
@@ -122,7 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
112
  - !ruby/object:Gem::Version
123
113
  version: '0'
124
114
  requirements: []
125
- rubygems_version: 3.1.2
115
+ rubygems_version: 3.1.6
126
116
  signing_key:
127
117
  specification_version: 4
128
118
  summary: Provides abstractions to handle HTTP protocols.
data/.editorconfig DELETED
@@ -1,5 +0,0 @@
1
- root = true
2
-
3
- [*]
4
- indent_style = tab
5
- indent_size = 2
@@ -1,44 +0,0 @@
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 DELETED
@@ -1,14 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
- /external/
10
-
11
- # rspec failure tracking
12
- .rspec_status
13
- /gems.locked
14
- .covered.db
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --warnings
3
- --require spec_helper
data/README.md DELETED
@@ -1,90 +0,0 @@
1
- # Protocol::HTTP
2
-
3
- Provides abstractions for working with the HTTP protocol.
4
-
5
- [![Development Status](https://github.com/socketry/protocol-http/workflows/Development/badge.svg)](https://github.com/socketry/protocol-http/actions?workflow=Development)
6
-
7
- ## Installation
8
-
9
- Add this line to your application's Gemfile:
10
-
11
- ``` ruby
12
- gem 'protocol-http'
13
- ```
14
-
15
- And then execute:
16
-
17
- $ bundle
18
-
19
- Or install it yourself as:
20
-
21
- $ gem install protocol-http
22
-
23
- ## Usage
24
-
25
- ### Headers
26
-
27
- ``` ruby
28
- require 'protocol/http/headers'
29
-
30
- headers = Protocol::HTTP::Headers.new
31
-
32
- headers['Content-Type'] = "image/jpeg"
33
-
34
- headers['content-type']
35
- # => "image/jpeg"
36
- ```
37
-
38
- ### Reference
39
-
40
- ``` ruby
41
- require 'protocol/http/reference'
42
-
43
- reference = Protocol::HTTP::Reference.new("/search", q: 'kittens')
44
-
45
- reference.to_s
46
- # => "/search?q=kittens"
47
- ```
48
-
49
- ### URL
50
-
51
- ``` ruby
52
- require 'protocol/http/url'
53
-
54
- reference = Protocol::HTTP::Reference.parse("/search?q=kittens")
55
-
56
- parameters = Protocol::HTTP::URL.decode(reference.query_string)
57
- # => {"q"=>"kittens"}
58
- ```
59
-
60
- ## Contributing
61
-
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
-
68
- ## License
69
-
70
- Released under the MIT license.
71
-
72
- Copyright, 2019, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
73
-
74
- Permission is hereby granted, free of charge, to any person obtaining a copy
75
- of this software and associated documentation files (the "Software"), to deal
76
- in the Software without restriction, including without limitation the rights
77
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
78
- copies of the Software, and to permit persons to whom the Software is
79
- furnished to do so, subject to the following conditions:
80
-
81
- The above copyright notice and this permission notice shall be included in
82
- all copies or substantial portions of the Software.
83
-
84
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
85
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
86
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
87
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
88
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
89
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
90
- THE SOFTWARE.
data/STREAMING.md DELETED
@@ -1,69 +0,0 @@
1
- # Streaming
2
-
3
- Streaming is a complex topic given that most server's are not scalable in this respect. A variety of solutions exist to work around limited server implementations, but they impose significant burden on the implementation and are generally incompatible with implementations of HTTP which are not request per connection. We propose to simplify the current Rack implementation to support streaming in a consistent way, but also allow for backwards compatibility with existing servers.
4
-
5
- ## Current Implementation
6
-
7
- Rack currently supports streaming using `rack.hijack`. There are two ways to hijack the underlying socket for a given request: a partial hijack and a full hijack. Not all servers support both modes of operation and neither method is fully compatible with HTTP/2.
8
-
9
- ### Partial Hijack
10
-
11
- A partial hijack allows the web server to respond with the response status, headers, and then yields the stream back to the application code. It does this by using a special `rack.hijack` header:
12
-
13
- ``` ruby
14
- def call(env)
15
- body = proc do |stream|
16
- stream.write("Hello World")
17
- stream.close
18
- end
19
-
20
- if env['rack.hijack?']
21
- return [200, {'rack.hijack' => body}, nil]
22
- end
23
- end
24
- ```
25
-
26
- - It is not clear whether the body needs to handle the formatting of the response, i.e. chunked encoding, compression, transfer encoding, etc.
27
- - It mixes `rack.` specific headers with normal HTTP headers which is computationally expensive for the server to detect.
28
- - It's not clear what the returned body should be.
29
-
30
- ### Full Hijack
31
-
32
- A full hijack allows the web server to completely take control of the underlying socket. This occurs at the point the `rack.hijack` is invoked.
33
-
34
- ``` ruby
35
- def call(env)
36
- if hijack = env['rack.hijack']
37
- socket = hijack.call
38
-
39
- Thread.new do
40
- socket.write("Hello World")
41
- socket.close
42
- end
43
-
44
- return nil # ???
45
- end
46
- end
47
- ```
48
-
49
- - The socket might not actually be a raw socket, if the server is using TLS.
50
- - Extreme care is required in order to handle the protocol correctly.
51
- - It's not clear if such a design can work with anything other than HTTP/1.
52
- - The user code **must** return from the `call(env)` method in order for the server continue handling requests.
53
- - It's not clear what the response should be.
54
-
55
- ## Typical Scenarios
56
-
57
- There are several typical scenarios where `rack.hijack` has been used.
58
-
59
- ### ActionCable
60
-
61
- ActionCable uses full hijack in order to negotiate and communicate using WebSocket protocol. Such a design requires the ActionCable server to run in the same process as the web server.
62
-
63
- ### MessageBus
64
-
65
- MessageBus uses full hijack in order to keep the socket alive and feed messages occasionally.
66
-
67
- ## Supporting HTTP/2
68
-
69
- It is possible to support partial hijack in HTTP/2. The hijacked stream is multiplexed the same as any other connection. However, such a design cannot be thread safe without significant design trade-offs.
data/bake.rb DELETED
@@ -1,37 +0,0 @@
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/gems.rb DELETED
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source "https://rubygems.org"
4
-
5
- # Specify your gem's dependencies in protocol-http.gemspec
6
- gemspec
7
-
8
- group :maintenance, optional: true do
9
- gem "bake-modernize"
10
- gem "bake-bundler"
11
- end
12
-
13
- group :test do
14
- gem 'async-io'
15
- gem 'async-rspec'
16
- end
@@ -1,25 +0,0 @@
1
-
2
- require_relative "lib/protocol/http/version"
3
-
4
- Gem::Specification.new do |spec|
5
- spec.name = "protocol-http"
6
- spec.version = Protocol::HTTP::VERSION
7
- spec.authors = ["Samuel Williams"]
8
- spec.email = ["samuel.williams@oriontransfer.co.nz"]
9
-
10
- spec.summary = "Provides abstractions to handle HTTP protocols."
11
- spec.homepage = "https://github.com/socketry/protocol-http"
12
- spec.license = "MIT"
13
-
14
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
15
- f.match(%r{^(test|spec|features)/})
16
- end
17
-
18
- spec.required_ruby_version = '>= 2.5'
19
-
20
- spec.require_paths = ["lib"]
21
-
22
- spec.add_development_dependency "covered"
23
- spec.add_development_dependency "bundler"
24
- spec.add_development_dependency "rspec"
25
- end