http2 0.0.17 → 0.0.18

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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.17
1
+ 0.0.18
data/http2.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "http2"
8
- s.version = "0.0.17"
8
+ s.version = "0.0.18"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kasper Johansen"]
12
- s.date = "2013-06-26"
12
+ s.date = "2013-06-28"
13
13
  s.description = "A lightweight framework for doing http-connections in Ruby. Supports cookies, keep-alive, compressing and much more."
14
14
  s.email = "k@spernj.org"
15
15
  s.extra_rdoc_files = [
@@ -36,7 +36,7 @@ Gem::Specification.new do |s|
36
36
  s.homepage = "http://github.com/kaspernj/http2"
37
37
  s.licenses = ["MIT"]
38
38
  s.require_paths = ["lib"]
39
- s.rubygems_version = "1.8.11"
39
+ s.rubygems_version = "1.8.23"
40
40
  s.summary = "A lightweight framework for doing http-connections in Ruby. Supports cookies, keep-alive, compressing and much more."
41
41
 
42
42
  if s.respond_to? :specification_version then
data/include/errors.rb CHANGED
@@ -9,4 +9,9 @@ class Http2::Errors
9
9
  class Internalserver < RuntimeError
10
10
  attr_accessor :response
11
11
  end
12
+
13
+ #Raised when a page is not found.
14
+ class Notfound < RuntimeError
15
+ attr_accessor :response
16
+ end
12
17
  end
data/include/response.rb CHANGED
@@ -8,6 +8,7 @@ class Http2::Response
8
8
  @args = args
9
9
  @args[:headers] = {} if !@args.key?(:headers)
10
10
  @args[:body] = "" if !@args.key?(:body)
11
+ @debug = @args[:debug]
11
12
  end
12
13
 
13
14
  #Returns headers given from the host for the result.
@@ -73,4 +74,28 @@ class Http2::Response
73
74
  raise "URL could not be detected." if !@args[:request_args][:url]
74
75
  return @args[:request_args][:url]
75
76
  end
77
+
78
+ # Checks the data that has been sat on the object and raises various exceptions, if it does not validate somehow.
79
+ def validate!
80
+ puts "Http2: Validating response length." if @debug
81
+ validate_body_versus_content_length!
82
+ end
83
+
84
+ private
85
+
86
+ # Checks that the length of the body is the same as the given content-length if given.
87
+ def validate_body_versus_content_length!
88
+ unless self.header?("content-length")
89
+ puts "Http2: No content length given - skipping length validation." if @debug
90
+ return nil
91
+ end
92
+
93
+ content_length = self.header("content-length").to_i
94
+ body_length = @args[:body].to_s.bytesize
95
+
96
+ puts "Http2: Body length: #{body_length}" if @debug
97
+ puts "Http2: Content length: #{content_length}" if @debug
98
+
99
+ raise "Body does not match the given content-length: '#{body_length}', '#{content_length}'." if body_length != content_length
100
+ end
76
101
  end
data/lib/http2.rb CHANGED
@@ -388,7 +388,7 @@ class Http2
388
388
  header_str << praw
389
389
  header_str << @nl
390
390
 
391
- puts "Header str: #{header_str}" if @debug
391
+ puts "Http2: Header str: #{header_str}" if @debug
392
392
 
393
393
  self.write(header_str)
394
394
  return self.read_response(args)
@@ -469,7 +469,7 @@ class Http2
469
469
 
470
470
 
471
471
  #Debug.
472
- print "Headerstr: #{header_str}\n" if @debug
472
+ print "Http2: Headerstr: #{header_str}\n" if @debug
473
473
 
474
474
 
475
475
  #Write and return.
@@ -534,14 +534,15 @@ class Http2
534
534
  # res = http.read_response
535
535
  def read_response(args = {})
536
536
  @mode = "headers"
537
- @resp = Http2::Response.new(:request_args => args)
538
-
537
+ @transfer_encoding = nil
538
+ @resp = Http2::Response.new(:request_args => args, :debug => @debug)
539
539
  rec_count = 0
540
540
 
541
541
  loop do
542
542
  begin
543
543
  if @length and @length > 0 and @mode == "body"
544
544
  line = @sock.read(@length)
545
+ raise "Expected to get #{@length} of bytes but got #{line.bytesize}" if @length != line.bytesize
545
546
  else
546
547
  line = @sock.gets
547
548
  end
@@ -553,7 +554,7 @@ class Http2
553
554
  raise Errno::ECONNABORTED, "Server closed the connection before being able to read anything (KeepAliveMax: '#{@keepalive_max}', Connection: '#{@connection}', PID: '#{Process.pid}')."
554
555
  end
555
556
 
556
- print "<#{@mode}>: '#{line}'\n" if @debug
557
+ puts "<#{@mode}>: '#{line}'" if @debug
557
558
  rescue Errno::ECONNRESET => e
558
559
  if rec_count > 0
559
560
  print "Http2: The connection was reset while reading - breaking gently...\n" if @debug
@@ -567,7 +568,8 @@ class Http2
567
568
  break if line.to_s == ""
568
569
 
569
570
  if @mode == "headers" and line == @nl
570
- print "Http2: Changing mode to body!\n" if @debug
571
+ puts "Http2: Changing mode to body!" if @debug
572
+ raise "No headers was given at all? Possibly corrupt state after last request?" if @resp.headers.empty?
571
573
  break if @length == 0
572
574
  @mode = "body"
573
575
  self.on_content_call(args, @nl)
@@ -584,6 +586,12 @@ class Http2
584
586
  end
585
587
 
586
588
 
589
+ #Release variables.
590
+ resp = @resp
591
+ @resp = nil
592
+ @mode = nil
593
+
594
+
587
595
  #Check if we should reconnect based on keep-alive-max.
588
596
  if @keepalive_max == 1 or @connection == "close"
589
597
  @sock.close if !@sock.closed?
@@ -591,30 +599,31 @@ class Http2
591
599
  end
592
600
 
593
601
 
602
+
603
+ # Validate that the response is as it should be.
604
+ puts "Http2: Validating response." if @debug
605
+ resp.validate!
606
+
607
+
594
608
  #Check if the content is gzip-encoded - if so: decode it!
595
609
  if @encoding == "gzip"
596
610
  require "zlib"
597
- require "iconv"
598
611
  require "stringio"
599
- io = StringIO.new(@resp.args[:body])
612
+ io = StringIO.new(resp.args[:body])
600
613
  gz = Zlib::GzipReader.new(io)
601
614
  untrusted_str = gz.read
602
615
 
603
616
  begin
604
- valid_string = ic.encode("utf-8")
617
+ valid_string = ic.encode("UTF-8")
605
618
  rescue
606
- ic = Iconv.new("UTF-8//IGNORE", "UTF-8")
607
- valid_string = ic.iconv(untrusted_str + " ")[0..-2]
619
+ valid_string = untrusted_str.force_encoding("UTF-8").encode("UTF-8", :invalid => :replace, :replace => "").encode("UTF-8")
608
620
  end
609
621
 
610
- @resp.args[:body] = valid_string
622
+ resp.args[:body] = valid_string
611
623
  end
612
624
 
613
625
 
614
- #Release variables.
615
- resp = @resp
616
- @resp = nil
617
- @mode = nil
626
+
618
627
 
619
628
  raise "No status-code was received from the server. Headers: '#{resp.headers}' Body: '#{resp.args[:body]}'." if !resp.args[:code]
620
629
 
@@ -628,7 +637,7 @@ class Http2
628
637
  args[:ssl] = true if uri.scheme == "https"
629
638
  args[:port] = uri.port if uri.port
630
639
 
631
- print "Redirecting from location-header to '#{url}'.\n" if @debug
640
+ puts "Http2: Redirecting from location-header to '#{url}'." if @debug
632
641
 
633
642
  if !args[:host] or args[:host] == @args[:host]
634
643
  return self.get(url)
@@ -644,6 +653,10 @@ class Http2
644
653
  err = Http2::Errors::Noaccess.new(resp.body)
645
654
  err.response = resp
646
655
  raise err
656
+ elsif @raise_errors && resp.args[:code].to_i == 404
657
+ err = Http2::Errors::Notfound.new(resp.body)
658
+ err.response = resp
659
+ raise err
647
660
  else
648
661
  autostate_register(resp) if @args[:autostate]
649
662
 
@@ -688,13 +701,16 @@ class Http2
688
701
 
689
702
  @ctype = ctype
690
703
  @resp.args[:contenttype] = @ctype
704
+ elsif key == "transfer-encoding"
705
+ @transfer_encoding = match[2].to_s.downcase.strip
691
706
  end
692
707
 
693
708
  if key != "transfer-encoding" and key != "content-length" and key != "connection" and key != "keep-alive"
694
709
  self.on_content_call(args, line)
695
710
  end
696
711
 
697
- @resp.headers[key] = [] if !@resp.headers.key?(key)
712
+ puts "Http2: Parsed header: #{match[1]}: #{match[2]}" if @debug
713
+ @resp.headers[key] = [] unless @resp.headers.key?(key)
698
714
  @resp.headers[key] << match[2]
699
715
  elsif match = line.match(/^HTTP\/([\d\.]+)\s+(\d+)\s+(.+)$/)
700
716
  @resp.args[:code] = match[2]
@@ -710,7 +726,7 @@ class Http2
710
726
  if @resp.args[:http_version] = "1.1"
711
727
  return "break" if @length == 0
712
728
 
713
- if @resp.header("transfer-encoding").to_s.downcase == "chunked"
729
+ if @transfer_encoding == "chunked"
714
730
  len = line.strip.hex
715
731
 
716
732
  if len > 0
@@ -731,9 +747,10 @@ class Http2
731
747
 
732
748
  raise "Should have read newline but didnt: '#{nl}'." if nl != @nl
733
749
  else
750
+ puts "Http2: Adding #{line.to_s.bytesize} to the body." if @debug
734
751
  @resp.args[:body] << line.to_s
735
752
  self.on_content_call(args, line)
736
- return "break" if @resp.header?("content-length") and @resp.args[:body].length >= @resp.header("content-length").to_i
753
+ return "break" if @resp.header?("content-length") && @resp.args[:body].length >= @resp.header("content-length").to_i
737
754
  end
738
755
  else
739
756
  raise "Dont know how to read HTTP version: '#{@resp.args[:http_version]}'."
data/spec/http2_spec.rb CHANGED
@@ -26,7 +26,7 @@ describe "Http2" do
26
26
  require "json"
27
27
 
28
28
  #Test posting keep-alive and advanced post-data.
29
- Http2.new(:host => "www.partyworm.dk") do |http|
29
+ Http2.new(:host => "www.partyworm.dk", :debug => false) do |http|
30
30
  0.upto(5) do
31
31
  resp = http.get("multipart_test.php")
32
32
 
@@ -110,4 +110,10 @@ describe "Http2" do
110
110
  isgd = Http2.isgdlink("https://github.com/kaspernj/http2")
111
111
  raise "Expected isgd-var to be valid but it wasnt: '#{isgd}'." if !isgd.match(/^http:\/\/is\.gd\/([A-z\d]+)$/)
112
112
  end
113
+
114
+ it "should raise exception when something is not found" do
115
+ expect{
116
+ res = Http2.new(:host => "www.partyworm.dk").get("something_that_does_not_exist.php")
117
+ }.to raise_error
118
+ end
113
119
  end
metadata CHANGED
@@ -1,60 +1,80 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.17
5
4
  prerelease:
5
+ version: 0.0.18
6
6
  platform: ruby
7
7
  authors:
8
8
  - Kasper Johansen
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-26 00:00:00.000000000 Z
12
+ date: 2013-06-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: rspec
16
- requirement: &9884720 !ruby/object:Gem::Requirement
15
+ version_requirements: !ruby/object:Gem::Requirement
17
16
  none: false
18
17
  requirements:
19
18
  - - ~>
20
19
  - !ruby/object:Gem::Version
21
20
  version: 2.8.0
21
+ name: rspec
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *9884720
24
+ requirement: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 2.8.0
25
30
  - !ruby/object:Gem::Dependency
26
- name: rdoc
27
- requirement: &9883900 !ruby/object:Gem::Requirement
31
+ version_requirements: !ruby/object:Gem::Requirement
28
32
  none: false
29
33
  requirements:
30
34
  - - ~>
31
35
  - !ruby/object:Gem::Version
32
36
  version: '3.12'
37
+ name: rdoc
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *9883900
40
+ requirement: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '3.12'
36
46
  - !ruby/object:Gem::Dependency
37
- name: bundler
38
- requirement: &9882980 !ruby/object:Gem::Requirement
47
+ version_requirements: !ruby/object:Gem::Requirement
39
48
  none: false
40
49
  requirements:
41
50
  - - ! '>='
42
51
  - !ruby/object:Gem::Version
43
52
  version: 1.0.0
53
+ name: bundler
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *9882980
56
+ requirement: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 1.0.0
47
62
  - !ruby/object:Gem::Dependency
48
- name: jeweler
49
- requirement: &9881920 !ruby/object:Gem::Requirement
63
+ version_requirements: !ruby/object:Gem::Requirement
50
64
  none: false
51
65
  requirements:
52
66
  - - ~>
53
67
  - !ruby/object:Gem::Version
54
68
  version: 1.8.4
69
+ name: jeweler
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *9881920
72
+ requirement: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.8.4
58
78
  description: A lightweight framework for doing http-connections in Ruby. Supports
59
79
  cookies, keep-alive, compressing and much more.
60
80
  email: k@spernj.org
@@ -91,10 +111,10 @@ required_ruby_version: !ruby/object:Gem::Requirement
91
111
  requirements:
92
112
  - - ! '>='
93
113
  - !ruby/object:Gem::Version
94
- version: '0'
95
114
  segments:
96
115
  - 0
97
- hash: 1747882727937754556
116
+ hash: 3868289279396036379
117
+ version: '0'
98
118
  required_rubygems_version: !ruby/object:Gem::Requirement
99
119
  none: false
100
120
  requirements:
@@ -103,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
123
  version: '0'
104
124
  requirements: []
105
125
  rubyforge_project:
106
- rubygems_version: 1.8.11
126
+ rubygems_version: 1.8.23
107
127
  signing_key:
108
128
  specification_version: 3
109
129
  summary: A lightweight framework for doing http-connections in Ruby. Supports cookies,