net-http-uploadprogress 1.0.0 → 2.0.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 +7 -0
- data/.gitignore +17 -1
- data/README.md +36 -0
- data/lib/net/http/uploadprogress.rb +34 -44
- data/lib/version.rb +1 -1
- data/net-http-uploadprogress.gemspec +4 -7
- data/spec/uploadprogress_spec.rb +138 -0
- metadata +30 -13
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dfca04e2958f5d9e546ee58349ce09b74c0e7eee
|
4
|
+
data.tar.gz: cfd40ef1a395ef7b083b011dbd6aaf9d244eada0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5c70ed1e96f4785be5df32f1e35e6940c63c41e37bd0fead8907aaf4702e4c98e7518b27dd70da3d48747f3f8f7744c3e2d70b6c5b9e26470172d24b723531f8
|
7
|
+
data.tar.gz: a55755082262ba51b9b86fb3e47813be53eb2bd900ffcb1171086b4747e5a67b00e62c66868865846dd619fe733c22ba31c0fc3d2fd0fe0cbc68bb660e3f4b45
|
data/.gitignore
CHANGED
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# net-http-uploadprogress.gem
|
2
|
+
|
3
|
+
Get the file uploading progress.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
gem install net-http-uploadprogress
|
8
|
+
|
9
|
+
## Examples
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
require 'net/http/uploadprogress'
|
13
|
+
|
14
|
+
# API style upload
|
15
|
+
File.open('path/to.file', 'rb') do |io|
|
16
|
+
http = Net::HTTP.new(host, port)
|
17
|
+
req = Net::HTTP::Post.new('/')
|
18
|
+
req.content_length = io.size
|
19
|
+
req.body_stream = io
|
20
|
+
Net::HTTP::UploadProgress.new(req) do |progress|
|
21
|
+
puts "uploaded so far: #{ progress.upload_size }"
|
22
|
+
end
|
23
|
+
res = http.request(req)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Form input type="file" style upload
|
27
|
+
File.open('path/to.file', 'rb') do |io|
|
28
|
+
http = Net::HTTP.new(host, port)
|
29
|
+
req = Net::HTTP::Post.new('/')
|
30
|
+
req.set_form({'file_form_field_name' => io}, 'multipart/form-data')
|
31
|
+
Net::HTTP::UploadProgress.new(req) do |progress|
|
32
|
+
puts "uploaded so far: #{ progress.upload_size }"
|
33
|
+
end
|
34
|
+
res = http.request(req)
|
35
|
+
end
|
36
|
+
```
|
@@ -1,52 +1,42 @@
|
|
1
1
|
require 'net/http'
|
2
|
-
require '
|
2
|
+
require 'tempfile'
|
3
|
+
require 'securerandom'
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
def begin_transport(req)
|
7
|
-
if @socket.closed?
|
8
|
-
req.reset_upload_size
|
9
|
-
connect
|
10
|
-
end
|
11
|
-
if not req.response_body_permitted? and @close_on_empty_response
|
12
|
-
req['connection'] ||= 'close'
|
13
|
-
end
|
14
|
-
req['host'] ||= addr_port()
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
class HTTPGenericRequest
|
19
|
-
def reset_upload_size
|
20
|
-
@upload_size = 0
|
21
|
-
end
|
5
|
+
class Net::HTTP::UploadProgress
|
6
|
+
attr_reader :upload_size
|
22
7
|
|
23
|
-
|
24
|
-
|
25
|
-
|
8
|
+
def initialize(req, &block)
|
9
|
+
@req = req
|
10
|
+
@callback = block
|
11
|
+
@upload_size = 0
|
12
|
+
if req.body_stream
|
13
|
+
@io = req.body_stream
|
14
|
+
req.body_stream = self
|
15
|
+
elsif req.instance_variable_get(:@body_data)
|
16
|
+
raise NotImplementedError if req.chunked?
|
17
|
+
raise NotImplementedError if /\Amultipart\/form-data\z/i !~ req.content_type
|
18
|
+
opt = req.instance_variable_get(:@form_option).dup
|
19
|
+
opt[:boundary] ||= SecureRandom.urlsafe_base64(40)
|
20
|
+
req.set_content_type(req.content_type, boundary: opt[:boundary])
|
21
|
+
file = Tempfile.new('multipart')
|
22
|
+
file.binmode
|
23
|
+
req.send(:encode_multipart_form_data, file, req.instance_variable_get(:@body_data), opt)
|
24
|
+
file.rewind
|
25
|
+
req.content_length = file.size
|
26
|
+
@io = file
|
27
|
+
req.body_stream = self
|
28
|
+
else
|
29
|
+
raise NotImplementedError
|
26
30
|
end
|
31
|
+
end
|
27
32
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
"Content-Length not given and Transfer-Encoding is not `chunked'"
|
34
|
-
end
|
35
|
-
@upload_size = 0 if @upload_size.nil?
|
36
|
-
supply_default_content_type
|
37
|
-
write_header sock, ver, path
|
38
|
-
if chunked?
|
39
|
-
while s = f.read(1024)
|
40
|
-
@upload_size += s.length
|
41
|
-
sock.write(sprintf("%x\r\n", s.length) << s << "\r\n")
|
42
|
-
end
|
43
|
-
sock.write "0\r\n\r\n"
|
44
|
-
else
|
45
|
-
while s = f.read(1024)
|
46
|
-
@upload_size += s.length
|
47
|
-
sock.write s
|
48
|
-
end
|
49
|
-
end
|
33
|
+
def readpartial(maxlen, outbuf)
|
34
|
+
begin
|
35
|
+
str = @io.readpartial(maxlen, outbuf)
|
36
|
+
ensure
|
37
|
+
@callback.call(self) unless @upload_size.zero?
|
50
38
|
end
|
39
|
+
@upload_size += str.length
|
40
|
+
str
|
51
41
|
end
|
52
42
|
end
|
data/lib/version.rb
CHANGED
@@ -5,20 +5,17 @@ require "version"
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "net-http-uploadprogress"
|
7
7
|
s.version = NetHttpUploadprogress::VERSION
|
8
|
-
s.authors = ["SKAhack"]
|
9
|
-
s.email = ["m@skahack.com"]
|
8
|
+
s.authors = ["SKAhack", "Vais Salikhov"]
|
9
|
+
s.email = ["m@skahack.com", "vsalikhov@gmail.com"]
|
10
10
|
s.homepage = "https://github.com/SKAhack/net-http-uploadprogress"
|
11
11
|
s.summary = %q{Get the file uploading progress.}
|
12
12
|
s.description = %q{Get the file uploading progress.}
|
13
13
|
|
14
|
-
s.rubyforge_project = "net-http-uploadprogress"
|
15
|
-
|
16
14
|
s.files = `git ls-files`.split("\n")
|
17
15
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
17
|
s.require_paths = ["lib"]
|
20
18
|
|
21
|
-
|
22
|
-
|
23
|
-
# s.add_runtime_dependency "rest-client"
|
19
|
+
s.required_ruby_version = '~> 2.0'
|
20
|
+
s.add_development_dependency "minitest"
|
24
21
|
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
# To run this test execute:
|
2
|
+
# $ bundle exec ruby spec/uploadprogress_spec.rb
|
3
|
+
|
4
|
+
require 'minitest/autorun'
|
5
|
+
require 'webrick'
|
6
|
+
require 'stringio'
|
7
|
+
|
8
|
+
require 'net/http/uploadprogress'
|
9
|
+
|
10
|
+
RUBY_IO_COPY_STREAM_BUFLEN = 16 * 1024
|
11
|
+
# See io.c
|
12
|
+
# static VALUE copy_stream_fallback_body(VALUE arg)
|
13
|
+
# ...
|
14
|
+
# const int buflen = 16*1024;
|
15
|
+
# ...
|
16
|
+
# https://github.com/ruby/ruby/blob/trunk/io.c#L10414
|
17
|
+
|
18
|
+
|
19
|
+
server = WEBrick::HTTPServer.new({
|
20
|
+
:BindAddress => '127.0.0.1',
|
21
|
+
:Port => 0,
|
22
|
+
:Logger => WEBrick::Log.new([], WEBrick::BasicLog::WARN),
|
23
|
+
:AccessLog => [],
|
24
|
+
:ServerType => Thread
|
25
|
+
})
|
26
|
+
|
27
|
+
server.mount_proc('/echo') do |req, res|
|
28
|
+
res.body = req.body
|
29
|
+
end
|
30
|
+
|
31
|
+
server.mount_proc('/file') do |req, res|
|
32
|
+
res.body = req.query['file']
|
33
|
+
end
|
34
|
+
|
35
|
+
server.start
|
36
|
+
|
37
|
+
describe 'Upload' do
|
38
|
+
[{
|
39
|
+
description: "smaller than buflen",
|
40
|
+
content_length: RUBY_IO_COPY_STREAM_BUFLEN - 1,
|
41
|
+
times_called: 1
|
42
|
+
}, {
|
43
|
+
description: "equal to buflen",
|
44
|
+
content_length: RUBY_IO_COPY_STREAM_BUFLEN,
|
45
|
+
times_called: 1
|
46
|
+
}, {
|
47
|
+
description: "larger than buflen",
|
48
|
+
content_length: RUBY_IO_COPY_STREAM_BUFLEN + 1,
|
49
|
+
times_called: 2
|
50
|
+
}, {
|
51
|
+
description: "exactly 2x larger than buflen",
|
52
|
+
content_length: RUBY_IO_COPY_STREAM_BUFLEN * 2,
|
53
|
+
times_called: 2
|
54
|
+
}, {
|
55
|
+
description: "more than 2x larger than buflen",
|
56
|
+
content_length: RUBY_IO_COPY_STREAM_BUFLEN * 2 + 1,
|
57
|
+
times_called: 3
|
58
|
+
}].each do |upload|
|
59
|
+
|
60
|
+
describe upload[:description] do
|
61
|
+
http = Net::HTTP.new(server[:BindAddress], server[:Port])
|
62
|
+
content = 'a' * upload[:content_length]
|
63
|
+
req = Net::HTTP::Post.new('/echo')
|
64
|
+
req.content_length = upload[:content_length]
|
65
|
+
req.body_stream = StringIO.new(content)
|
66
|
+
|
67
|
+
times_called = 0
|
68
|
+
upload_size = 0
|
69
|
+
|
70
|
+
Net::HTTP::UploadProgress.new(req) do |progress|
|
71
|
+
times_called += 1
|
72
|
+
upload_size += progress.upload_size - upload_size
|
73
|
+
end
|
74
|
+
|
75
|
+
res = http.request(req)
|
76
|
+
|
77
|
+
it 'correctly transmits data to the server' do
|
78
|
+
assert_equal(content, res.body)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'updates progress expected number of times' do
|
82
|
+
assert_equal(upload[:times_called], times_called)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'updates progress with correct upload size' do
|
86
|
+
assert_equal(upload[:content_length], upload_size)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'file' do
|
92
|
+
http = Net::HTTP.new(server[:BindAddress], server[:Port])
|
93
|
+
req = Net::HTTP::Post.new('/file')
|
94
|
+
|
95
|
+
content = 'hello'
|
96
|
+
|
97
|
+
file = Tempfile.new('uploadprogress_spec')
|
98
|
+
file.binmode
|
99
|
+
file << content
|
100
|
+
file.rewind
|
101
|
+
|
102
|
+
req.set_form({'file' => file}, 'multipart/form-data', boundary: 'UfpmKZyktEWfuJidfSVW_Ss-HV5f-mbma0uQchAVbCJFxhKnYOcaTA')
|
103
|
+
|
104
|
+
multipart_content = [
|
105
|
+
'--UfpmKZyktEWfuJidfSVW_Ss-HV5f-mbma0uQchAVbCJFxhKnYOcaTA',
|
106
|
+
'Content-Disposition: form-data; name="file"; filename="<filename>"',
|
107
|
+
'Content-Type: application/octet-stream',
|
108
|
+
'',
|
109
|
+
'hello',
|
110
|
+
'--UfpmKZyktEWfuJidfSVW_Ss-HV5f-mbma0uQchAVbCJFxhKnYOcaTA--',
|
111
|
+
''
|
112
|
+
].join("\r\n").sub('<filename>', File.basename(file.path))
|
113
|
+
|
114
|
+
times_called = 0
|
115
|
+
upload_size = 0
|
116
|
+
|
117
|
+
Net::HTTP::UploadProgress.new(req) do |progress|
|
118
|
+
times_called += 1
|
119
|
+
upload_size += progress.upload_size - upload_size
|
120
|
+
end
|
121
|
+
|
122
|
+
res = http.request(req)
|
123
|
+
|
124
|
+
file.close!
|
125
|
+
|
126
|
+
it 'correctly transmits data to the server' do
|
127
|
+
assert_equal(content, res.body)
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'updates progress expected number of times' do
|
131
|
+
assert_equal(1, times_called)
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'updates progress with correct upload size' do
|
135
|
+
assert_equal(multipart_content.length, upload_size)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
metadata
CHANGED
@@ -1,51 +1,68 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: net-http-uploadprogress
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
5
|
-
prerelease:
|
4
|
+
version: 2.0.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- SKAhack
|
8
|
+
- Vais Salikhov
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
dependencies:
|
12
|
+
date: 2015-01-12 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: minitest
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - '>='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - '>='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
14
28
|
description: Get the file uploading progress.
|
15
29
|
email:
|
16
30
|
- m@skahack.com
|
31
|
+
- vsalikhov@gmail.com
|
17
32
|
executables: []
|
18
33
|
extensions: []
|
19
34
|
extra_rdoc_files: []
|
20
35
|
files:
|
21
36
|
- .gitignore
|
22
37
|
- Gemfile
|
38
|
+
- README.md
|
23
39
|
- Rakefile
|
24
40
|
- lib/net/http/uploadprogress.rb
|
25
41
|
- lib/version.rb
|
26
42
|
- net-http-uploadprogress.gemspec
|
43
|
+
- spec/uploadprogress_spec.rb
|
27
44
|
homepage: https://github.com/SKAhack/net-http-uploadprogress
|
28
45
|
licenses: []
|
46
|
+
metadata: {}
|
29
47
|
post_install_message:
|
30
48
|
rdoc_options: []
|
31
49
|
require_paths:
|
32
50
|
- lib
|
33
51
|
required_ruby_version: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
52
|
requirements:
|
36
|
-
- -
|
53
|
+
- - ~>
|
37
54
|
- !ruby/object:Gem::Version
|
38
|
-
version: '0'
|
55
|
+
version: '2.0'
|
39
56
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
40
|
-
none: false
|
41
57
|
requirements:
|
42
|
-
- -
|
58
|
+
- - '>='
|
43
59
|
- !ruby/object:Gem::Version
|
44
60
|
version: '0'
|
45
61
|
requirements: []
|
46
|
-
rubyforge_project:
|
47
|
-
rubygems_version:
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 2.0.2
|
48
64
|
signing_key:
|
49
|
-
specification_version:
|
65
|
+
specification_version: 4
|
50
66
|
summary: Get the file uploading progress.
|
51
|
-
test_files:
|
67
|
+
test_files:
|
68
|
+
- spec/uploadprogress_spec.rb
|