http2 0.0.30 → 0.0.31
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 +4 -4
- data/README.md +37 -2
- data/include/connection.rb +36 -19
- data/include/cookie.rb +19 -0
- data/include/response_reader.rb +19 -6
- data/include/utils.rb +22 -12
- data/lib/http2.rb +52 -40
- data/spec/http2/cookies_spec.rb +18 -0
- data/spec/spec_root/cookie_test.rhtml +8 -0
- metadata +18 -13
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 00dd7c4f177f2a7c84ef8f9ef463fe6f2675a400
         | 
| 4 | 
            +
              data.tar.gz: 7c28395bf02c20a50d2b8633e6ddd8156c8972f3
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: bdc915bf5453cb50d0d58e298f661b833d5086f370d66bfda2e5f654d01572ea4880f340d99dd3e6853abfd20e6d3a7bed5892758add2ad4c7187087f71e59b4
         | 
| 7 | 
            +
              data.tar.gz: 54923d3a26cfe73698df0fbde92cd1dd517b61efaad45e77102fb469716d3efc4833b337bb2d915fb367d826e6370b5e068e6175a8ea7884b6b14bc9069f3024
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            [](https://app.shippable.com/projects/540e7b9b3479c5ea8f9ec21d/builds/latest)
         | 
| 2 2 | 
             
            [](https://codeclimate.com/github/kaspernj/http2)
         | 
| 3 3 | 
             
            [](https://codeclimate.com/github/kaspernj/http2)
         | 
| 4 4 |  | 
| @@ -23,7 +23,17 @@ http = Http2.new(...) | |
| 23 23 |  | 
| 24 24 | 
             
            # Do requests here.
         | 
| 25 25 |  | 
| 26 | 
            -
            http. | 
| 26 | 
            +
            http.destroy # Closes the connection and frees up any variables used
         | 
| 27 | 
            +
            ```
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            Or through a proxy:
         | 
| 30 | 
            +
            ```ruby
         | 
| 31 | 
            +
            Http2.new(host: "www.google.com", proxy: {host: "myproxy.com", port: 80, user: "myname", passwd: "mypassword"})
         | 
| 32 | 
            +
            ```
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            You can also use SSL:
         | 
| 35 | 
            +
            ```ruby
         | 
| 36 | 
            +
            Http2.new(host: "myhost.com", ssl: true, ssl_skip_verify: true)
         | 
| 27 37 | 
             
            ```
         | 
| 28 38 |  | 
| 29 39 | 
             
            ## Get requests
         | 
| @@ -31,6 +41,11 @@ http.close | |
| 31 41 | 
             
            res = http.get("path/to/something")
         | 
| 32 42 | 
             
            ```
         | 
| 33 43 |  | 
| 44 | 
            +
            Or as a hash:
         | 
| 45 | 
            +
            ```ruby
         | 
| 46 | 
            +
            res = http.get(url: "path/to/something")
         | 
| 47 | 
            +
            ```
         | 
| 48 | 
            +
             | 
| 34 49 | 
             
            ## Post requests
         | 
| 35 50 | 
             
            ```ruby
         | 
| 36 51 | 
             
            res = http.post(url: "path/to/something", post: {
         | 
| @@ -52,6 +67,13 @@ res = http.post( | |
| 52 67 | 
             
            res = http.post(url: "path/to/something", json: {some_argument: true})
         | 
| 53 68 | 
             
            ```
         | 
| 54 69 |  | 
| 70 | 
            +
            ### Reading JSON from request
         | 
| 71 | 
            +
            ```ruby
         | 
| 72 | 
            +
            res = http.post(url: "something", json: {some_argument: true})
         | 
| 73 | 
            +
            res.json? #=> true (if content-type is application/json)
         | 
| 74 | 
            +
            res.json #=> {"value" => "something"}
         | 
| 75 | 
            +
            ```
         | 
| 76 | 
            +
             | 
| 55 77 | 
             
            ## Delete requests
         | 
| 56 78 | 
             
            ```ruby
         | 
| 57 79 | 
             
            res = http.delete(url: "path/to/something")
         | 
| @@ -120,6 +142,19 @@ Handy when doing retries. | |
| 120 142 | 
             
            http.reconnect
         | 
| 121 143 | 
             
            ```
         | 
| 122 144 |  | 
| 145 | 
            +
             | 
| 146 | 
            +
            ## Basic HTTP authentication for all requests
         | 
| 147 | 
            +
             | 
| 148 | 
            +
            ```ruby
         | 
| 149 | 
            +
            http = Http2.new(
         | 
| 150 | 
            +
              host: "www.somehost.com",
         | 
| 151 | 
            +
              basic_auth: {
         | 
| 152 | 
            +
                user: "username",
         | 
| 153 | 
            +
                passwd: "password"
         | 
| 154 | 
            +
              }
         | 
| 155 | 
            +
            )
         | 
| 156 | 
            +
            ```
         | 
| 157 | 
            +
             | 
| 123 158 | 
             
            ## Contributing to http2
         | 
| 124 159 |  | 
| 125 160 | 
             
            * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
         | 
    
        data/include/connection.rb
    CHANGED
    
    | @@ -1,17 +1,17 @@ | |
| 1 1 | 
             
            class Http2::Connection
         | 
| 2 2 | 
             
              def initialize(http2)
         | 
| 3 | 
            -
                @http2, @debug, @args = http2, http2.debug, http2.args
         | 
| 3 | 
            +
                @http2, @debug, @args, @nl = http2, http2.debug, http2.args, http2.nl
         | 
| 4 4 | 
             
                reconnect
         | 
| 5 5 | 
             
              end
         | 
| 6 6 |  | 
| 7 7 | 
             
              def destroy
         | 
| 8 | 
            -
                @sock.close if @sock  | 
| 8 | 
            +
                @sock.close if @sock && !@sock.closed?
         | 
| 9 9 | 
             
                @sock = nil
         | 
| 10 10 |  | 
| 11 | 
            -
                @sock_plain.close if @sock_plain  | 
| 11 | 
            +
                @sock_plain.close if @sock_plain && !@sock_plain.closed?
         | 
| 12 12 | 
             
                @sock_plain = nil
         | 
| 13 13 |  | 
| 14 | 
            -
                @sock_ssl.close if @sock_ssl  | 
| 14 | 
            +
                @sock_ssl.close if @sock_ssl && !@sock_ssl.closed?
         | 
| 15 15 | 
             
                @sock_ssl = nil
         | 
| 16 16 | 
             
              end
         | 
| 17 17 |  | 
| @@ -62,10 +62,12 @@ class Http2::Connection | |
| 62 62 | 
             
                puts "Http2: Reconnect." if @debug
         | 
| 63 63 |  | 
| 64 64 | 
             
                #Open connection.
         | 
| 65 | 
            -
                if @args[:proxy] | 
| 66 | 
            -
                   | 
| 67 | 
            -
             | 
| 68 | 
            -
                   | 
| 65 | 
            +
                if @args[:proxy]
         | 
| 66 | 
            +
                  if @args[:proxy][:connect]
         | 
| 67 | 
            +
                    connect_proxy_connect
         | 
| 68 | 
            +
                  else
         | 
| 69 | 
            +
                    connect_proxy
         | 
| 70 | 
            +
                  end
         | 
| 69 71 | 
             
                else
         | 
| 70 72 | 
             
                  puts "Http2: Opening socket connection to '#{@http2.host}:#{@http2.port}'." if @debug
         | 
| 71 73 | 
             
                  @sock_plain = TCPSocket.new(@http2.host, @http2.port)
         | 
| @@ -102,23 +104,39 @@ class Http2::Connection | |
| 102 104 | 
             
                @sock_plain.close if @sock_plain && !@sock_plain.closed?
         | 
| 103 105 | 
             
              end
         | 
| 104 106 |  | 
| 105 | 
            -
              def  | 
| 106 | 
            -
                puts "Http2: Initializing proxy  | 
| 107 | 
            +
              def connect_proxy_connect
         | 
| 108 | 
            +
                puts "Http2: Initializing proxy connect to '#{@args[:host]}:#{@args[:port]}' through proxy '#{@args[:proxy][:host]}:#{@args[:proxy][:port]}'." if @debug
         | 
| 107 109 | 
             
                @sock_plain = TCPSocket.new(@args[:proxy][:host], @args[:proxy][:port])
         | 
| 108 110 |  | 
| 109 | 
            -
                 | 
| 110 | 
            -
                 | 
| 111 | 
            +
                connect = "CONNECT #{@args[:host]}:#{@args[:port]} HTTP/1.1#{@nl}"
         | 
| 112 | 
            +
                puts "Http2: Sending connect: #{connect}" if @debug
         | 
| 113 | 
            +
                @sock_plain.write(connect)
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                headers = {
         | 
| 116 | 
            +
                  "Host" => "#{@args[:host]}:#{@args[:port]}"
         | 
| 117 | 
            +
                }
         | 
| 111 118 |  | 
| 112 119 | 
             
                if @args[:proxy][:user] && @args[:proxy][:passwd]
         | 
| 113 | 
            -
                   | 
| 114 | 
            -
             | 
| 115 | 
            -
             | 
| 120 | 
            +
                  headers["Proxy-Authorization"] = "Basic #{["#{@args[:proxy][:user]}:#{@args[:proxy][:passwd]}"].pack("m").chomp}"
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                headers.each do |key, value|
         | 
| 124 | 
            +
                  header = "#{key}: #{value}"
         | 
| 125 | 
            +
                  puts "Http2: Sending header to proxy: #{header}" if @debug
         | 
| 126 | 
            +
                  @sock_plain.write("#{header}#{@nl}")
         | 
| 116 127 | 
             
                end
         | 
| 117 128 |  | 
| 118 129 | 
             
                @sock_plain.write(@nl)
         | 
| 119 130 |  | 
| 120 | 
            -
                res = @sock_plain.gets
         | 
| 121 | 
            -
                raise res  | 
| 131 | 
            +
                res = @sock_plain.gets.to_s
         | 
| 132 | 
            +
                raise "Couldn't connect through proxy: #{res}" unless res.match(/^http\/1\.(0|1)\s+200/i)
         | 
| 133 | 
            +
                @sock_plain.gets
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                @proxy_connect = true
         | 
| 136 | 
            +
              end
         | 
| 137 | 
            +
             | 
| 138 | 
            +
              def proxy_connect?
         | 
| 139 | 
            +
                @proxy_connect
         | 
| 122 140 | 
             
              end
         | 
| 123 141 |  | 
| 124 142 | 
             
              def connect_proxy
         | 
| @@ -131,8 +149,7 @@ class Http2::Connection | |
| 131 149 | 
             
                require "openssl" unless ::Kernel.const_defined?(:OpenSSL)
         | 
| 132 150 |  | 
| 133 151 | 
             
                ssl_context = OpenSSL::SSL::SSLContext.new
         | 
| 134 | 
            -
                 | 
| 135 | 
            -
             | 
| 152 | 
            +
                ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER unless @args[:ssl_skip_verify]
         | 
| 136 153 | 
             
                @sock_ssl = OpenSSL::SSL::SSLSocket.new(@sock_plain, ssl_context)
         | 
| 137 154 | 
             
                @sock_ssl.sync_close = true
         | 
| 138 155 | 
             
                @sock_ssl.connect
         | 
    
        data/include/cookie.rb
    ADDED
    
    | @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            class Http2::Cookie
         | 
| 2 | 
            +
              attr_reader :name, :value, :path, :expires_raw
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              def initialize(args)
         | 
| 5 | 
            +
                @name, @value, @path, @expires_raw = args[:name], args[:value], args[:path], args[:expires]
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              def inspect
         | 
| 9 | 
            +
                "#<Http2::Cookie name=#{@name} value=#{@value} path=#{@path}>"
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              def to_s
         | 
| 13 | 
            +
                inspect
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              def expires
         | 
| 17 | 
            +
                @expires ||= Time.parse(@expires_raw) if @expires_raw
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
    
        data/include/response_reader.rb
    CHANGED
    
    | @@ -57,8 +57,8 @@ class Http2::ResponseReader | |
| 57 57 | 
             
                # Validate that the response is as it should be.
         | 
| 58 58 | 
             
                puts "Http2: Validating response." if @debug
         | 
| 59 59 |  | 
| 60 | 
            -
                 | 
| 61 | 
            -
                  raise "No status-code was received from the server. Headers: '#{@response.headers}' Body: '#{ | 
| 60 | 
            +
                unless @response.code
         | 
| 61 | 
            +
                  raise "No status-code was received from the server. Headers: '#{@response.headers}' Body: '#{@response.body}'."
         | 
| 62 62 | 
             
                end
         | 
| 63 63 |  | 
| 64 64 | 
             
                @response.validate!
         | 
| @@ -74,10 +74,10 @@ class Http2::ResponseReader | |
| 74 74 | 
             
            private
         | 
| 75 75 |  | 
| 76 76 | 
             
              def check_and_follow_redirect
         | 
| 77 | 
            -
                if  | 
| 77 | 
            +
                if redirect_response?
         | 
| 78 78 | 
             
                  url, args = url_and_args_from_location
         | 
| 79 79 |  | 
| 80 | 
            -
                  if  | 
| 80 | 
            +
                  if redirect_using_same_connection?(args)
         | 
| 81 81 | 
             
                    return @http2.get(url)
         | 
| 82 82 | 
             
                  else
         | 
| 83 83 | 
             
                    ::Http2.new(args).get(url)
         | 
| @@ -85,6 +85,19 @@ private | |
| 85 85 | 
             
                end
         | 
| 86 86 | 
             
              end
         | 
| 87 87 |  | 
| 88 | 
            +
              REDIRECT_CODES = [302, 303, 307]
         | 
| 89 | 
            +
              def redirect_response?
         | 
| 90 | 
            +
                REDIRECT_CODES.include?(@response.code.to_i) && @response.header?("location") && @http2.args[:follow_redirects]
         | 
| 91 | 
            +
              end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
              def redirect_using_same_connection?(args)
         | 
| 94 | 
            +
                if !args[:host] || args[:host] == @args[:host]
         | 
| 95 | 
            +
                  return true
         | 
| 96 | 
            +
                else
         | 
| 97 | 
            +
                  return false
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
              end
         | 
| 100 | 
            +
             | 
| 88 101 | 
             
              def url_and_args_from_location
         | 
| 89 102 | 
             
                uri = URI.parse(@response.header("location"))
         | 
| 90 103 | 
             
                url = uri.path
         | 
| @@ -145,8 +158,8 @@ private | |
| 145 158 | 
             
              end
         | 
| 146 159 |  | 
| 147 160 | 
             
              def parse_cookie(cookie_line)
         | 
| 148 | 
            -
                ::Http2::Utils.parse_set_cookies(cookie_line).each do | | 
| 149 | 
            -
                  @http2.cookies[ | 
| 161 | 
            +
                ::Http2::Utils.parse_set_cookies(cookie_line).each do |cookie|
         | 
| 162 | 
            +
                  @http2.cookies[cookie.name] = cookie
         | 
| 150 163 | 
             
                end
         | 
| 151 164 | 
             
              end
         | 
| 152 165 |  | 
    
        data/include/utils.rb
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 | 
            -
            #This class holds various methods for encoding, decoding and parsing of HTTP-related stuff.
         | 
| 1 | 
            +
            # This class holds various methods for encoding, decoding and parsing of HTTP-related stuff.
         | 
| 2 2 | 
             
            class Http2::Utils
         | 
| 3 | 
            -
              #URL-encodes a string.
         | 
| 3 | 
            +
              # URL-encodes a string.
         | 
| 4 4 | 
             
              def self.urlenc(string)
         | 
| 5 5 | 
             
                #Thanks to CGI framework
         | 
| 6 6 | 
             
                string.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/) do
         | 
| @@ -8,7 +8,7 @@ class Http2::Utils | |
| 8 8 | 
             
                end.tr(' ', '+')
         | 
| 9 9 | 
             
              end
         | 
| 10 10 |  | 
| 11 | 
            -
              #URL-decodes a string.
         | 
| 11 | 
            +
              # URL-decodes a string.
         | 
| 12 12 | 
             
              def self.urldec(string)
         | 
| 13 13 | 
             
                #Thanks to CGI framework
         | 
| 14 14 | 
             
                str = string.to_s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/) do
         | 
| @@ -16,25 +16,35 @@ class Http2::Utils | |
| 16 16 | 
             
                end
         | 
| 17 17 | 
             
              end
         | 
| 18 18 |  | 
| 19 | 
            -
              #Parses a cookies-string and returns them in an array.
         | 
| 19 | 
            +
              # Parses a cookies-string and returns them in an array.
         | 
| 20 20 | 
             
              def self.parse_set_cookies(str)
         | 
| 21 | 
            -
                str =  | 
| 22 | 
            -
                return [] if str. | 
| 23 | 
            -
                args = {}
         | 
| 21 | 
            +
                str = "#{str}"
         | 
| 22 | 
            +
                return [] if str.empty?
         | 
| 24 23 | 
             
                cookie_start_regex = /^(.+?)=(.*?)(;\s*|$)/
         | 
| 25 24 |  | 
| 26 25 | 
             
                match = str.match(cookie_start_regex)
         | 
| 27 | 
            -
                raise "Could not match cookie: '#{str}' | 
| 26 | 
            +
                raise "Could not match cookie: '#{str}'" unless match
         | 
| 28 27 | 
             
                str.gsub!(cookie_start_regex, "")
         | 
| 29 28 |  | 
| 30 | 
            -
                 | 
| 31 | 
            -
             | 
| 29 | 
            +
                cookie_data = {
         | 
| 30 | 
            +
                  name: urldec(match[1].to_s),
         | 
| 31 | 
            +
                  value: self.urldec(match[2].to_s)
         | 
| 32 | 
            +
                }
         | 
| 32 33 |  | 
| 33 34 | 
             
                while match = str.match(/(.+?)=(.*?)(;\s*|$)/)
         | 
| 34 35 | 
             
                  str = str.gsub(match[0], "")
         | 
| 35 | 
            -
                   | 
| 36 | 
            +
                  key = match[1].to_s.downcase
         | 
| 37 | 
            +
                  value = match[2].to_s
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  if key == "path" || key == "expires"
         | 
| 40 | 
            +
                    cookie_data[key.to_sym] = value
         | 
| 41 | 
            +
                  else
         | 
| 42 | 
            +
                    cookie_data[key] = value
         | 
| 43 | 
            +
                  end
         | 
| 36 44 | 
             
                end
         | 
| 37 45 |  | 
| 38 | 
            -
                 | 
| 46 | 
            +
                cookie = Http2::Cookie.new(cookie_data)
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                return [cookie]
         | 
| 39 49 | 
             
              end
         | 
| 40 50 | 
             
            end
         | 
    
        data/lib/http2.rb
    CHANGED
    
    | @@ -15,16 +15,16 @@ require "string-cases" | |
| 15 15 | 
             
            #  print "#{res.headers}"
         | 
| 16 16 | 
             
            # end
         | 
| 17 17 | 
             
            class Http2
         | 
| 18 | 
            -
              #Autoloader for subclasses.
         | 
| 18 | 
            +
              # Autoloader for subclasses.
         | 
| 19 19 | 
             
              def self.const_missing(name)
         | 
| 20 20 | 
             
                require "#{File.dirname(__FILE__)}/../include/#{::StringCases.camel_to_snake(name)}.rb"
         | 
| 21 21 | 
             
                return Http2.const_get(name)
         | 
| 22 22 | 
             
              end
         | 
| 23 23 |  | 
| 24 | 
            -
              #Converts a URL to "is.gd"-short-URL.
         | 
| 24 | 
            +
              # Converts a URL to "is.gd"-short-URL.
         | 
| 25 25 | 
             
              def self.isgdlink(url)
         | 
| 26 26 | 
             
                Http2.new(host: "is.gd") do |http|
         | 
| 27 | 
            -
                  resp = http.get(" | 
| 27 | 
            +
                  resp = http.get("api.php?longurl=#{url}")
         | 
| 28 28 | 
             
                  return resp.body
         | 
| 29 29 | 
             
                end
         | 
| 30 30 | 
             
              end
         | 
| @@ -32,7 +32,7 @@ class Http2 | |
| 32 32 | 
             
              attr_reader :autostate, :connection, :cookies, :args, :debug, :mutex, :resp, :raise_errors, :nl
         | 
| 33 33 | 
             
              attr_accessor :keepalive_max, :keepalive_timeout
         | 
| 34 34 |  | 
| 35 | 
            -
              VALID_ARGUMENTS_INITIALIZE = [:host, :port, :skip_port_in_host_header, :ssl, :nl, :user_agent, :raise_errors, :follow_redirects, :debug, :encoding_gzip, :autostate, :basic_auth, :extra_headers, :proxy]
         | 
| 35 | 
            +
              VALID_ARGUMENTS_INITIALIZE = [:host, :port, :skip_port_in_host_header, :ssl, :ssl_skip_verify, :nl, :user_agent, :raise_errors, :follow_redirects, :debug, :encoding_gzip, :autostate, :basic_auth, :extra_headers, :proxy]
         | 
| 36 36 | 
             
              def initialize(args = {})
         | 
| 37 37 | 
             
                @args = parse_init_args(args)
         | 
| 38 38 | 
             
                set_default_values
         | 
| @@ -78,7 +78,7 @@ class Http2 | |
| 78 78 | 
             
                @connection = ::Http2::Connection.new(self)
         | 
| 79 79 | 
             
              end
         | 
| 80 80 |  | 
| 81 | 
            -
              #Destroys the object unsetting all variables and closing all sockets.
         | 
| 81 | 
            +
              # Destroys the object unsetting all variables and closing all sockets.
         | 
| 82 82 | 
             
              #===Examples
         | 
| 83 83 | 
             
              # http.destroy
         | 
| 84 84 | 
             
              def destroy
         | 
| @@ -94,26 +94,22 @@ class Http2 | |
| 94 94 | 
             
                @connection = nil
         | 
| 95 95 | 
             
              end
         | 
| 96 96 |  | 
| 97 | 
            -
              #Forces various stuff into arguments-hash like URL from original arguments and enables single-string-shortcuts and more.
         | 
| 97 | 
            +
              # Forces various stuff into arguments-hash like URL from original arguments and enables single-string-shortcuts and more.
         | 
| 98 98 | 
             
              def parse_args(*args)
         | 
| 99 99 | 
             
                if args.length == 1 && args.first.is_a?(String)
         | 
| 100 100 | 
             
                  args = {url: args.first}
         | 
| 101 | 
            -
                elsif args.length  | 
| 102 | 
            -
                  raise "Couldnt parse arguments."
         | 
| 103 | 
            -
                elsif args.is_a?(Array) && args.length == 1
         | 
| 101 | 
            +
                elsif args.length == 1
         | 
| 104 102 | 
             
                  args = args.first
         | 
| 105 103 | 
             
                else
         | 
| 106 | 
            -
                  raise "Invalid arguments: '#{args.class.name}' | 
| 104 | 
            +
                  raise "Invalid arguments: '#{args.class.name}'"
         | 
| 107 105 | 
             
                end
         | 
| 108 106 |  | 
| 109 | 
            -
                 | 
| 110 | 
            -
                  raise "Invalid URL: '#{args[:url]}'."
         | 
| 111 | 
            -
                end
         | 
| 107 | 
            +
                raise "Invalid URL: '#{args[:url]}'" unless args[:url].to_s.split("\n").length == 1
         | 
| 112 108 |  | 
| 113 109 | 
             
                return args
         | 
| 114 110 | 
             
              end
         | 
| 115 111 |  | 
| 116 | 
            -
              #Returns a result-object based on the arguments.
         | 
| 112 | 
            +
              # Returns a result-object based on the arguments.
         | 
| 117 113 | 
             
              #===Examples
         | 
| 118 114 | 
             
              # res = http.get("somepage.html")
         | 
| 119 115 | 
             
              # print res.body #=> <String>-object containing the HTML gotten.
         | 
| @@ -130,7 +126,7 @@ class Http2 | |
| 130 126 | 
             
                end
         | 
| 131 127 | 
             
              end
         | 
| 132 128 |  | 
| 133 | 
            -
              #Returns the default headers for a request.
         | 
| 129 | 
            +
              # Returns the default headers for a request.
         | 
| 134 130 | 
             
              #===Examples
         | 
| 135 131 | 
             
              # headers_hash = http.default_headers
         | 
| 136 132 | 
             
              # print "#{headers_hash}"
         | 
| @@ -139,15 +135,10 @@ class Http2 | |
| 139 135 |  | 
| 140 136 | 
             
                headers = {
         | 
| 141 137 | 
             
                  "Connection" => "Keep-Alive",
         | 
| 142 | 
            -
                  "User-Agent" => @uagent
         | 
| 138 | 
            +
                  "User-Agent" => @uagent,
         | 
| 139 | 
            +
                  "Host" => host_header
         | 
| 143 140 | 
             
                }
         | 
| 144 141 |  | 
| 145 | 
            -
                #Possible to give custom host-argument.
         | 
| 146 | 
            -
                host = args[:host] || self.host
         | 
| 147 | 
            -
                port = args[:port] || self.port
         | 
| 148 | 
            -
             | 
| 149 | 
            -
                headers["Host"] = "#{host}" # Copy host string to avoid changing the original string if port has been given!
         | 
| 150 | 
            -
                headers["Host"] << ":#{port}" if port && ![80, 443].include?(port.to_i) && !@args[:skip_port_in_host_header]
         | 
| 151 142 | 
             
                headers["Accept-Encoding"] = "gzip" if @args[:encoding_gzip]
         | 
| 152 143 |  | 
| 153 144 | 
             
                if @args[:basic_auth]
         | 
| @@ -155,26 +146,32 @@ class Http2 | |
| 155 146 | 
             
                  headers["Authorization"] = "Basic #{Base64.encode64("#{@args[:basic_auth][:user]}:#{@args[:basic_auth][:passwd]}").strip}"
         | 
| 156 147 | 
             
                end
         | 
| 157 148 |  | 
| 149 | 
            +
                if @args[:proxy] && @args[:proxy][:user] && @args[:proxy][:passwd] && !@connection.proxy_connect?
         | 
| 150 | 
            +
                  require "base64" unless ::Kernel.const_defined?(:Base64)
         | 
| 151 | 
            +
                  puts "Http2: Adding proxy auth header to request" if @debug
         | 
| 152 | 
            +
                  headers["Proxy-Authorization"] = "Basic #{Base64.encode64("#{@args[:proxy][:user]}:#{@args[:proxy][:passwd]}").strip}"
         | 
| 153 | 
            +
                end
         | 
| 154 | 
            +
             | 
| 158 155 | 
             
                headers.merge!(@args[:extra_headers]) if @args[:extra_headers]
         | 
| 159 156 | 
             
                headers.merge!(args[:headers]) if args[:headers]
         | 
| 160 157 | 
             
                return headers
         | 
| 161 158 | 
             
              end
         | 
| 162 159 |  | 
| 163 | 
            -
              #Posts to a certain page.
         | 
| 160 | 
            +
              # Posts to a certain page.
         | 
| 164 161 | 
             
              #===Examples
         | 
| 165 162 | 
             
              # res = http.post("login.php", {"username" => "John Doe", "password" => 123)
         | 
| 166 163 | 
             
              def post(args)
         | 
| 167 164 | 
             
                ::Http2::PostRequest.new(self, args).execute
         | 
| 168 165 | 
             
              end
         | 
| 169 166 |  | 
| 170 | 
            -
              #Posts to a certain page using the multipart-method.
         | 
| 167 | 
            +
              # Posts to a certain page using the multipart-method.
         | 
| 171 168 | 
             
              #===Examples
         | 
| 172 169 | 
             
              # res = http.post_multipart("upload.php", {"normal_value" => 123, "file" => Tempfile.new(?)})
         | 
| 173 170 | 
             
              def post_multipart(*args)
         | 
| 174 171 | 
             
                ::Http2::PostMultipartRequest.new(self, *args).execute
         | 
| 175 172 | 
             
              end
         | 
| 176 173 |  | 
| 177 | 
            -
              #Returns a header-string which normally would be used for a request in the given state.
         | 
| 174 | 
            +
              # Returns a header-string which normally would be used for a request in the given state.
         | 
| 178 175 | 
             
              def header_str(headers_hash, args = {})
         | 
| 179 176 | 
             
                headers_hash["Cookie"] = cookie_header_string
         | 
| 180 177 |  | 
| @@ -190,30 +187,33 @@ class Http2 | |
| 190 187 | 
             
                cstr = ""
         | 
| 191 188 |  | 
| 192 189 | 
             
                first = true
         | 
| 193 | 
            -
                @cookies.each do |cookie_name,  | 
| 190 | 
            +
                @cookies.each do |cookie_name, cookie|
         | 
| 194 191 | 
             
                  cstr << "; " unless first
         | 
| 195 192 | 
             
                  first = false if first
         | 
| 196 | 
            -
             | 
| 197 | 
            -
                   | 
| 198 | 
            -
                    name = cookie_data["name"]
         | 
| 199 | 
            -
                    value = cookie_data["value"]
         | 
| 200 | 
            -
                  else
         | 
| 201 | 
            -
                    name = cookie_name
         | 
| 202 | 
            -
                    value = cookie_data
         | 
| 203 | 
            -
                  end
         | 
| 204 | 
            -
             | 
| 205 | 
            -
                  raise "Unexpected lines: #{value.lines.to_a.length}." if value.lines.to_a.length != 1
         | 
| 206 | 
            -
                  cstr << "#{Http2::Utils.urlenc(name)}=#{Http2::Utils.urlenc(value)}"
         | 
| 193 | 
            +
                  ensure_single_lines([cookie.name, cookie.value])
         | 
| 194 | 
            +
                  cstr << "#{Http2::Utils.urlenc(cookie.name)}=#{Http2::Utils.urlenc(cookie.value)}"
         | 
| 207 195 | 
             
                end
         | 
| 208 196 |  | 
| 209 197 | 
             
                return cstr
         | 
| 210 198 | 
             
              end
         | 
| 211 199 |  | 
| 200 | 
            +
              def cookie(name)
         | 
| 201 | 
            +
                name = name.to_s
         | 
| 202 | 
            +
                return @cookies.fetch(name) if @cookies.key?(name)
         | 
| 203 | 
            +
                raise "No cookie by that name: '#{name}' in '#{@cookies.keys.join(", ")}'"
         | 
| 204 | 
            +
              end
         | 
| 205 | 
            +
             | 
| 206 | 
            +
              def ensure_single_lines(*strings)
         | 
| 207 | 
            +
                strings.each do |string|
         | 
| 208 | 
            +
                  raise "More than one line: #{string}." unless string.to_s.lines.to_a.length == 1
         | 
| 209 | 
            +
                end
         | 
| 210 | 
            +
              end
         | 
| 211 | 
            +
             | 
| 212 212 | 
             
              def on_content_call(args, str)
         | 
| 213 213 | 
             
                args[:on_content].call(str) if args.key?(:on_content)
         | 
| 214 214 | 
             
              end
         | 
| 215 215 |  | 
| 216 | 
            -
              #Reads the response after posting headers and data.
         | 
| 216 | 
            +
              # Reads the response after posting headers and data.
         | 
| 217 217 | 
             
              #===Examples
         | 
| 218 218 | 
             
              # res = http.read_response
         | 
| 219 219 | 
             
              def read_response(args = {})
         | 
| @@ -230,7 +230,17 @@ class Http2 | |
| 230 230 |  | 
| 231 231 | 
             
            private
         | 
| 232 232 |  | 
| 233 | 
            -
               | 
| 233 | 
            +
              def host_header
         | 
| 234 | 
            +
                #Possible to give custom host-argument.
         | 
| 235 | 
            +
                host = args[:host] || self.host
         | 
| 236 | 
            +
                port = args[:port] || self.port
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                host_header_string = "#{host}" # Copy host string to avoid changing the original string if port has been given!
         | 
| 239 | 
            +
                host_header_string << ":#{port}" if port && ![80, 443].include?(port.to_i) && !@args[:skip_port_in_host_header]
         | 
| 240 | 
            +
                return host_header_string
         | 
| 241 | 
            +
              end
         | 
| 242 | 
            +
             | 
| 243 | 
            +
              # Registers the states from a result.
         | 
| 234 244 | 
             
              def autostate_register(res)
         | 
| 235 245 | 
             
                puts "Http2: Running autostate-register on result." if @debug
         | 
| 236 246 | 
             
                @autostate_values.clear
         | 
| @@ -247,7 +257,7 @@ private | |
| 247 257 | 
             
                raise "No states could be found." if @autostate_values.empty?
         | 
| 248 258 | 
             
              end
         | 
| 249 259 |  | 
| 250 | 
            -
              #Sets the states on the given post-hash.
         | 
| 260 | 
            +
              # Sets the states on the given post-hash.
         | 
| 251 261 | 
             
              def autostate_set_on_post_hash(phash)
         | 
| 252 262 | 
             
                phash.merge!(@autostate_values)
         | 
| 253 263 | 
             
              end
         | 
| @@ -260,6 +270,8 @@ private | |
| 260 270 | 
             
                  raise "Invalid key: '#{key}'." unless VALID_ARGUMENTS_INITIALIZE.include?(key)
         | 
| 261 271 | 
             
                end
         | 
| 262 272 |  | 
| 273 | 
            +
                args[:proxy][:connect] = true if args[:proxy] && !args[:proxy].key?(:connect) && args[:ssl]
         | 
| 274 | 
            +
             | 
| 263 275 | 
             
                raise "No host was given." unless args[:host]
         | 
| 264 276 | 
             
                return args
         | 
| 265 277 | 
             
              end
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            require "spec_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Http2 do
         | 
| 4 | 
            +
              include Helpers
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              it "should parse cookies and let them be read" do
         | 
| 7 | 
            +
                with_http do |http|
         | 
| 8 | 
            +
                  res = http.get("cookie_test.rhtml")
         | 
| 9 | 
            +
                  http.cookies.length.should eq 2
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  cookie = http.cookie("TestCookie")
         | 
| 12 | 
            +
                  cookie.name.should eq "TestCookie"
         | 
| 13 | 
            +
                  cookie.value.should eq "TestValue"
         | 
| 14 | 
            +
                  cookie.path.should eq "/"
         | 
| 15 | 
            +
                  cookie.expires.should > Time.now
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,27 +1,27 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: http2
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0. | 
| 4 | 
            +
              version: 0.0.31
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Kasper Johansen
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2015- | 
| 11 | 
            +
            date: 2015-05-13 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: string-cases
         | 
| 15 15 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 16 | 
             
                requirements:
         | 
| 17 | 
            -
                - - " | 
| 17 | 
            +
                - - "~>"
         | 
| 18 18 | 
             
                  - !ruby/object:Gem::Version
         | 
| 19 19 | 
             
                    version: '0'
         | 
| 20 20 | 
             
              type: :runtime
         | 
| 21 21 | 
             
              prerelease: false
         | 
| 22 22 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 23 | 
             
                requirements:
         | 
| 24 | 
            -
                - - " | 
| 24 | 
            +
                - - "~>"
         | 
| 25 25 | 
             
                  - !ruby/object:Gem::Version
         | 
| 26 26 | 
             
                    version: '0'
         | 
| 27 27 | 
             
            - !ruby/object:Gem::Dependency
         | 
| @@ -84,14 +84,14 @@ dependencies: | |
| 84 84 | 
             
              name: hayabusa
         | 
| 85 85 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 86 86 | 
             
                requirements:
         | 
| 87 | 
            -
                - - " | 
| 87 | 
            +
                - - "~>"
         | 
| 88 88 | 
             
                  - !ruby/object:Gem::Version
         | 
| 89 89 | 
             
                    version: 0.0.25
         | 
| 90 90 | 
             
              type: :development
         | 
| 91 91 | 
             
              prerelease: false
         | 
| 92 92 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 93 93 | 
             
                requirements:
         | 
| 94 | 
            -
                - - " | 
| 94 | 
            +
                - - "~>"
         | 
| 95 95 | 
             
                  - !ruby/object:Gem::Version
         | 
| 96 96 | 
             
                    version: 0.0.25
         | 
| 97 97 | 
             
            - !ruby/object:Gem::Dependency
         | 
| @@ -135,6 +135,7 @@ files: | |
| 135 135 | 
             
            - README.md
         | 
| 136 136 | 
             
            - Rakefile
         | 
| 137 137 | 
             
            - include/connection.rb
         | 
| 138 | 
            +
            - include/cookie.rb
         | 
| 138 139 | 
             
            - include/errors.rb
         | 
| 139 140 | 
             
            - include/get_request.rb
         | 
| 140 141 | 
             
            - include/post_data_generator.rb
         | 
| @@ -146,12 +147,14 @@ files: | |
| 146 147 | 
             
            - include/utils.rb
         | 
| 147 148 | 
             
            - lib/http2.rb
         | 
| 148 149 | 
             
            - spec/helpers.rb
         | 
| 150 | 
            +
            - spec/http2/cookies_spec.rb
         | 
| 149 151 | 
             
            - spec/http2/post_data_generator_spec.rb
         | 
| 150 152 | 
             
            - spec/http2/response_spec.rb
         | 
| 151 153 | 
             
            - spec/http2/url_builder_spec.rb
         | 
| 152 154 | 
             
            - spec/http2_spec.rb
         | 
| 153 155 | 
             
            - spec/spec_helper.rb
         | 
| 154 156 | 
             
            - spec/spec_root/content_type_test.rhtml
         | 
| 157 | 
            +
            - spec/spec_root/cookie_test.rhtml
         | 
| 155 158 | 
             
            - spec/spec_root/json_test.rhtml
         | 
| 156 159 | 
             
            - spec/spec_root/multipart_test.rhtml
         | 
| 157 160 | 
             
            - spec/spec_root/redirect_test.rhtml
         | 
| @@ -175,19 +178,21 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 175 178 | 
             
                  version: '0'
         | 
| 176 179 | 
             
            requirements: []
         | 
| 177 180 | 
             
            rubyforge_project: 
         | 
| 178 | 
            -
            rubygems_version: 2. | 
| 181 | 
            +
            rubygems_version: 2.2.2
         | 
| 179 182 | 
             
            signing_key: 
         | 
| 180 183 | 
             
            specification_version: 4
         | 
| 181 184 | 
             
            summary: A lightweight framework for doing http-connections in Ruby. Supports cookies,
         | 
| 182 185 | 
             
              keep-alive, compressing and much more.
         | 
| 183 186 | 
             
            test_files:
         | 
| 184 | 
            -
            - spec/ | 
| 187 | 
            +
            - spec/helpers.rb
         | 
| 188 | 
            +
            - spec/http2/cookies_spec.rb
         | 
| 185 189 | 
             
            - spec/http2/post_data_generator_spec.rb
         | 
| 186 | 
            -
            - spec/http2/url_builder_spec.rb
         | 
| 187 190 | 
             
            - spec/http2/response_spec.rb
         | 
| 188 | 
            -
            - spec/ | 
| 191 | 
            +
            - spec/http2/url_builder_spec.rb
         | 
| 192 | 
            +
            - spec/http2_spec.rb
         | 
| 193 | 
            +
            - spec/spec_helper.rb
         | 
| 194 | 
            +
            - spec/spec_root/content_type_test.rhtml
         | 
| 195 | 
            +
            - spec/spec_root/cookie_test.rhtml
         | 
| 189 196 | 
             
            - spec/spec_root/json_test.rhtml
         | 
| 190 197 | 
             
            - spec/spec_root/multipart_test.rhtml
         | 
| 191 | 
            -
            - spec/spec_root/ | 
| 192 | 
            -
            - spec/helpers.rb
         | 
| 193 | 
            -
            - spec/spec_helper.rb
         | 
| 198 | 
            +
            - spec/spec_root/redirect_test.rhtml
         |