http2 0.0.24 → 0.0.25
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/Gemfile +1 -3
- data/Gemfile.lock +25 -19
- data/README.md +1 -0
- data/VERSION +1 -1
- data/http2.gemspec +16 -8
- data/include/connection.rb +142 -0
- data/include/get_request.rb +34 -0
- data/include/post_data_generator.rb +62 -0
- data/include/post_multipart_request.rb +113 -0
- data/include/post_request.rb +71 -0
- data/include/response.rb +17 -45
- data/include/response_reader.rb +101 -97
- data/include/url_builder.rb +58 -0
- data/lib/http2.rb +52 -315
- data/spec/http2/post_data_generator_spec.rb +24 -0
- data/spec/http2/url_builder_spec.rb +17 -0
- data/spec/http2_spec.rb +18 -24
- data/spec/spec_helper.rb +3 -1
- metadata +25 -18
- data/include/post_multipart_helper.rb +0 -77
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a747caea21ace1b6e3aea354a4d9e9ffe437dc08
|
|
4
|
+
data.tar.gz: 4cd7db8fbe2d498efcf28fdfad1cba6d9388c491
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5ed8bec6e8c5abaa859799a1cb378189eac83e13fccd947c736555a249d6b1de291da4b1beb65df1fba46982023c757a9374ae287f70b7a7ee1808f26f211c04
|
|
7
|
+
data.tar.gz: e36e5e10eb01b93e219b5912de26c9b049605c55628770e356c9d34faa11c37cfc74c28feb0d4efa0b8212729cc82424497596faa58afa4b9b7628a3f507e353
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -3,38 +3,43 @@ GEM
|
|
|
3
3
|
specs:
|
|
4
4
|
addressable (2.3.6)
|
|
5
5
|
builder (3.2.2)
|
|
6
|
-
codeclimate-test-reporter (0.
|
|
6
|
+
codeclimate-test-reporter (0.4.0)
|
|
7
7
|
simplecov (>= 0.7.1, < 1.0.0)
|
|
8
|
+
descendants_tracker (0.0.4)
|
|
9
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
|
8
10
|
diff-lcs (1.1.3)
|
|
9
11
|
docile (1.1.5)
|
|
10
|
-
faraday (0.
|
|
11
|
-
multipart-post (
|
|
12
|
-
git (1.2.
|
|
13
|
-
github_api (0.
|
|
14
|
-
addressable
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
faraday (0.9.0)
|
|
13
|
+
multipart-post (>= 1.2, < 3)
|
|
14
|
+
git (1.2.8)
|
|
15
|
+
github_api (0.12.0)
|
|
16
|
+
addressable (~> 2.3)
|
|
17
|
+
descendants_tracker (~> 0.0.4)
|
|
18
|
+
faraday (~> 0.8, < 0.10)
|
|
19
|
+
hashie (>= 3.2)
|
|
20
|
+
multi_json (>= 1.7.5, < 2.0)
|
|
21
|
+
nokogiri (~> 1.6.3)
|
|
19
22
|
oauth2
|
|
20
|
-
hashie (2.
|
|
23
|
+
hashie (3.2.0)
|
|
21
24
|
highline (1.6.21)
|
|
22
|
-
jeweler (
|
|
25
|
+
jeweler (2.0.1)
|
|
23
26
|
builder
|
|
24
|
-
bundler (
|
|
27
|
+
bundler (>= 1.0)
|
|
25
28
|
git (>= 1.2.5)
|
|
26
|
-
github_api
|
|
29
|
+
github_api
|
|
27
30
|
highline (>= 1.6.15)
|
|
28
|
-
nokogiri (
|
|
31
|
+
nokogiri (>= 1.5.10)
|
|
29
32
|
rake
|
|
30
33
|
rdoc
|
|
31
34
|
json (1.8.1)
|
|
32
35
|
jwt (1.0.0)
|
|
36
|
+
mini_portile (0.6.0)
|
|
33
37
|
multi_json (1.10.1)
|
|
34
38
|
multi_xml (0.5.5)
|
|
35
|
-
multipart-post (
|
|
36
|
-
nokogiri (1.
|
|
37
|
-
|
|
39
|
+
multipart-post (2.0.0)
|
|
40
|
+
nokogiri (1.6.3.1)
|
|
41
|
+
mini_portile (= 0.6.0)
|
|
42
|
+
oauth2 (1.0.0)
|
|
38
43
|
faraday (>= 0.8, < 0.10)
|
|
39
44
|
jwt (~> 1.0)
|
|
40
45
|
multi_json (~> 1.3)
|
|
@@ -52,12 +57,13 @@ GEM
|
|
|
52
57
|
rspec-expectations (2.8.0)
|
|
53
58
|
diff-lcs (~> 1.1.2)
|
|
54
59
|
rspec-mocks (2.8.0)
|
|
55
|
-
simplecov (0.
|
|
60
|
+
simplecov (0.9.0)
|
|
56
61
|
docile (~> 1.1.0)
|
|
57
62
|
multi_json
|
|
58
63
|
simplecov-html (~> 0.8.0)
|
|
59
64
|
simplecov-html (0.8.0)
|
|
60
65
|
string-cases (0.0.0)
|
|
66
|
+
thread_safe (0.3.4)
|
|
61
67
|
|
|
62
68
|
PLATFORMS
|
|
63
69
|
ruby
|
data/README.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.shippable.com/projects/53bd3eef2e23bdcb03c0df9e)
|
|
4
4
|
[](https://codeclimate.com/github/kaspernj/http2)
|
|
5
|
+
[](https://codeclimate.com/github/kaspernj/http2)
|
|
5
6
|
|
|
6
7
|
Example of usage:
|
|
7
8
|
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.0.
|
|
1
|
+
0.0.25
|
data/http2.gemspec
CHANGED
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
|
5
|
+
# stub: http2 0.0.25 ruby lib
|
|
5
6
|
|
|
6
7
|
Gem::Specification.new do |s|
|
|
7
8
|
s.name = "http2"
|
|
8
|
-
s.version = "0.0.
|
|
9
|
+
s.version = "0.0.25"
|
|
9
10
|
|
|
10
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
12
|
+
s.require_paths = ["lib"]
|
|
11
13
|
s.authors = ["Kasper Johansen"]
|
|
12
|
-
s.date = "2014-
|
|
14
|
+
s.date = "2014-08-04"
|
|
13
15
|
s.description = "A lightweight framework for doing http-connections in Ruby. Supports cookies, keep-alive, compressing and much more."
|
|
14
16
|
s.email = "k@spernj.org"
|
|
15
17
|
s.extra_rdoc_files = [
|
|
@@ -26,20 +28,26 @@ Gem::Specification.new do |s|
|
|
|
26
28
|
"Rakefile",
|
|
27
29
|
"VERSION",
|
|
28
30
|
"http2.gemspec",
|
|
31
|
+
"include/connection.rb",
|
|
29
32
|
"include/errors.rb",
|
|
30
|
-
"include/
|
|
33
|
+
"include/get_request.rb",
|
|
34
|
+
"include/post_data_generator.rb",
|
|
35
|
+
"include/post_multipart_request.rb",
|
|
36
|
+
"include/post_request.rb",
|
|
31
37
|
"include/response.rb",
|
|
32
38
|
"include/response_reader.rb",
|
|
39
|
+
"include/url_builder.rb",
|
|
33
40
|
"include/utils.rb",
|
|
34
41
|
"lib/http2.rb",
|
|
35
42
|
"shippable.yml",
|
|
43
|
+
"spec/http2/post_data_generator_spec.rb",
|
|
44
|
+
"spec/http2/url_builder_spec.rb",
|
|
36
45
|
"spec/http2_spec.rb",
|
|
37
46
|
"spec/spec_helper.rb"
|
|
38
47
|
]
|
|
39
48
|
s.homepage = "http://github.com/kaspernj/http2"
|
|
40
49
|
s.licenses = ["MIT"]
|
|
41
|
-
s.
|
|
42
|
-
s.rubygems_version = "2.0.14"
|
|
50
|
+
s.rubygems_version = "2.4.0"
|
|
43
51
|
s.summary = "A lightweight framework for doing http-connections in Ruby. Supports cookies, keep-alive, compressing and much more."
|
|
44
52
|
|
|
45
53
|
if s.respond_to? :specification_version then
|
|
@@ -50,20 +58,20 @@ Gem::Specification.new do |s|
|
|
|
50
58
|
s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
|
|
51
59
|
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
|
52
60
|
s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
|
|
53
|
-
s.add_development_dependency(%q<jeweler>, ["
|
|
61
|
+
s.add_development_dependency(%q<jeweler>, [">= 1.8.4"])
|
|
54
62
|
else
|
|
55
63
|
s.add_dependency(%q<string-cases>, [">= 0"])
|
|
56
64
|
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
|
57
65
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
|
58
66
|
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
|
59
|
-
s.add_dependency(%q<jeweler>, ["
|
|
67
|
+
s.add_dependency(%q<jeweler>, [">= 1.8.4"])
|
|
60
68
|
end
|
|
61
69
|
else
|
|
62
70
|
s.add_dependency(%q<string-cases>, [">= 0"])
|
|
63
71
|
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
|
64
72
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
|
65
73
|
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
|
66
|
-
s.add_dependency(%q<jeweler>, ["
|
|
74
|
+
s.add_dependency(%q<jeweler>, [">= 1.8.4"])
|
|
67
75
|
end
|
|
68
76
|
end
|
|
69
77
|
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
class Http2::Connection
|
|
2
|
+
def initialize(http2)
|
|
3
|
+
@http2, @debug, @args = http2, http2.debug, http2.args
|
|
4
|
+
reconnect
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def destroy
|
|
8
|
+
@sock.close if @sock and !@sock.closed?
|
|
9
|
+
@sock = nil
|
|
10
|
+
|
|
11
|
+
@sock_plain.close if @sock_plain and !@sock_plain.closed?
|
|
12
|
+
@sock_plain = nil
|
|
13
|
+
|
|
14
|
+
@sock_ssl.close if @sock_ssl and !@sock_ssl.closed?
|
|
15
|
+
@sock_ssl = nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def gets
|
|
19
|
+
@sock.gets
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def read(length)
|
|
23
|
+
@sock.read(length)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def close
|
|
27
|
+
@sock.close
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def closed?
|
|
31
|
+
@sock.closed?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def sock_write(str)
|
|
35
|
+
str = str.to_s
|
|
36
|
+
return if str.empty?
|
|
37
|
+
count = @sock.write(str)
|
|
38
|
+
raise "Couldnt write to socket: '#{count}', '#{str}'." if count <= 0
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def sock_puts(str)
|
|
42
|
+
sock_write("#{str}#{@nl}")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Tries to write a string to the socket. If it fails it reconnects and tries again.
|
|
46
|
+
def write(str)
|
|
47
|
+
reconnect unless socket_working?
|
|
48
|
+
|
|
49
|
+
begin
|
|
50
|
+
raise Errno::EPIPE, "The socket is closed." if !@sock || @sock.closed?
|
|
51
|
+
sock_write(str)
|
|
52
|
+
rescue Errno::EPIPE #this can also be thrown by puts.
|
|
53
|
+
reconnect
|
|
54
|
+
sock_write(str)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
@request_last = Time.now
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Reconnects to the host.
|
|
61
|
+
def reconnect
|
|
62
|
+
puts "Http2: Reconnect." if @debug
|
|
63
|
+
|
|
64
|
+
#Open connection.
|
|
65
|
+
if @args[:proxy] && @args[:ssl]
|
|
66
|
+
connect_proxy_ssl
|
|
67
|
+
elsif @args[:proxy]
|
|
68
|
+
connect_proxy
|
|
69
|
+
else
|
|
70
|
+
print "Http2: Opening socket connection to '#{@args[:host]}:#{@args[:port]}'.\n" if @debug
|
|
71
|
+
@sock_plain = TCPSocket.new(@args[:host], @args[:port].to_i)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
if @args[:ssl]
|
|
75
|
+
apply_ssl
|
|
76
|
+
else
|
|
77
|
+
@sock = @sock_plain
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Returns boolean based on the if the object is connected and the socket is working.
|
|
82
|
+
#===Examples
|
|
83
|
+
# puts "Socket is working." if http.socket_working?
|
|
84
|
+
def socket_working?
|
|
85
|
+
return false if !@sock or @sock.closed?
|
|
86
|
+
|
|
87
|
+
if @keepalive_timeout && @request_last
|
|
88
|
+
between = Time.now.to_i - @request_last.to_i
|
|
89
|
+
if between >= @keepalive_timeout
|
|
90
|
+
puts "Http2: We are over the keepalive-wait - returning false for socket_working?." if @debug
|
|
91
|
+
return false
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
return true
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Closes the current connection if any.
|
|
99
|
+
def close
|
|
100
|
+
@sock.close if @sock && !@sock.closed?
|
|
101
|
+
@sock_ssl.close if @sock_ssl && !@sock_ssl.closed?
|
|
102
|
+
@sock_plain.close if @sock_plain && !@sock_plain.closed?
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def connect_proxy_ssl
|
|
106
|
+
puts "Http2: Initializing proxy stuff." if @debug
|
|
107
|
+
@sock_plain = TCPSocket.new(@args[:proxy][:host], @args[:proxy][:port])
|
|
108
|
+
|
|
109
|
+
@sock_plain.write("CONNECT #{@args[:host]}:#{@args[:port]} HTTP/1.0#{@nl}")
|
|
110
|
+
@sock_plain.write("User-Agent: #{@uagent}#{@nl}")
|
|
111
|
+
|
|
112
|
+
if @args[:proxy][:user] && @args[:proxy][:passwd]
|
|
113
|
+
credential = ["#{@args[:proxy][:user]}:#{@args[:proxy][:passwd]}"].pack("m")
|
|
114
|
+
credential.delete!("\r\n")
|
|
115
|
+
@sock_plain.write("Proxy-Authorization: Basic #{credential}#{@nl}")
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
@sock_plain.write(@nl)
|
|
119
|
+
|
|
120
|
+
res = @sock_plain.gets
|
|
121
|
+
raise res if res.to_s.downcase != "http/1.0 200 connection established#{@nl}"
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def connect_proxy
|
|
125
|
+
puts "Http2: Opening socket connection to '#{@args[:host]}:#{@args[:port]}' through proxy '#{@args[:proxy][:host]}:#{@args[:proxy][:port]}'." if @debug
|
|
126
|
+
@sock_plain = TCPSocket.new(@args[:proxy][:host], @args[:proxy][:port].to_i)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def apply_ssl
|
|
130
|
+
puts "Http2: Initializing SSL." if @debug
|
|
131
|
+
require "openssl" unless ::Kernel.const_defined?(:OpenSSL)
|
|
132
|
+
|
|
133
|
+
ssl_context = OpenSSL::SSL::SSLContext.new
|
|
134
|
+
#ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
135
|
+
|
|
136
|
+
@sock_ssl = OpenSSL::SSL::SSLSocket.new(@sock_plain, ssl_context)
|
|
137
|
+
@sock_ssl.sync_close = true
|
|
138
|
+
@sock_ssl.connect
|
|
139
|
+
|
|
140
|
+
@sock = @sock_ssl
|
|
141
|
+
end
|
|
142
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
class Http2::GetRequest
|
|
2
|
+
def initialize(http2, args)
|
|
3
|
+
@http2, @args, @debug, @nl = http2, http2.parse_args(args), http2.debug, http2.nl
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def execute
|
|
7
|
+
@http2.mutex.synchronize do
|
|
8
|
+
puts "Http2: Writing headers: #{header_string}" if @debug
|
|
9
|
+
@http2.connection.write(header_string)
|
|
10
|
+
|
|
11
|
+
puts "Http2: Reading response." if @debug
|
|
12
|
+
resp = @http2.read_response(@args)
|
|
13
|
+
|
|
14
|
+
puts "Http2: Done with get request." if @debug
|
|
15
|
+
return resp
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def method
|
|
22
|
+
if @args[:method]
|
|
23
|
+
@args[:method].to_s.upcase
|
|
24
|
+
else
|
|
25
|
+
"GET"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def header_string
|
|
30
|
+
header_str = "#{method} /#{@args[:url]} HTTP/1.1#{@nl}"
|
|
31
|
+
header_str << @http2.header_str(@http2.default_headers(@args), @args)
|
|
32
|
+
header_str << @nl
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
class Http2::PostDataGenerator
|
|
2
|
+
def initialize(pdata, args = {})
|
|
3
|
+
@pdata, @args = pdata, args
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def generate
|
|
7
|
+
praw = ""
|
|
8
|
+
|
|
9
|
+
if @pdata.is_a?(Hash)
|
|
10
|
+
praw << generate_for_hash(@pdata)
|
|
11
|
+
elsif @pdata.is_a?(Array)
|
|
12
|
+
praw << generate_for_array(@pdata)
|
|
13
|
+
else
|
|
14
|
+
return @pdata.to_s
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
return praw
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def generate_for_hash(hash)
|
|
23
|
+
praw = ""
|
|
24
|
+
|
|
25
|
+
@pdata.each do |key, val|
|
|
26
|
+
praw << "&" if praw != ""
|
|
27
|
+
key = "#{@args[:orig_key]}[#{key}]" if @args[:orig_key]
|
|
28
|
+
praw << generate_key_value(key, val)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
praw
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def generate_for_array(array)
|
|
35
|
+
praw = ""
|
|
36
|
+
|
|
37
|
+
count = 0
|
|
38
|
+
@pdata.each do |val|
|
|
39
|
+
praw << "&" if praw != ""
|
|
40
|
+
|
|
41
|
+
if @args[:orig_key]
|
|
42
|
+
key = "#{@args[:orig_key]}[#{count}]"
|
|
43
|
+
else
|
|
44
|
+
key = count
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
praw << generate_key_value(key, val)
|
|
48
|
+
count += 1
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
praw
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def generate_key_value(key, value)
|
|
55
|
+
if value.is_a?(Hash) || value.is_a?(Array)
|
|
56
|
+
return ::Http2::PostDataGenerator.new(value, :orig_key => key).generate
|
|
57
|
+
else
|
|
58
|
+
data = ::Http2::PostDataGenerator.new(value).generate
|
|
59
|
+
return "#{Http2::Utils.urlenc(key)}=#{Http2::Utils.urlenc(data)}"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
require "tempfile"
|
|
2
|
+
|
|
3
|
+
class Http2::PostMultipartRequest
|
|
4
|
+
def initialize(http2, *args)
|
|
5
|
+
@http2, @nl, @args = http2, http2.nl, http2.parse_args(*args)
|
|
6
|
+
@phash = @args[:post].clone
|
|
7
|
+
@http2.autostate_set_on_post_hash(phash) if @http2.autostate
|
|
8
|
+
@boundary = rand(36**50).to_s(36)
|
|
9
|
+
@conn = @http2.connection
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def execute
|
|
13
|
+
generate_raw(@phash) do |helper, praw|
|
|
14
|
+
puts "Http2: Header string: #{header_string}" if @debug
|
|
15
|
+
|
|
16
|
+
@http2.mutex.synchronize do
|
|
17
|
+
@conn.write(header_string(praw))
|
|
18
|
+
|
|
19
|
+
praw.rewind
|
|
20
|
+
praw.each_line do |data|
|
|
21
|
+
@conn.sock_write(data)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
return @http2.read_response(@args)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def header_string(praw)
|
|
32
|
+
header_str = "POST /#{@args[:url]} HTTP/1.1#{@nl}"
|
|
33
|
+
header_str << @http2.header_str(@http2.default_headers(@args).merge(
|
|
34
|
+
"Content-Type" => "multipart/form-data; boundary=#{@boundary}",
|
|
35
|
+
"Content-Length" => praw.size
|
|
36
|
+
), @args)
|
|
37
|
+
header_str << @nl
|
|
38
|
+
|
|
39
|
+
return header_str
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def generate_raw(phash)
|
|
43
|
+
Tempfile.open("http2_post_multipart_tmp_#{@boundary}") do |praw|
|
|
44
|
+
phash.each do |key, val|
|
|
45
|
+
add_headers(praw, key, val)
|
|
46
|
+
add_body(praw, val)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
praw << "--#{@boundary}--"
|
|
50
|
+
|
|
51
|
+
yield self, praw
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def read_file(path, praw)
|
|
56
|
+
File.open(path, "r") do |fp|
|
|
57
|
+
begin
|
|
58
|
+
while data = fp.sysread(4096)
|
|
59
|
+
praw << data
|
|
60
|
+
end
|
|
61
|
+
rescue EOFError
|
|
62
|
+
# Happens when done.
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def parse_temp_file(key, val, praw)
|
|
68
|
+
praw << "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{val.original_filename}\";#{@nl}"
|
|
69
|
+
praw << "Content-Length: #{val.to_s.bytesize}#{@nl}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def parse_file(key, val, praw)
|
|
73
|
+
praw << "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{val[:filename]}\";#{@nl}"
|
|
74
|
+
|
|
75
|
+
if val[:content]
|
|
76
|
+
praw << "Content-Length: #{val[:content].to_s.bytesize}#{@nl}"
|
|
77
|
+
elsif val[:fpath]
|
|
78
|
+
praw << "Content-Length: #{File.size(val[:fpath])}#{@nl}"
|
|
79
|
+
else
|
|
80
|
+
raise "Could not figure out where to get content from."
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def add_headers(praw, key, val)
|
|
85
|
+
praw << "--#{@boundary}#{@nl}"
|
|
86
|
+
|
|
87
|
+
if val.is_a?(Tempfile) && val.respond_to?(:original_filename)
|
|
88
|
+
parse_temp_file(key, val, praw)
|
|
89
|
+
elsif val.is_a?(Hash) && val[:filename]
|
|
90
|
+
parse_file(key, val, praw)
|
|
91
|
+
else
|
|
92
|
+
praw << "Content-Disposition: form-data; name=\"#{key}\";#{@nl}"
|
|
93
|
+
praw << "Content-Length: #{val.to_s.bytesize}#{@nl}"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
praw << "Content-Type: text/plain#{@nl}"
|
|
97
|
+
praw << @nl
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def add_body(praw, val)
|
|
101
|
+
if val.class.name.to_s == "StringIO"
|
|
102
|
+
praw << val.read
|
|
103
|
+
elsif val.is_a?(Hash) && val[:content]
|
|
104
|
+
praw << val[:content].to_s
|
|
105
|
+
elsif val.is_a?(Hash) && val[:fpath]
|
|
106
|
+
read_file(val[:fpath], praw)
|
|
107
|
+
else
|
|
108
|
+
praw << val.to_s
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
praw << @nl
|
|
112
|
+
end
|
|
113
|
+
end
|