-
Notifications
You must be signed in to change notification settings - Fork 35
/
HTTPStreaming.rb
107 lines (99 loc) · 3.51 KB
/
HTTPStreaming.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# This software code is made available "AS IS" without warranties of any
# kind. You may copy, display, modify and redistribute the software
# code either by itself or as incorporated into your code; provided that
# you do not remove any proprietary notices. Your use of this software
# code is at your own risk and you waive any claim against the author
# with respect to your use of this software code.
# (c) 2007 s3sync.net
#
# The purpose of this file is to overlay the net/http library
# to add some functionality
# (without changing the file itself or requiring a specific version)
# It still isn't perfectly robust, i.e. if radical changes are made
# to the underlying lib this stuff will need updating.
require 'net/http'
module Net
$HTTPStreamingDebug = false
# Allow request body to be an IO stream
# Allow an IO stream argument to stream the response body out
class HTTP
alias _HTTPStreaming_request request
def request(req, body = nil, streamResponseBodyTo = nil, &block)
if not block_given? and streamResponseBodyTo and streamResponseBodyTo.respond_to?(:write)
$stderr.puts "Response using streaming" if $HTTPStreamingDebug
# this might be a retry, we should make sure the stream is at its beginning
streamResponseBodyTo.rewind if streamResponseBodyTo.respond_to?(:rewind) and streamResponseBodyTo != $stdout
block = proc do |res|
res.read_body do |chunk|
streamResponseBodyTo.write(chunk)
end
end
end
if body != nil && body.respond_to?(:read)
$stderr.puts "Request using streaming" if $HTTPStreamingDebug
# this might be a retry, we should make sure the stream is at its beginning
body.rewind if body.respond_to?(:rewind)
req.body_stream = body
return _HTTPStreaming_request(req, nil, &block)
else
return _HTTPStreaming_request(req, body, &block)
end
end
end
end #module
module S3sync
class ProgressStream < SimpleDelegator
def initialize(s, size=0)
@start = @last = Time.new
@total = size
@transferred = 0
@closed = false
@printed = false
@innerStream = s
super(@innerStream)
__setobj__(@innerStream)
end
# need to catch reads and writes so we can count what's being transferred
def read(i)
res = @innerStream.read(i)
@transferred += res.respond_to?(:length) ? res.length : 0
now = Time.new
if(now - @last > 1) # don't do this oftener than once per second
@printed = true
begin
$stdout.printf("\rProgress: %db %db/s %s ", @transferred, (@transferred/(now - @start)).floor,
@total > 0? (100 * @transferred/@total).floor.to_s + "%" : ""
)
rescue FloatDomainError
#wtf?
end
$stdout.flush
@last = now
end
res
end
def write(s)
@transferred += s.length
res = @innerStream.write(s)
now = Time.new
if(now -@last > 1) # don't do this oftener than once per second
@printed = true
$stdout.printf("\rProgress: %db %db/s %s ", @transferred, (@transferred/(now - @start)).floor,
@total > 0? (100 * @transferred/@total).floor.to_s + "%" : ""
)
$stdout.flush
@last = now
end
res
end
def rewind()
@transferred = 0
@innerStream.rewind if @innerStream.respond_to?(:rewind)
end
def close()
$stdout.printf("\n") if @printed and not @closed
@closed = true
@innerStream.close
end
end
end #module