http2 0.0.31 → 0.0.32

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: 00dd7c4f177f2a7c84ef8f9ef463fe6f2675a400
4
- data.tar.gz: 7c28395bf02c20a50d2b8633e6ddd8156c8972f3
3
+ metadata.gz: 5a6f33cdd27db12f717a7364f0b01e003fa136f4
4
+ data.tar.gz: e5db49475ea7e1d94d3637273098d3e5fa3c40ba
5
5
  SHA512:
6
- metadata.gz: bdc915bf5453cb50d0d58e298f661b833d5086f370d66bfda2e5f654d01572ea4880f340d99dd3e6853abfd20e6d3a7bed5892758add2ad4c7187087f71e59b4
7
- data.tar.gz: 54923d3a26cfe73698df0fbde92cd1dd517b61efaad45e77102fb469716d3efc4833b337bb2d915fb367d826e6370b5e068e6175a8ea7884b6b14bc9069f3024
6
+ metadata.gz: d1502af03635d87d6c13253a5f160fb697cf83f5489a99e0b2de1ed7ce3a59b38cc11c970a4848fedc8ab6ddb88c24af31d2d651360b3081ee23a12bf6700770
7
+ data.tar.gz: f4ac8597f0752a57342e0166a1bf017fc1f320d1eda7b093e7706eec8320827a5f895b320fc6bfe9e55b19dee6e58a59c62a0710a90b9cc0a177be1d5176b5f2
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- [![Build Status](https://api.shippable.com/projects/540e7b9b3479c5ea8f9ec21d/badge?branchName=master)](https://app.shippable.com/projects/540e7b9b3479c5ea8f9ec21d/builds/latest)
1
+ [![Build Status](https://img.shields.io/shippable/540e7b9b3479c5ea8f9ec21d.svg)](https://app.shippable.com/projects/540e7b9b3479c5ea8f9ec21d/builds/latest)
2
2
  [![Code Climate](https://codeclimate.com/github/kaspernj/http2.png)](https://codeclimate.com/github/kaspernj/http2)
3
3
  [![Code Climate](https://codeclimate.com/github/kaspernj/http2/coverage.png)](https://codeclimate.com/github/kaspernj/http2)
4
4
 
@@ -36,6 +36,11 @@ You can also use SSL:
36
36
  Http2.new(host: "myhost.com", ssl: true, ssl_skip_verify: true)
37
37
  ```
38
38
 
39
+ You can make it follow redirects like this:
40
+ ```ruby
41
+ Http2.new(host: "myhost.com", follow_redirects: true)
42
+ ```
43
+
39
44
  ## Get requests
40
45
  ```ruby
41
46
  res = http.get("path/to/something")
@@ -155,6 +160,14 @@ http = Http2.new(
155
160
  )
156
161
  ```
157
162
 
163
+ ## Inspect the headers that were sent
164
+
165
+ ```ruby
166
+ response = http.get("some_page")
167
+ request = response.request
168
+ request.headers_string #=> "GET /some_page\n..."
169
+ ```
170
+
158
171
  ## Contributing to http2
159
172
 
160
173
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'rubygems'
4
- require 'bundler'
3
+ require "rubygems"
4
+ require "bundler"
5
5
  begin
6
6
  Bundler.setup(:default, :development)
7
7
  rescue Bundler::BundlerError => e
@@ -9,29 +9,32 @@ rescue Bundler::BundlerError => e
9
9
  $stderr.puts "Run `bundle install` to install missing gems"
10
10
  exit e.status_code
11
11
  end
12
- require 'rake'
12
+ require "rake"
13
13
 
14
- require 'rspec/core'
15
- require 'rspec/core/rake_task'
14
+ require "rspec/core"
15
+ require "rspec/core/rake_task"
16
16
  RSpec::Core::RakeTask.new(:spec) do |spec|
17
- spec.pattern = FileList['spec/**/*_spec.rb']
17
+ spec.pattern = FileList["spec/**/*_spec.rb"]
18
18
  end
19
19
 
20
20
  RSpec::Core::RakeTask.new(:rcov) do |spec|
21
- spec.pattern = 'spec/**/*_spec.rb'
21
+ spec.pattern = "spec/**/*_spec.rb"
22
22
  spec.rcov = true
23
23
  end
24
24
 
25
- task :default => :spec
25
+ task default: :spec
26
26
 
27
- require 'rdoc/task'
27
+ require "rdoc/task"
28
28
  Rake::RDocTask.new do |rdoc|
29
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
29
+ version = File.exist?("VERSION") ? File.read("VERSION") : ""
30
30
 
31
- rdoc.rdoc_dir = 'rdoc'
31
+ rdoc.rdoc_dir = "rdoc"
32
32
  rdoc.title = "http2 #{version}"
33
- rdoc.rdoc_files.include('README*')
34
- rdoc.rdoc_files.include('lib/**/*.rb')
33
+ rdoc.rdoc_files.include("README*")
34
+ rdoc.rdoc_files.include("lib/**/*.rb")
35
35
  end
36
36
 
37
37
  Bundler::GemHelper.install_tasks
38
+
39
+ require "best_practice_project"
40
+ BestPracticeProject.load_tasks
@@ -3,7 +3,7 @@ require "uri"
3
3
  require "monitor" unless ::Kernel.const_defined?(:Monitor)
4
4
  require "string-cases"
5
5
 
6
- #This class tries to emulate a browser in Ruby without any visual stuff. Remember cookies, keep sessions alive, reset connections according to keep-alive rules and more.
6
+ # This class tries to emulate a browser in Ruby without any visual stuff. Remember cookies, keep sessions alive, reset connections according to keep-alive rules and more.
7
7
  #===Examples
8
8
  # Http2.new(host: "www.somedomain.com", port: 80, ssl: false, debug: false) do |http|
9
9
  # res = http.get("index.rhtml?show=some_page")
@@ -17,8 +17,8 @@ require "string-cases"
17
17
  class Http2
18
18
  # Autoloader for subclasses.
19
19
  def self.const_missing(name)
20
- require "#{File.dirname(__FILE__)}/../include/#{::StringCases.camel_to_snake(name)}.rb"
21
- return Http2.const_get(name)
20
+ require "#{File.dirname(__FILE__)}/http2/#{::StringCases.camel_to_snake(name)}.rb"
21
+ Http2.const_get(name)
22
22
  end
23
23
 
24
24
  # Converts a URL to "is.gd"-short-URL.
@@ -45,17 +45,21 @@ class Http2
45
45
  begin
46
46
  yield(self)
47
47
  ensure
48
- self.destroy
48
+ destroy
49
49
  end
50
50
  end
51
51
  end
52
52
 
53
53
  def host
54
- @args[:host]
54
+ @args.fetch(:host)
55
55
  end
56
56
 
57
57
  def port
58
- @args[:port]
58
+ @args.fetch(:port)
59
+ end
60
+
61
+ def ssl?
62
+ @args[:ssl] ? true : false
59
63
  end
60
64
 
61
65
  def reconnect
@@ -68,7 +72,7 @@ class Http2
68
72
  builder.port = port
69
73
  builder.protocol = @args[:protocol]
70
74
 
71
- return builder
75
+ builder
72
76
  end
73
77
 
74
78
  # Closes current connection if any, changes the arguments on the object and reconnects keeping all cookies and other stuff intact.
@@ -104,9 +108,9 @@ class Http2
104
108
  raise "Invalid arguments: '#{args.class.name}'"
105
109
  end
106
110
 
107
- raise "Invalid URL: '#{args[:url]}'" unless args[:url].to_s.split("\n").length == 1
111
+ raise "Invalid URL: '#{args[:url]}'" if args[:url] != "" && args[:url].to_s.split("\n").length != 1
108
112
 
109
- return args
113
+ args
110
114
  end
111
115
 
112
116
  # Returns a result-object based on the arguments.
@@ -154,7 +158,7 @@ class Http2
154
158
 
155
159
  headers.merge!(@args[:extra_headers]) if @args[:extra_headers]
156
160
  headers.merge!(args[:headers]) if args[:headers]
157
- return headers
161
+ headers
158
162
  end
159
163
 
160
164
  # Posts to a certain page.
@@ -172,7 +176,7 @@ class Http2
172
176
  end
173
177
 
174
178
  # Returns a header-string which normally would be used for a request in the given state.
175
- def header_str(headers_hash, args = {})
179
+ def header_str(headers_hash)
176
180
  headers_hash["Cookie"] = cookie_header_string
177
181
 
178
182
  headers_str = ""
@@ -180,21 +184,21 @@ class Http2
180
184
  headers_str << "#{key}: #{val}#{@nl}"
181
185
  end
182
186
 
183
- return headers_str
187
+ headers_str
184
188
  end
185
189
 
186
190
  def cookie_header_string
187
191
  cstr = ""
188
192
 
189
193
  first = true
190
- @cookies.each do |cookie_name, cookie|
194
+ @cookies.each do |_cookie_name, cookie|
191
195
  cstr << "; " unless first
192
196
  first = false if first
193
197
  ensure_single_lines([cookie.name, cookie.value])
194
198
  cstr << "#{Http2::Utils.urlenc(cookie.name)}=#{Http2::Utils.urlenc(cookie.value)}"
195
199
  end
196
200
 
197
- return cstr
201
+ cstr
198
202
  end
199
203
 
200
204
  def cookie(name)
@@ -216,8 +220,8 @@ class Http2
216
220
  # Reads the response after posting headers and data.
217
221
  #===Examples
218
222
  # res = http.read_response
219
- def read_response(args = {})
220
- ::Http2::ResponseReader.new(http2: self, sock: @sock, args: args).response
223
+ def read_response(request, args = {})
224
+ ::Http2::ResponseReader.new(http2: self, sock: @sock, args: args, request: request).response
221
225
  end
222
226
 
223
227
  def to_s
@@ -231,13 +235,13 @@ class Http2
231
235
  private
232
236
 
233
237
  def host_header
234
- #Possible to give custom host-argument.
238
+ # Possible to give custom host-argument.
235
239
  host = args[:host] || self.host
236
240
  port = args[:port] || self.port
237
241
 
238
242
  host_header_string = "#{host}" # Copy host string to avoid changing the original string if port has been given!
239
243
  host_header_string << ":#{port}" if port && ![80, 443].include?(port.to_i) && !@args[:skip_port_in_host_header]
240
- return host_header_string
244
+ host_header_string
241
245
  end
242
246
 
243
247
  # Registers the states from a result.
@@ -247,7 +251,6 @@ private
247
251
 
248
252
  res.body.to_s.scan(/<input type="hidden" name="__(EVENTTARGET|EVENTARGUMENT|VIEWSTATE|LASTFOCUS)" id="(.*?)" value="(.*?)" \/>/) do |match|
249
253
  name = "__#{match[0]}"
250
- id = match[1]
251
254
  value = match[2]
252
255
 
253
256
  puts "Http2: Registered autostate-value with name '#{name}' and value '#{value}'." if @debug
@@ -266,14 +269,14 @@ private
266
269
  args = {host: args} if args.is_a?(String)
267
270
  raise "Arguments wasnt a hash." unless args.is_a?(Hash)
268
271
 
269
- args.each do |key, val|
272
+ args.each do |key, _val|
270
273
  raise "Invalid key: '#{key}'." unless VALID_ARGUMENTS_INITIALIZE.include?(key)
271
274
  end
272
275
 
273
276
  args[:proxy][:connect] = true if args[:proxy] && !args[:proxy].key?(:connect) && args[:ssl]
274
277
 
275
278
  raise "No host was given." unless args[:host]
276
- return args
279
+ args
277
280
  end
278
281
 
279
282
  def set_default_values
@@ -281,7 +284,7 @@ private
281
284
  @autostate_values = {} if autostate
282
285
  @nl = @args[:nl] || "\r\n"
283
286
 
284
- if !@args[:port]
287
+ unless @args[:port]
285
288
  if @args[:ssl]
286
289
  @args[:port] = 443
287
290
  else
@@ -0,0 +1,22 @@
1
+ class Http2::BaseRequest
2
+ attr_reader :http2, :args, :debug
3
+
4
+ VALID_ARGUMENTS_POST = [:post, :url, :default_headers, :headers, :json, :method, :cookies, :on_content, :content_type]
5
+
6
+ def initialize(http2, args)
7
+ @http2 = http2
8
+ @args = http2.parse_args(args)
9
+ @debug = http2.debug
10
+ @nl = http2.nl
11
+
12
+ @args.each do |key, _val|
13
+ raise "Invalid key: '#{key}'." unless VALID_ARGUMENTS_POST.include?(key)
14
+ end
15
+
16
+ @conn = @http2.connection
17
+ end
18
+
19
+ def path
20
+ @args.fetch(:url)
21
+ end
22
+ end
@@ -1,6 +1,9 @@
1
1
  class Http2::Connection
2
2
  def initialize(http2)
3
- @http2, @debug, @args, @nl = http2, http2.debug, http2.args, http2.nl
3
+ @http2 = http2
4
+ @debug = http2.debug
5
+ @args = http2.args
6
+ @nl = http2.nl
4
7
  reconnect
5
8
  end
6
9
 
@@ -23,10 +26,6 @@ class Http2::Connection
23
26
  @sock.read(length)
24
27
  end
25
28
 
26
- def close
27
- @sock.close
28
- end
29
-
30
29
  def closed?
31
30
  @sock.closed?
32
31
  end
@@ -46,10 +45,12 @@ class Http2::Connection
46
45
  def write(str)
47
46
  reconnect unless socket_working?
48
47
 
48
+ puts "Http2: Writing: #{str}" if @debug
49
+
49
50
  begin
50
51
  raise Errno::EPIPE, "The socket is closed." if !@sock || @sock.closed?
51
52
  sock_write(str)
52
- rescue Errno::EPIPE #this can also be thrown by puts.
53
+ rescue Errno::EPIPE # this can also be thrown by puts.
53
54
  reconnect
54
55
  sock_write(str)
55
56
  end
@@ -61,7 +62,7 @@ class Http2::Connection
61
62
  def reconnect
62
63
  puts "Http2: Reconnect." if @debug
63
64
 
64
- #Open connection.
65
+ # Open connection.
65
66
  if @args[:proxy]
66
67
  if @args[:proxy][:connect]
67
68
  connect_proxy_connect
@@ -84,7 +85,7 @@ class Http2::Connection
84
85
  #===Examples
85
86
  # puts "Socket is working." if http.socket_working?
86
87
  def socket_working?
87
- return false if !@sock or @sock.closed?
88
+ return false if !@sock || @sock.closed?
88
89
 
89
90
  if @keepalive_timeout && @request_last
90
91
  between = Time.now.to_i - @request_last.to_i
@@ -94,7 +95,7 @@ class Http2::Connection
94
95
  end
95
96
  end
96
97
 
97
- return true
98
+ true
98
99
  end
99
100
 
100
101
  # Closes the current connection if any.
@@ -2,7 +2,10 @@ class Http2::Cookie
2
2
  attr_reader :name, :value, :path, :expires_raw
3
3
 
4
4
  def initialize(args)
5
- @name, @value, @path, @expires_raw = args[:name], args[:value], args[:path], args[:expires]
5
+ @name = args[:name]
6
+ @value = args[:value]
7
+ @path = args[:path]
8
+ @expires_raw = args[:expires]
6
9
  end
7
10
 
8
11
  def inspect
@@ -1,4 +1,4 @@
1
- #This class holds various classes for error-handeling.
1
+ # This class holds various classes for error-handeling.
2
2
  class Http2::Errors
3
3
  class Http2error < RuntimeError
4
4
  attr_accessor :response
@@ -0,0 +1,33 @@
1
+ class Http2::GetRequest < Http2::BaseRequest
2
+ def execute
3
+ @http2.mutex.synchronize do
4
+ @http2.connection.write(headers_string)
5
+
6
+ puts "Http2: Reading response." if @debug
7
+ resp = @http2.read_response(self, @args)
8
+
9
+ puts "Http2: Done with get request." if @debug
10
+ return resp
11
+ end
12
+ end
13
+
14
+ def headers_string
15
+ unless @header_str
16
+ @header_str = "#{method} /#{@args[:url]} HTTP/1.1#{@nl}"
17
+ @header_str << @http2.header_str(@http2.default_headers(@args))
18
+ @header_str << @nl
19
+ end
20
+
21
+ @header_str
22
+ end
23
+
24
+ private
25
+
26
+ def method
27
+ if @args[:method]
28
+ @args[:method].to_s.upcase
29
+ else
30
+ "GET"
31
+ end
32
+ end
33
+ end
@@ -1,6 +1,7 @@
1
1
  class Http2::PostDataGenerator
2
2
  def initialize(pdata, args = {})
3
- @pdata, @args = pdata, args
3
+ @pdata = pdata
4
+ @args = args
4
5
  end
5
6
 
6
7
  def generate
@@ -14,7 +15,7 @@ class Http2::PostDataGenerator
14
15
  return @pdata.to_s
15
16
  end
16
17
 
17
- return praw
18
+ praw
18
19
  end
19
20
 
20
21
  private
@@ -22,7 +23,7 @@ private
22
23
  def generate_for_hash(hash)
23
24
  praw = ""
24
25
 
25
- @pdata.each do |key, val|
26
+ hash.each do |key, val|
26
27
  praw << "&" if praw != ""
27
28
  key = "#{@args[:orig_key]}[#{key}]" if @args[:orig_key]
28
29
  praw << generate_key_value(key, val)
@@ -35,7 +36,7 @@ private
35
36
  praw = ""
36
37
 
37
38
  count = 0
38
- @pdata.each do |val|
39
+ array.each do |val|
39
40
  praw << "&" if praw != ""
40
41
 
41
42
  if @args[:orig_key]
@@ -1,42 +1,44 @@
1
1
  require "tempfile"
2
2
 
3
- class Http2::PostMultipartRequest
3
+ class Http2::PostMultipartRequest < Http2::BaseRequest
4
+ attr_reader :headers_string
5
+
4
6
  def initialize(http2, *args)
5
- @http2, @nl, @args = http2, http2.nl, http2.parse_args(*args)
7
+ super
8
+
6
9
  @phash = @args[:post].clone
7
10
  @http2.autostate_set_on_post_hash(phash) if @http2.autostate
8
11
  @boundary = rand(36**50).to_s(36)
9
- @conn = @http2.connection
10
12
  end
11
13
 
12
14
  def execute
13
- generate_raw(@phash) do |helper, praw|
14
- puts "Http2: Header string: #{header_string}" if @debug
15
-
15
+ generate_raw(@phash) do |_helper, praw|
16
16
  @http2.mutex.synchronize do
17
- @conn.write(header_string(praw))
17
+ @conn.write(header_string_with_raw_post(praw))
18
18
 
19
19
  praw.rewind
20
20
  praw.each_line do |data|
21
21
  @conn.sock_write(data)
22
22
  end
23
23
 
24
- return @http2.read_response(@args)
24
+ return @http2.read_response(self, @args)
25
25
  end
26
26
  end
27
27
  end
28
28
 
29
29
  private
30
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(
31
+ def header_string_with_raw_post(praw)
32
+ @headers_string = "POST /#{@args[:url]} HTTP/1.1#{@nl}"
33
+
34
+ headers = @http2.default_headers(@args).merge(
34
35
  "Content-Type" => "multipart/form-data; boundary=#{@boundary}",
35
36
  "Content-Length" => praw.size
36
- ), @args)
37
- header_str << @nl
37
+ )
38
38
 
39
- return header_str
39
+ @headers_string << @http2.header_str(headers)
40
+ @headers_string << @nl
41
+ @headers_string
40
42
  end
41
43
 
42
44
  def generate_raw(phash)
@@ -55,10 +57,12 @@ private
55
57
  def read_file(path, praw)
56
58
  File.open(path, "r") do |fp|
57
59
  begin
58
- while data = fp.sysread(4096)
60
+ while (data = fp.sysread(4096))
59
61
  praw << data
60
62
  end
63
+ # rubocop:disable Lint/HandleExceptions
61
64
  rescue EOFError
65
+ # rubocop:enable Lint/HandleExceptions
62
66
  # Happens when done.
63
67
  end
64
68
  end