async-http 0.38.0 → 0.38.1

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: 89e83fd398432897302be1ddbb07fad391a285216320e282e218c2faf07f4183
4
- data.tar.gz: c9f37f4776390db5b0d050845397d7b530b145b6072f062b453957944683d7d6
3
+ metadata.gz: 83a5e5bd7e766404f4011a11d61d6cfcc75d1cff40c1822895f21f71ccf91925
4
+ data.tar.gz: ecdde5ee1128a0ee9f947a1da217c683fda1c65c281dba0694ff72749a31ca9f
5
5
  SHA512:
6
- metadata.gz: 53f726aec29bd9130015446d9e05b5b11be437c85978f9cb6d22647ebd17dd033182e647dda82c31bfb42e14cf01b9c1b8bae904e781370564f33df390470916
7
- data.tar.gz: c698697b2d53e17a2321d430b01cd5746ef4eaf5623cb59b8a08200f86c4d3357037d85444c4141b23198bf4eba1aedd4915c8e79646717a761c02e8dd7d79b9
6
+ metadata.gz: ce5c4265e43776b208ef51ebcb5b54b84f0b86e7d8d52dbccf3905869fc6094ec88d74b6afb35eba557ffcae0699dae5f130e7b72f507ac989c28e2904e55fbb
7
+ data.tar.gz: 74b16c8ad259f0aaded61ef8094d26043354b717d299c3de04b2a4aab0169b74ebc2808f889ff284468a5ffabd4ad1a2f0e988dd67b268d3a8660303df9b7fe3
@@ -0,0 +1,70 @@
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 'writable'
22
+
23
+ require 'async/clock'
24
+
25
+ module Async
26
+ module HTTP
27
+ module Body
28
+ # A dynamic body which you can write to and read from.
29
+ class Slowloris < Writable
30
+ class ThroughputError < StandardError
31
+ def initialize(throughput, minimum_throughput, time_since_last_write)
32
+ super("Slow write: #{throughput.round(1)}bytes/s less than required #{minimum_throughput.round}bytes/s.")
33
+ end
34
+ end
35
+
36
+ # In order for this implementation to work correctly, you need to use a LimitedQueue.
37
+ # @param minimum_throughput [Integer] the minimum bytes per second otherwise this body will be forcefully closed.
38
+ def initialize(*args, minimum_throughput: 1024, **options)
39
+ super(*args, **options)
40
+
41
+ @minimum_throughput = minimum_throughput
42
+
43
+ @last_write_at = nil
44
+ @last_chunk_size = nil
45
+ end
46
+
47
+ attr :minimum_throughput
48
+
49
+ # If #read is called regularly to maintain throughput, that is good. If #read is not called, that is a problem. Throughput is dependent on data being available, from #write, so it doesn't seem particularly problimatic to do this check in #write.
50
+ def write(chunk)
51
+ if @last_chunk_size
52
+ time_since_last_write = Async::Clock.now - @last_write_at
53
+ throughput = @last_chunk_size / time_since_last_write
54
+
55
+ if throughput < @minimum_throughput
56
+ error = ThroughputError.new(throughput, @minimum_throughput, time_since_last_write)
57
+
58
+ self.close(error)
59
+ end
60
+ end
61
+
62
+ super.tap do
63
+ @last_write_at = Async::Clock.now
64
+ @last_chunk_size = chunk&.bytesize
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -51,6 +51,9 @@ module Async
51
51
  return request.stream
52
52
  end
53
53
 
54
+ def close!(state)
55
+ end
56
+
54
57
  # @return [Stream] the promised stream, on which to send data.
55
58
  def push(path, headers = nil)
56
59
  push_headers = [
@@ -52,6 +52,10 @@ module Async
52
52
  return promise.stream
53
53
  end
54
54
 
55
+ def close!(state)
56
+ self.promises.enqueue(nil)
57
+ end
58
+
55
59
  # Notify anyone waiting on the response headers to be received (or failure).
56
60
  protected def notify!
57
61
  if @notification
@@ -43,6 +43,12 @@ module Async
43
43
  @delegate.create_promise_stream(headers, stream_id)
44
44
  end
45
45
 
46
+ def close!(state = :closed)
47
+ super
48
+
49
+ @delegate.close!(state)
50
+ end
51
+
46
52
  def send_body(body, task: Async::Task.current)
47
53
  # TODO Might need to stop this task when body is cancelled.
48
54
  @task = task.async do |subtask|
@@ -20,6 +20,6 @@
20
20
 
21
21
  module Async
22
22
  module HTTP
23
- VERSION = "0.38.0"
23
+ VERSION = "0.38.1"
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.38.0
4
+ version: 0.38.1
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-02-09 00:00:00.000000000 Z
11
+ date: 2019-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -161,6 +161,7 @@ files:
161
161
  - lib/async/http/body/readable.rb
162
162
  - lib/async/http/body/reader.rb
163
163
  - lib/async/http/body/rewindable.rb
164
+ - lib/async/http/body/slowloris.rb
164
165
  - lib/async/http/body/streamable.rb
165
166
  - lib/async/http/body/wrapper.rb
166
167
  - lib/async/http/body/writable.rb