http2 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
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,