http2 0.0.24 → 0.0.25

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
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