fast_send 1.2.0 → 1.2.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
- SHA1:
3
- metadata.gz: 26069db40cb9f389a16d39c87a6171dd6f341256
4
- data.tar.gz: 937f14723306d0d7dcdd58b8a1178a895bcbcbdd
2
+ SHA256:
3
+ metadata.gz: 6e2c4890b5649cc57d8ada06a7d603dce77e5d98f3fed5f08cc8509f36b2f474
4
+ data.tar.gz: 55bbe6a60c743baf0b587f9d8b9f11141110f6fe8d497a1bc110620487524edf
5
5
  SHA512:
6
- metadata.gz: 325587ad50e76b729cc2075b31800d0da68410004bc5826fa936a86ae2fa68da66bfc44511167070bea6a201524d73bd63f7ca84f66e94781ef1a30b21a30cdb
7
- data.tar.gz: 25d732c665b5ad6fc96b7a822cdf28225d30e55fec78b0124b61468ec59ccd8f45bef02bc3b6d9c8c7bd6b71e645193019fd98b18d8e12ab66c3f3a91db54d94
6
+ metadata.gz: 18f09fb016ffbfec08b34b1e249c618500c72099c247f77673ac974ec2f666c7a9da9fdab605a344f42c1f60760cfd2790d5740db1fdd9e2afe2fea2bf587d97
7
+ data.tar.gz: 52de47120c17aa8c4fa10d9586c6039d04538517cc6da7be069c5082adc5755f162843183494061ec6947a698f684462b33521849d0fe4464a1aea726ea5a910
@@ -30,8 +30,6 @@ class FastSend::SocketHandler < Struct.new(:stream, :logger, :started_proc, :abo
30
30
  SENDFILE_CHUNK_SIZE = 2*1024*1024
31
31
 
32
32
  def call(socket)
33
- return if socket.closed?
34
-
35
33
  writer_method_name = if socket.respond_to?(:sendfile)
36
34
  :sendfile
37
35
  elsif RUBY_PLATFORM == 'java'
@@ -39,44 +37,40 @@ class FastSend::SocketHandler < Struct.new(:stream, :logger, :started_proc, :abo
39
37
  else
40
38
  :copy_stream
41
39
  end
42
-
43
- logger.debug { "Will do file-to-socket using %s" % writer_method_name }
44
-
45
- begin
46
- logger.debug { "Starting the response" }
47
-
48
- bytes_written = 0
49
-
50
- started_proc.call(bytes_written)
51
-
52
- stream.each_file do | file |
53
- logger.debug { "Sending %s" % file.inspect }
54
- # Run the sending method, depending on the implementation
55
- send(writer_method_name, socket, file) do |n_bytes_sent|
56
- bytes_written += n_bytes_sent
57
- logger.debug { "Written %d bytes" % bytes_written }
58
- written_proc.call(n_bytes_sent, bytes_written)
59
- end
40
+
41
+ logger.debug { "Starting the response, writing via #{writer_method_name}" }
42
+ bytes_written = 0
43
+ started_proc.call(bytes_written)
44
+
45
+ return if socket.closed? # Only do this now as we need to have bytes_written set
46
+
47
+ stream.each_file do | file |
48
+ logger.debug { "Sending %s" % file.inspect }
49
+ # Run the sending method, depending on the implementation
50
+ send(writer_method_name, socket, file) do |n_bytes_sent|
51
+ bytes_written += n_bytes_sent
52
+ logger.debug { "Written %d bytes" % bytes_written }
53
+ written_proc.call(n_bytes_sent, bytes_written)
60
54
  end
61
-
62
- logger.info { "Response written in full - %d bytes" % bytes_written }
63
- done_proc.call(bytes_written)
64
- rescue *CLIENT_DISCONNECT_EXCEPTIONS => e
65
- logger.warn { "Client closed connection: #{e.class}(#{e.message})" }
66
- aborted_proc.call(e)
67
- rescue Exception => e
68
- logger.fatal { "Aborting response due to error: #{e.class}(#{e.message}) and will propagate" }
69
- aborted_proc.call(e)
70
- error_proc.call(e)
71
- raise e unless StandardError === e # Re-raise system errors, signals and other Exceptions
72
- ensure
73
- # With rack.hijack the consensus seems to be that the hijack
74
- # proc is responsible for closing the socket. We also use no-keepalive
75
- # so this should not pose any problems.
76
- socket.close unless socket.closed?
77
- logger.debug { "Performing cleanup" }
78
- cleanup_proc.call(bytes_written)
79
55
  end
56
+
57
+ logger.info { "Response written in full - %d bytes" % bytes_written }
58
+ done_proc.call(bytes_written)
59
+ rescue *CLIENT_DISCONNECT_EXCEPTIONS => e
60
+ logger.warn { "Client closed connection: #{e.class}(#{e.message})" }
61
+ aborted_proc.call(e)
62
+ rescue Exception => e
63
+ logger.fatal { "Aborting response due to error: #{e.class}(#{e.message}) and will propagate" }
64
+ aborted_proc.call(e)
65
+ error_proc.call(e)
66
+ raise e unless StandardError === e # Re-raise system errors, signals and other Exceptions
67
+ ensure
68
+ # With rack.hijack the consensus seems to be that the hijack
69
+ # proc is responsible for closing the socket. We also use no-keepalive
70
+ # so this should not pose any problems.
71
+ socket.close unless socket.closed?
72
+ logger.debug { "Performing cleanup" }
73
+ cleanup_proc.call(bytes_written)
80
74
  end
81
75
 
82
76
  # This is majorly useful - if the socket is not selectable after a certain
@@ -1,3 +1,3 @@
1
1
  class FastSend
2
- VERSION = "1.2.0"
2
+ VERSION = "1.2.1"
3
3
  end
@@ -239,7 +239,29 @@ describe 'FastSend when used with a mock Socket' do
239
239
 
240
240
  expect(output.size).to eq(source_size)
241
241
  end
242
-
242
+
243
+ it 'calls the cleanup proc even if the socket enters the handler in a closed state' do
244
+ source_size = (64 + 54) * 1024 * 1024
245
+ cleanup_proc = double('Cleanup')
246
+ app = ->(env) { [200, {'fast_send.cleanup' => cleanup_proc}, EachFileResponse.new] }
247
+
248
+ handler = described_class.new(app)
249
+
250
+ status, headers, body = handler.call({'rack.hijack?' => true, 'rack.logger' => logger})
251
+ expect(status).to eq(200)
252
+ expect(body).to eq([])
253
+
254
+ output = Tempfile.new('response_body')
255
+
256
+ already_closed_socket = FakeSocket.new(output)
257
+ already_closed_socket.close
258
+
259
+ hijack = headers.fetch('rack.hijack')
260
+
261
+ # The cleanup proc gets called with the number of bytes transferred
262
+ expect(cleanup_proc).to receive(:call).with(0)
263
+ hijack.call(already_closed_socket)
264
+ end
243
265
 
244
266
  it 'can execute the hijack proc twice without resending the data' do
245
267
  source_size = (64 + 54) * 1024 * 1024
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fast_send
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julik Tarkhanov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-05 00:00:00.000000000 Z
11
+ date: 2020-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -108,8 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
110
  requirements: []
111
- rubyforge_project:
112
- rubygems_version: 2.6.11
111
+ rubygems_version: 3.0.3
113
112
  signing_key:
114
113
  specification_version: 4
115
114
  summary: and do so bypassing the Ruby VM