async-http 0.39.0 → 0.40.0

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: 9d2ae06b181bb3fc7bca37de3c13361d9cf06c033f5ca0a4221cd1afb32108f7
4
- data.tar.gz: 2e91385f85f2a2710ea7fa4490b04f01272f7cf525b24581cfe774683eb625a5
3
+ metadata.gz: 9648e5ee0b4e51a48771c3c861cdd9642eaba42a2d55fe9ad6bf47a70f2dc150
4
+ data.tar.gz: 4690e5a313f699de6ac6e774259f21ec889fb3f4540074c3526c92bc1e0ceab8
5
5
  SHA512:
6
- metadata.gz: 0ed6969ab041fd96096c6e445d1fba0774d7de57546c98d1b241a27f46328fae44eb331bff08febb0175457c62f46447070f9eb25afe4c1de84d9786bff99379
7
- data.tar.gz: 80b2ad6e10754ed1eb99d244f838f45fa9f8478273ce740ea922ed1abd4a0180d324fe9c4a968f152bbded8ff6f8483ab0fe8e13d4ddeab5f961070a077f3217
6
+ metadata.gz: 816c05d8d689c21b64f046cff2f7da9460c4b4d9b28205ce23b91ac8fd3053edfced60d9d5838a9f237e89497b004a644267c7f4cfd14a375f08a1195ae15ff9
7
+ data.tar.gz: 9c4ed6fa66a82c2ad4de23249ff5e21ba1a8d24d9d59ccf07b93b640233d2892afe5e3a70ce84e3d5eb04e032b4ef0ec84926c41803ab198dc0b1ec6b3dffe52
data/async-http.gemspec CHANGED
@@ -19,9 +19,9 @@ Gem::Specification.new do |spec|
19
19
  spec.add_dependency("async", "~> 1.14")
20
20
  spec.add_dependency("async-io", "~> 1.18")
21
21
 
22
- spec.add_dependency("protocol-http", "~> 0.1.0")
23
- spec.add_dependency("protocol-http1", "~> 0.1.0")
24
- spec.add_dependency("protocol-http2", "~> 0.1.0")
22
+ spec.add_dependency("protocol-http", "~> 0.3.0")
23
+ spec.add_dependency("protocol-http1", "~> 0.3.0")
24
+ spec.add_dependency("protocol-http2", "~> 0.2.0")
25
25
 
26
26
  # spec.add_dependency("openssl")
27
27
 
@@ -0,0 +1,79 @@
1
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'readable'
22
+ require_relative 'stream'
23
+
24
+ module Async
25
+ module HTTP
26
+ module Body
27
+ # A body which is designed for hijacked connections.
28
+ class Hijack < Readable
29
+ def self.response(request, status, headers, &block)
30
+ Async::HTTP::Response[status, headers, self.wrap(request, &block)]
31
+ end
32
+
33
+ def self.wrap(request, &block)
34
+ self.new(request.body, &block)
35
+ end
36
+
37
+ def initialize(input = nil, &block)
38
+ @input = input
39
+ @block = block
40
+
41
+ @task = nil
42
+ @stream = nil
43
+ end
44
+
45
+ def call(stream)
46
+ return @block.call(stream)
47
+ ensure
48
+ @block = nil
49
+ end
50
+
51
+ # Has the producer called #finish and has the reader consumed the nil token?
52
+ def empty?
53
+ @block.nil?
54
+ end
55
+
56
+ # Read the next available chunk.
57
+ def read
58
+ return unless @block
59
+
60
+ unless @task
61
+ @stream = Stream.new(@input)
62
+
63
+ @task = Task.current.async do
64
+ @block.call(@stream)
65
+ end
66
+
67
+ @block = nil
68
+ end
69
+
70
+ return @stream.output.read
71
+ end
72
+
73
+ def inspect
74
+ "\#<#{self.class} #{@block}>"
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,131 @@
1
+ # Copyright, 2019, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'writable'
22
+
23
+ module Async
24
+ module HTTP
25
+ module Body
26
+ # The input stream is an IO-like object which contains the raw HTTP POST data. When applicable, its external encoding must be “ASCII-8BIT” and it must be opened in binary mode, for Ruby 1.9 compatibility. The input stream must respond to gets, each, read and rewind.
27
+ class Stream
28
+ def initialize(input, output = Writable.new)
29
+ @input = input
30
+ @output = output
31
+
32
+ # Will hold remaining data in `#read`.
33
+ @buffer = nil
34
+ end
35
+
36
+ attr :input
37
+ attr :output
38
+
39
+ # rack.hijack_io must respond to:
40
+ # read, write, read_nonblock, write_nonblock, flush, close, close_read, close_write, closed?
41
+
42
+ # read behaves like IO#read. Its signature is read([length, [buffer]]). If given, length must be a non-negative Integer (>= 0) or nil, and buffer must be a String and may not be nil. If length is given and not nil, then this method reads at most length bytes from the input stream. If length is not given or nil, then this method reads all data until EOF. When EOF is reached, this method returns nil if length is given and not nil, or “” if length is not given or is nil. If buffer is given, then the read data will be placed into buffer instead of a newly created String object.
43
+ # @param length [Integer] the amount of data to read
44
+ # @param buffer [String] the buffer which will receive the data
45
+ # @return a buffer containing the data
46
+ def read(length = nil, buffer = nil)
47
+ buffer ||= Async::IO::Buffer.new
48
+ buffer.clear
49
+
50
+ until buffer.bytesize == length
51
+ @buffer = read_next if @buffer.nil?
52
+ break if @buffer.nil?
53
+
54
+ remaining_length = length - buffer.bytesize if length
55
+
56
+ if remaining_length && remaining_length < @buffer.bytesize
57
+ # We know that we are not going to reuse the original buffer.
58
+ # But byteslice will generate a hidden copy. So let's freeze it first:
59
+ @buffer.freeze
60
+
61
+ buffer << @buffer.byteslice(0, remaining_length)
62
+ @buffer = @buffer.byteslice(remaining_length, @buffer.bytesize)
63
+ else
64
+ buffer << @buffer
65
+ @buffer = nil
66
+ end
67
+ end
68
+
69
+ return nil if buffer.empty? && length && length > 0
70
+
71
+ return buffer
72
+ end
73
+
74
+ def read_nonblock(length, buffer = nil)
75
+ @buffer ||= read_next
76
+ chunk = nil
77
+
78
+ if @buffer.bytesize > length
79
+ chunk = @buffer.byteslice(0, length)
80
+ @buffer = @buffer.byteslice(length, @buffer.bytesize)
81
+ else
82
+ chunk = @buffer
83
+ @buffer = nil
84
+ end
85
+
86
+ if buffer
87
+ buffer.replace(chunk)
88
+ else
89
+ buffer = chunk
90
+ end
91
+
92
+ return buffer
93
+ end
94
+
95
+ def write(buffer)
96
+ @output.write(buffer)
97
+ end
98
+
99
+ alias write_nonblock write
100
+
101
+ def flush
102
+ end
103
+
104
+ def close_read
105
+ @input&.close
106
+ end
107
+
108
+ # close must never be called on the input stream. huh?
109
+ def close_write
110
+ @output&.close
111
+ end
112
+
113
+ def close
114
+ self.close_read
115
+ self.close_write
116
+ end
117
+
118
+ private
119
+
120
+ def read_next
121
+ if chunk = @input&.read
122
+ return chunk
123
+ else
124
+ @input = nil
125
+ return nil
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -61,6 +61,10 @@ module Async
61
61
  super
62
62
  end
63
63
 
64
+ def closed?
65
+ @closed
66
+ end
67
+
64
68
  # Has the producer called #finish and has the reader consumed the nil token?
65
69
  def empty?
66
70
  @finished
@@ -57,14 +57,22 @@ module Async
57
57
  return if @stream.closed?
58
58
 
59
59
  if response
60
- write_response(@version, response.status, response.headers, response.body, request.head?)
60
+ # Try to avoid holding on to request, to minimse GC overhead:
61
+ head = request.head?
62
+
63
+ unless request.body?
64
+ # If there is no body, #finish is a no-op.
65
+ request = nil
66
+ end
67
+
68
+ write_response(@version, response.status, response.headers, response.body, head)
61
69
  else
62
70
  # If the request failed to generate a response, it was an internal server error:
63
71
  write_response(@version, 500, {}, nil)
64
72
  end
65
73
 
66
74
  # Gracefully finish reading the request body if it was not already done so.
67
- request.finish
75
+ request&.finish
68
76
 
69
77
  # This ensures we yield at least once every iteration of the loop and allow other fibers to execute.
70
78
  task.yield
@@ -20,6 +20,6 @@
20
20
 
21
21
  module Async
22
22
  module HTTP
23
- VERSION = "0.39.0"
23
+ VERSION = "0.40.0"
24
24
  end
25
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-http
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.39.0
4
+ version: 0.40.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-08 00:00:00.000000000 Z
11
+ date: 2019-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -44,42 +44,42 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 0.1.0
47
+ version: 0.3.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 0.1.0
54
+ version: 0.3.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: protocol-http1
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.1.0
61
+ version: 0.3.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.1.0
68
+ version: 0.3.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: protocol-http2
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 0.1.0
75
+ version: 0.2.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 0.1.0
82
+ version: 0.2.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: async-rspec
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -187,11 +187,13 @@ files:
187
187
  - lib/async/http/body/delayed.rb
188
188
  - lib/async/http/body/file.rb
189
189
  - lib/async/http/body/fixed.rb
190
+ - lib/async/http/body/hijack.rb
190
191
  - lib/async/http/body/inflate.rb
191
192
  - lib/async/http/body/readable.rb
192
193
  - lib/async/http/body/reader.rb
193
194
  - lib/async/http/body/rewindable.rb
194
195
  - lib/async/http/body/slowloris.rb
196
+ - lib/async/http/body/stream.rb
195
197
  - lib/async/http/body/streamable.rb
196
198
  - lib/async/http/body/wrapper.rb
197
199
  - lib/async/http/body/writable.rb