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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1ceccc4ed3d44786cd9e606a534761f41e14fac6
4
- data.tar.gz: e89411685ce84e2fa7d2de4275a6a94fe60dfa5d
3
+ metadata.gz: a747caea21ace1b6e3aea354a4d9e9ffe437dc08
4
+ data.tar.gz: 4cd7db8fbe2d498efcf28fdfad1cba6d9388c491
5
5
  SHA512:
6
- metadata.gz: 00e97764f4dfea2d97014bc8e88e43e4ad3644a73570775789b293c89fbd5bc991f77b9411e36548f3d3ab473291b8794e228893066b25c5e8548144a788523a
7
- data.tar.gz: b7a44522fa4032401c88e6f552702e9f50a6c207edb357211b91f5af645e4d40e666041abda4b7c37eadaf2bd5555cc20e4e275fbf8d6e1b4297ebc47662ff0f
6
+ metadata.gz: 5ed8bec6e8c5abaa859799a1cb378189eac83e13fccd947c736555a249d6b1de291da4b1beb65df1fba46982023c757a9374ae287f70b7a7ee1808f26f211c04
7
+ data.tar.gz: e36e5e10eb01b93e219b5912de26c9b049605c55628770e356c9d34faa11c37cfc74c28feb0d4efa0b8212729cc82424497596faa58afa4b9b7628a3f507e353
data/Gemfile CHANGED
@@ -1,7 +1,5 @@
1
1
  source "http://rubygems.org"
2
- # Add dependencies required to use your gem here.
3
- # Example:
4
- # gem "activesupport", ">= 2.3.5"
2
+
5
3
  gem "string-cases"
6
4
 
7
5
  # Add dependencies to develop your gem here.
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.3.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.8.9)
11
- multipart-post (~> 1.2.0)
12
- git (1.2.6)
13
- github_api (0.10.1)
14
- addressable
15
- faraday (~> 0.8.1)
16
- hashie (>= 1.2)
17
- multi_json (~> 1.4)
18
- nokogiri (~> 1.5.2)
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.1.1)
23
+ hashie (3.2.0)
21
24
  highline (1.6.21)
22
- jeweler (1.8.8)
25
+ jeweler (2.0.1)
23
26
  builder
24
- bundler (~> 1.0)
27
+ bundler (>= 1.0)
25
28
  git (>= 1.2.5)
26
- github_api (= 0.10.1)
29
+ github_api
27
30
  highline (>= 1.6.15)
28
- nokogiri (= 1.5.10)
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 (1.2.0)
36
- nokogiri (1.5.10)
37
- oauth2 (0.9.4)
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.8.2)
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
  [![Build Status](https://api.shippable.com/projects/53bd3eef2e23bdcb03c0df9e/badge/master)](https://www.shippable.com/projects/53bd3eef2e23bdcb03c0df9e)
4
4
  [![Code Climate](https://codeclimate.com/github/kaspernj/http2.png)](https://codeclimate.com/github/kaspernj/http2)
5
+ [![Code Climate](https://codeclimate.com/github/kaspernj/http2/coverage.png)](https://codeclimate.com/github/kaspernj/http2)
5
6
 
6
7
  Example of usage:
7
8
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.24
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.24"
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-07-09"
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/post_multipart_helper.rb",
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.require_paths = ["lib"]
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>, ["~> 1.8.4"])
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>, ["~> 1.8.4"])
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>, ["~> 1.8.4"])
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