async-http 0.31.1 → 0.32.0
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/lib/async/http/body.rb +17 -0
- data/lib/async/http/body/buffered.rb +4 -4
- data/lib/async/http/body/chunked.rb +8 -3
- data/lib/async/http/body/deflate.rb +6 -7
- data/lib/async/http/body/file.rb +7 -7
- data/lib/async/http/body/fixed.rb +6 -2
- data/lib/async/http/body/readable.rb +14 -12
- data/lib/async/http/body/reader.rb +7 -12
- data/lib/async/http/body/rewindable.rb +1 -1
- data/lib/async/http/body/streamable.rb +1 -1
- data/lib/async/http/body/wrapper.rb +14 -11
- data/lib/async/http/body/writable.rb +20 -18
- data/lib/async/http/protocol/http2/request.rb +1 -1
- data/lib/async/http/protocol/http2/response.rb +2 -2
- data/lib/async/http/protocol/http2/stream.rb +5 -2
- data/lib/async/http/statistics.rb +1 -1
- data/lib/async/http/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a35d727fb4d1811ad0ddea60170aef62f60084759c1c2d0f658e335f3496be4d
|
4
|
+
data.tar.gz: 58004aea432052f2979346a359ad55f2d098f9fa1d9f03e4f89bd08474ced951
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cee0898153224018a6d9a6b04b5da0635895c59aeb3f37fe5ee3fa20260529a887ee73398afa34ec98ab443a5699d0506bf40fab54123705c1f336ff7e381d72
|
7
|
+
data.tar.gz: fb39c47f2edb32732b16d8a8ac3cd8158f6f78212d4dae6af2201eedc24b6bdf30085a1670b4040fb23f384b51efdf9fcaa4b09994a25c86004da9672a4104e2
|
data/lib/async/http/body.rb
CHANGED
@@ -20,3 +20,20 @@
|
|
20
20
|
|
21
21
|
require_relative 'body/writable'
|
22
22
|
require_relative 'body/buffered'
|
23
|
+
|
24
|
+
module Async
|
25
|
+
module HTTP
|
26
|
+
# These classes implement a general IO model for streaming HTTP bodies.
|
27
|
+
module Body
|
28
|
+
# The implementation assumes a sequential unbuffered stream of data.
|
29
|
+
# class Body
|
30
|
+
# def each -> yield(String | nil)
|
31
|
+
# def read -> String | nil
|
32
|
+
# def join -> String
|
33
|
+
|
34
|
+
# def finish -> buffer the stream and close it.
|
35
|
+
# def close(error = nil) -> close the stream immediately.
|
36
|
+
# end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -54,6 +54,10 @@ module Async
|
|
54
54
|
@index = 0
|
55
55
|
end
|
56
56
|
|
57
|
+
def finish
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
57
61
|
def length
|
58
62
|
@length ||= @chunks.inject(0) {|sum, chunk| sum + chunk.bytesize}
|
59
63
|
end
|
@@ -62,10 +66,6 @@ module Async
|
|
62
66
|
@index >= @chunks.length
|
63
67
|
end
|
64
68
|
|
65
|
-
def close
|
66
|
-
self
|
67
|
-
end
|
68
|
-
|
69
69
|
def read
|
70
70
|
if chunk = @chunks[@index]
|
71
71
|
@index += 1
|
@@ -36,9 +36,14 @@ module Async
|
|
36
36
|
@finished
|
37
37
|
end
|
38
38
|
|
39
|
-
def
|
40
|
-
|
41
|
-
@finished
|
39
|
+
def close(error = nil)
|
40
|
+
# We only close the connection if we haven't completed reading the entire body:
|
41
|
+
unless @finished
|
42
|
+
@protocol.close
|
43
|
+
@finished = true
|
44
|
+
end
|
45
|
+
|
46
|
+
super
|
42
47
|
end
|
43
48
|
|
44
49
|
def read
|
@@ -55,6 +55,12 @@ module Async
|
|
55
55
|
@output_length = 0
|
56
56
|
end
|
57
57
|
|
58
|
+
def close(error = nil)
|
59
|
+
@stream.close unless @stream.closed?
|
60
|
+
|
61
|
+
super
|
62
|
+
end
|
63
|
+
|
58
64
|
def length
|
59
65
|
# We don't know the length of the output until after it's been compressed.
|
60
66
|
nil
|
@@ -71,13 +77,6 @@ module Async
|
|
71
77
|
end
|
72
78
|
end
|
73
79
|
|
74
|
-
def stop(error)
|
75
|
-
# There are two ways for the stream to be closed. Either #read returns nil or #stop is called.
|
76
|
-
@stream.close unless @stream.closed?
|
77
|
-
|
78
|
-
super
|
79
|
-
end
|
80
|
-
|
81
80
|
def inspect
|
82
81
|
"#{super} | \#<#{self.class} #{(ratio*100).round(2)}%>"
|
83
82
|
end
|
data/lib/async/http/body/file.rb
CHANGED
@@ -46,6 +46,13 @@ module Async
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
+
def close(error = nil)
|
50
|
+
@file.close
|
51
|
+
@remaining = 0
|
52
|
+
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
49
56
|
attr :offset
|
50
57
|
attr :length
|
51
58
|
|
@@ -57,11 +64,6 @@ module Async
|
|
57
64
|
@file.seek(@offset)
|
58
65
|
end
|
59
66
|
|
60
|
-
def close
|
61
|
-
@file.close
|
62
|
-
@remaining = 0
|
63
|
-
end
|
64
|
-
|
65
67
|
def read
|
66
68
|
if @remaining > 0
|
67
69
|
amount = [@remaining, @block_size].min
|
@@ -70,8 +72,6 @@ module Async
|
|
70
72
|
@remaining -= chunk.bytesize
|
71
73
|
|
72
74
|
return chunk
|
73
|
-
else
|
74
|
-
@file.close
|
75
75
|
end
|
76
76
|
end
|
77
77
|
end
|
@@ -37,10 +37,12 @@ module Async
|
|
37
37
|
@remaining == 0
|
38
38
|
end
|
39
39
|
|
40
|
-
def
|
40
|
+
def close(error = nil)
|
41
41
|
if @remaining != 0
|
42
42
|
@stream.close
|
43
43
|
end
|
44
|
+
|
45
|
+
super
|
44
46
|
end
|
45
47
|
|
46
48
|
def read
|
@@ -75,9 +77,11 @@ module Async
|
|
75
77
|
@stream.closed?
|
76
78
|
end
|
77
79
|
|
78
|
-
def
|
80
|
+
def close(error = nil)
|
79
81
|
# We can't really do anything in this case except close the connection.
|
80
82
|
@stream.close
|
83
|
+
|
84
|
+
super
|
81
85
|
end
|
82
86
|
|
83
87
|
def read
|
@@ -25,9 +25,17 @@ module Async
|
|
25
25
|
module Body
|
26
26
|
# A generic base class for wrapping body instances. Typically you'd override `#read`.
|
27
27
|
class Readable
|
28
|
-
# Read all remaining chunks into a buffered body.
|
29
|
-
def
|
30
|
-
Buffered.for(self)
|
28
|
+
# Read all remaining chunks into a buffered body and close the underlying input.
|
29
|
+
def finish
|
30
|
+
buffered = Buffered.for(self)
|
31
|
+
|
32
|
+
self.close
|
33
|
+
|
34
|
+
return buffered
|
35
|
+
end
|
36
|
+
|
37
|
+
# The consumer can call stop to signal that the stream output has terminated.
|
38
|
+
def close(error = nil)
|
31
39
|
end
|
32
40
|
|
33
41
|
# Will read return any data?
|
@@ -44,11 +52,7 @@ module Async
|
|
44
52
|
nil
|
45
53
|
end
|
46
54
|
|
47
|
-
#
|
48
|
-
def stop(error)
|
49
|
-
end
|
50
|
-
|
51
|
-
# Enumerate all chunks until finished. If an error is thrown, #stop will be invoked.
|
55
|
+
# Enumerate all chunks until finished. Then invoke `#close`.
|
52
56
|
def each
|
53
57
|
return to_enum unless block_given?
|
54
58
|
|
@@ -56,10 +60,8 @@ module Async
|
|
56
60
|
yield chunk
|
57
61
|
# chunk.clear
|
58
62
|
end
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
raise
|
63
|
+
ensure
|
64
|
+
self.close($!)
|
63
65
|
end
|
64
66
|
|
65
67
|
# Read all remaining chunks into a single binary string.
|
@@ -34,24 +34,19 @@ module Async
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
# Immediately stop reading the body. May close the underlying connection. Discards body.
|
38
|
-
def stop(error = EOFError)
|
39
|
-
if self.body
|
40
|
-
self.body.stop(error)
|
41
|
-
self.body = nil
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
37
|
# Gracefully finish reading the body. This will buffer the remainder of the body.
|
46
38
|
def finish
|
47
39
|
if self.body
|
48
|
-
self.body = self.body.
|
40
|
+
self.body = self.body.finish
|
49
41
|
end
|
50
42
|
end
|
51
43
|
|
52
|
-
# Close the connection as quickly as possible. Discards body.
|
53
|
-
def close
|
54
|
-
self.
|
44
|
+
# Close the connection as quickly as possible. Discards body. May close the underlying connection if necessary to terminate the stream.
|
45
|
+
def close(error = nil)
|
46
|
+
if self.body
|
47
|
+
self.body.close(error)
|
48
|
+
self.body = nil
|
49
|
+
end
|
55
50
|
end
|
56
51
|
|
57
52
|
# Whether there is a body?
|
@@ -29,6 +29,20 @@ module Async
|
|
29
29
|
@body = body
|
30
30
|
end
|
31
31
|
|
32
|
+
# The wrapped body.
|
33
|
+
attr :body
|
34
|
+
|
35
|
+
# Buffer any remaining body.
|
36
|
+
def finish
|
37
|
+
@body.finish
|
38
|
+
end
|
39
|
+
|
40
|
+
def close(error = nil)
|
41
|
+
@body.close(error)
|
42
|
+
|
43
|
+
super
|
44
|
+
end
|
45
|
+
|
32
46
|
def empty?
|
33
47
|
@body.empty?
|
34
48
|
end
|
@@ -37,22 +51,11 @@ module Async
|
|
37
51
|
@body.length
|
38
52
|
end
|
39
53
|
|
40
|
-
# Buffer any remaining body.
|
41
|
-
def close
|
42
|
-
@body = @body.close
|
43
|
-
|
44
|
-
return self
|
45
|
-
end
|
46
|
-
|
47
54
|
# Read the next available chunk.
|
48
55
|
def read
|
49
56
|
@body.read
|
50
57
|
end
|
51
58
|
|
52
|
-
def stop(error)
|
53
|
-
@body.stop(error)
|
54
|
-
end
|
55
|
-
|
56
59
|
def inspect
|
57
60
|
return @body.inspect
|
58
61
|
end
|
@@ -27,13 +27,30 @@ module Async
|
|
27
27
|
module Body
|
28
28
|
# A dynamic body which you can write to and read from.
|
29
29
|
class Writable < Readable
|
30
|
+
class Closed < StandardError
|
31
|
+
end
|
32
|
+
|
30
33
|
def initialize
|
31
34
|
@queue = Async::Queue.new
|
32
35
|
|
33
36
|
@count = 0
|
34
37
|
|
35
38
|
@finished = false
|
36
|
-
|
39
|
+
|
40
|
+
@closed = false
|
41
|
+
@error = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
# Stop generating output; cause the next call to write to fail with the given error.
|
45
|
+
def close(error = nil)
|
46
|
+
unless @closed
|
47
|
+
@queue.enqueue(nil)
|
48
|
+
|
49
|
+
@closed = true
|
50
|
+
@error = error
|
51
|
+
end
|
52
|
+
|
53
|
+
super
|
37
54
|
end
|
38
55
|
|
39
56
|
# Has the producer called #finish and has the reader consumed the nil token?
|
@@ -43,11 +60,6 @@ module Async
|
|
43
60
|
|
44
61
|
# Read the next available chunk.
|
45
62
|
def read
|
46
|
-
# I'm not sure if this is a good idea.
|
47
|
-
# if @stopped
|
48
|
-
# raise @stopped
|
49
|
-
# end
|
50
|
-
|
51
63
|
return if @finished
|
52
64
|
|
53
65
|
unless chunk = @queue.dequeue
|
@@ -57,17 +69,12 @@ module Async
|
|
57
69
|
return chunk
|
58
70
|
end
|
59
71
|
|
60
|
-
# Stop generating output; cause the next call to write to fail with the given error.
|
61
|
-
def stop(error)
|
62
|
-
@stopped ||= error
|
63
|
-
end
|
64
|
-
|
65
72
|
# Write a single chunk to the body. Signal completion by calling `#finish`.
|
66
73
|
def write(chunk)
|
67
74
|
# If the reader breaks, the writer will break.
|
68
75
|
# The inverse of this is less obvious (*)
|
69
|
-
if @
|
70
|
-
raise
|
76
|
+
if @closed
|
77
|
+
raise(@error || Closed)
|
71
78
|
end
|
72
79
|
|
73
80
|
# TODO should this yield if the queue is full?
|
@@ -78,11 +85,6 @@ module Async
|
|
78
85
|
|
79
86
|
alias << write
|
80
87
|
|
81
|
-
# Signal that output has finished. This must be called at least once.
|
82
|
-
def finish
|
83
|
-
@queue.enqueue(nil)
|
84
|
-
end
|
85
|
-
|
86
88
|
def inspect
|
87
89
|
"\#<#{self.class} #{@count} chunks written#{@finished ? ', finished' : ''}>"
|
88
90
|
end
|
@@ -56,7 +56,10 @@ module Async
|
|
56
56
|
elsif chunk = @body.read
|
57
57
|
# There was a new chunk of data to send
|
58
58
|
else
|
59
|
-
@body
|
59
|
+
if @body
|
60
|
+
@body.close
|
61
|
+
@body = nil
|
62
|
+
end
|
60
63
|
|
61
64
|
# @body.read above might take a while and a stream reset might be received in the mean time.
|
62
65
|
unless closed?
|
@@ -109,7 +112,7 @@ module Async
|
|
109
112
|
error_code = super
|
110
113
|
|
111
114
|
if @body
|
112
|
-
@body.
|
115
|
+
@body.close(EOFError.new(error_code))
|
113
116
|
@body = nil
|
114
117
|
end
|
115
118
|
|
data/lib/async/http/version.rb
CHANGED
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.
|
4
|
+
version: 0.32.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: 2018-
|
11
|
+
date: 2018-10-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async
|