net-http 0.1.1 → 0.4.1
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/Gemfile +2 -0
- data/README.md +1 -1
- data/Rakefile +0 -7
- data/doc/net-http/examples.rdoc +31 -0
- data/doc/net-http/included_getters.rdoc +3 -0
- data/lib/net/http/backward.rb +27 -13
- data/lib/net/http/exceptions.rb +28 -27
- data/lib/net/http/generic_request.rb +96 -21
- data/lib/net/http/header.rb +628 -163
- data/lib/net/http/proxy_delta.rb +1 -1
- data/lib/net/http/request.rb +73 -6
- data/lib/net/http/requests.rb +327 -25
- data/lib/net/http/response.rb +339 -28
- data/lib/net/http/responses.rb +1090 -223
- data/lib/net/http/status.rb +7 -6
- data/lib/net/http.rb +1458 -668
- data/lib/net/https.rb +1 -1
- data/net-http.gemspec +9 -6
- metadata +5 -20
- data/.github/workflows/test.yml +0 -24
- data/.gitignore +0 -8
- data/Gemfile.lock +0 -23
    
        data/lib/net/http/response.rb
    CHANGED
    
    | @@ -1,20 +1,136 @@ | |
| 1 | 
            -
            # frozen_string_literal:  | 
| 2 | 
            -
             | 
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # This class is the base class for \Net::HTTP response classes.
         | 
| 4 | 
            +
            #
         | 
| 5 | 
            +
            # == About the Examples
         | 
| 6 | 
            +
            #
         | 
| 7 | 
            +
            # :include: doc/net-http/examples.rdoc
         | 
| 8 | 
            +
            #
         | 
| 9 | 
            +
            # == Returned Responses
         | 
| 10 | 
            +
            #
         | 
| 11 | 
            +
            # \Method Net::HTTP.get_response returns
         | 
| 12 | 
            +
            # an instance of one of the subclasses of \Net::HTTPResponse:
         | 
| 13 | 
            +
            #
         | 
| 14 | 
            +
            #   Net::HTTP.get_response(uri)
         | 
| 15 | 
            +
            #   # => #<Net::HTTPOK 200 OK readbody=true>
         | 
| 16 | 
            +
            #   Net::HTTP.get_response(hostname, '/nosuch')
         | 
| 17 | 
            +
            #   # => #<Net::HTTPNotFound 404 Not Found readbody=true>
         | 
| 18 | 
            +
            #
         | 
| 19 | 
            +
            # As does method Net::HTTP#request:
         | 
| 20 | 
            +
            #
         | 
| 21 | 
            +
            #   req = Net::HTTP::Get.new(uri)
         | 
| 22 | 
            +
            #   Net::HTTP.start(hostname) do |http|
         | 
| 23 | 
            +
            #     http.request(req)
         | 
| 24 | 
            +
            #   end # => #<Net::HTTPOK 200 OK readbody=true>
         | 
| 25 | 
            +
            #
         | 
| 26 | 
            +
            # \Class \Net::HTTPResponse includes module Net::HTTPHeader,
         | 
| 27 | 
            +
            # which provides access to response header values via (among others):
         | 
| 28 | 
            +
            #
         | 
| 29 | 
            +
            # - \Hash-like method <tt>[]</tt>.
         | 
| 30 | 
            +
            # - Specific reader methods, such as +content_type+.
         | 
| 31 | 
            +
            #
         | 
| 32 | 
            +
            # Examples:
         | 
| 33 | 
            +
            #
         | 
| 34 | 
            +
            #   res = Net::HTTP.get_response(uri) # => #<Net::HTTPOK 200 OK readbody=true>
         | 
| 35 | 
            +
            #   res['Content-Type']               # => "text/html; charset=UTF-8"
         | 
| 36 | 
            +
            #   res.content_type                  # => "text/html"
         | 
| 37 | 
            +
            #
         | 
| 38 | 
            +
            # == Response Subclasses
         | 
| 39 | 
            +
            #
         | 
| 40 | 
            +
            # \Class \Net::HTTPResponse has a subclass for each
         | 
| 41 | 
            +
            # {HTTP status code}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes].
         | 
| 42 | 
            +
            # You can look up the response class for a given code:
         | 
| 43 | 
            +
            #
         | 
| 44 | 
            +
            #   Net::HTTPResponse::CODE_TO_OBJ['200'] # => Net::HTTPOK
         | 
| 45 | 
            +
            #   Net::HTTPResponse::CODE_TO_OBJ['400'] # => Net::HTTPBadRequest
         | 
| 46 | 
            +
            #   Net::HTTPResponse::CODE_TO_OBJ['404'] # => Net::HTTPNotFound
         | 
| 47 | 
            +
            #
         | 
| 48 | 
            +
            # And you can retrieve the status code for a response object:
         | 
| 49 | 
            +
            #
         | 
| 50 | 
            +
            #   Net::HTTP.get_response(uri).code                 # => "200"
         | 
| 51 | 
            +
            #   Net::HTTP.get_response(hostname, '/nosuch').code # => "404"
         | 
| 52 | 
            +
            #
         | 
| 53 | 
            +
            # The response subclasses (indentation shows class hierarchy):
         | 
| 54 | 
            +
            #
         | 
| 55 | 
            +
            # - Net::HTTPUnknownResponse (for unhandled \HTTP extensions).
         | 
| 3 56 | 
             
            #
         | 
| 4 | 
            -
            #  | 
| 5 | 
            -
            # entity requested).
         | 
| 57 | 
            +
            # - Net::HTTPInformation:
         | 
| 6 58 | 
             
            #
         | 
| 7 | 
            -
            #  | 
| 8 | 
            -
            # | 
| 59 | 
            +
            #   - Net::HTTPContinue (100)
         | 
| 60 | 
            +
            #   - Net::HTTPSwitchProtocol (101)
         | 
| 61 | 
            +
            #   - Net::HTTPProcessing (102)
         | 
| 62 | 
            +
            #   - Net::HTTPEarlyHints (103)
         | 
| 9 63 | 
             
            #
         | 
| 10 | 
            -
            #  | 
| 11 | 
            -
            # HTTPResponse subclass. All classes are defined under the Net module.
         | 
| 12 | 
            -
            # Indentation indicates inheritance.  For a list of the classes see Net::HTTP.
         | 
| 64 | 
            +
            # - Net::HTTPSuccess:
         | 
| 13 65 | 
             
            #
         | 
| 14 | 
            -
            #  | 
| 15 | 
            -
            #  | 
| 66 | 
            +
            #   - Net::HTTPOK (200)
         | 
| 67 | 
            +
            #   - Net::HTTPCreated (201)
         | 
| 68 | 
            +
            #   - Net::HTTPAccepted (202)
         | 
| 69 | 
            +
            #   - Net::HTTPNonAuthoritativeInformation (203)
         | 
| 70 | 
            +
            #   - Net::HTTPNoContent (204)
         | 
| 71 | 
            +
            #   - Net::HTTPResetContent (205)
         | 
| 72 | 
            +
            #   - Net::HTTPPartialContent (206)
         | 
| 73 | 
            +
            #   - Net::HTTPMultiStatus (207)
         | 
| 74 | 
            +
            #   - Net::HTTPAlreadyReported (208)
         | 
| 75 | 
            +
            #   - Net::HTTPIMUsed (226)
         | 
| 16 76 | 
             
            #
         | 
| 17 | 
            -
            # | 
| 77 | 
            +
            # - Net::HTTPRedirection:
         | 
| 78 | 
            +
            #
         | 
| 79 | 
            +
            #   - Net::HTTPMultipleChoices (300)
         | 
| 80 | 
            +
            #   - Net::HTTPMovedPermanently (301)
         | 
| 81 | 
            +
            #   - Net::HTTPFound (302)
         | 
| 82 | 
            +
            #   - Net::HTTPSeeOther (303)
         | 
| 83 | 
            +
            #   - Net::HTTPNotModified (304)
         | 
| 84 | 
            +
            #   - Net::HTTPUseProxy (305)
         | 
| 85 | 
            +
            #   - Net::HTTPTemporaryRedirect (307)
         | 
| 86 | 
            +
            #   - Net::HTTPPermanentRedirect (308)
         | 
| 87 | 
            +
            #
         | 
| 88 | 
            +
            # - Net::HTTPClientError:
         | 
| 89 | 
            +
            #
         | 
| 90 | 
            +
            #   - Net::HTTPBadRequest (400)
         | 
| 91 | 
            +
            #   - Net::HTTPUnauthorized (401)
         | 
| 92 | 
            +
            #   - Net::HTTPPaymentRequired (402)
         | 
| 93 | 
            +
            #   - Net::HTTPForbidden (403)
         | 
| 94 | 
            +
            #   - Net::HTTPNotFound (404)
         | 
| 95 | 
            +
            #   - Net::HTTPMethodNotAllowed (405)
         | 
| 96 | 
            +
            #   - Net::HTTPNotAcceptable (406)
         | 
| 97 | 
            +
            #   - Net::HTTPProxyAuthenticationRequired (407)
         | 
| 98 | 
            +
            #   - Net::HTTPRequestTimeOut (408)
         | 
| 99 | 
            +
            #   - Net::HTTPConflict (409)
         | 
| 100 | 
            +
            #   - Net::HTTPGone (410)
         | 
| 101 | 
            +
            #   - Net::HTTPLengthRequired (411)
         | 
| 102 | 
            +
            #   - Net::HTTPPreconditionFailed (412)
         | 
| 103 | 
            +
            #   - Net::HTTPRequestEntityTooLarge (413)
         | 
| 104 | 
            +
            #   - Net::HTTPRequestURITooLong (414)
         | 
| 105 | 
            +
            #   - Net::HTTPUnsupportedMediaType (415)
         | 
| 106 | 
            +
            #   - Net::HTTPRequestedRangeNotSatisfiable (416)
         | 
| 107 | 
            +
            #   - Net::HTTPExpectationFailed (417)
         | 
| 108 | 
            +
            #   - Net::HTTPMisdirectedRequest (421)
         | 
| 109 | 
            +
            #   - Net::HTTPUnprocessableEntity (422)
         | 
| 110 | 
            +
            #   - Net::HTTPLocked (423)
         | 
| 111 | 
            +
            #   - Net::HTTPFailedDependency (424)
         | 
| 112 | 
            +
            #   - Net::HTTPUpgradeRequired (426)
         | 
| 113 | 
            +
            #   - Net::HTTPPreconditionRequired (428)
         | 
| 114 | 
            +
            #   - Net::HTTPTooManyRequests (429)
         | 
| 115 | 
            +
            #   - Net::HTTPRequestHeaderFieldsTooLarge (431)
         | 
| 116 | 
            +
            #   - Net::HTTPUnavailableForLegalReasons (451)
         | 
| 117 | 
            +
            #
         | 
| 118 | 
            +
            # - Net::HTTPServerError:
         | 
| 119 | 
            +
            #
         | 
| 120 | 
            +
            #   - Net::HTTPInternalServerError (500)
         | 
| 121 | 
            +
            #   - Net::HTTPNotImplemented (501)
         | 
| 122 | 
            +
            #   - Net::HTTPBadGateway (502)
         | 
| 123 | 
            +
            #   - Net::HTTPServiceUnavailable (503)
         | 
| 124 | 
            +
            #   - Net::HTTPGatewayTimeOut (504)
         | 
| 125 | 
            +
            #   - Net::HTTPVersionNotSupported (505)
         | 
| 126 | 
            +
            #   - Net::HTTPVariantAlsoNegotiates (506)
         | 
| 127 | 
            +
            #   - Net::HTTPInsufficientStorage (507)
         | 
| 128 | 
            +
            #   - Net::HTTPLoopDetected (508)
         | 
| 129 | 
            +
            #   - Net::HTTPNotExtended (510)
         | 
| 130 | 
            +
            #   - Net::HTTPNetworkAuthenticationRequired (511)
         | 
| 131 | 
            +
            #
         | 
| 132 | 
            +
            # There is also the Net::HTTPBadResponse exception which is raised when
         | 
| 133 | 
            +
            # there is a protocol error.
         | 
| 18 134 | 
             
            #
         | 
| 19 135 | 
             
            class Net::HTTPResponse
         | 
| 20 136 | 
             
              class << self
         | 
| @@ -84,6 +200,8 @@ class Net::HTTPResponse | |
| 84 200 | 
             
                @read = false
         | 
| 85 201 | 
             
                @uri  = nil
         | 
| 86 202 | 
             
                @decode_content = false
         | 
| 203 | 
            +
                @body_encoding = false
         | 
| 204 | 
            +
                @ignore_eof = true
         | 
| 87 205 | 
             
              end
         | 
| 88 206 |  | 
| 89 207 | 
             
              # The HTTP version supported by the server.
         | 
| @@ -106,6 +224,41 @@ class Net::HTTPResponse | |
| 106 224 | 
             
              # Accept-Encoding header from the user.
         | 
| 107 225 | 
             
              attr_accessor :decode_content
         | 
| 108 226 |  | 
| 227 | 
            +
              # Returns the value set by body_encoding=, or +false+ if none;
         | 
| 228 | 
            +
              # see #body_encoding=.
         | 
| 229 | 
            +
              attr_reader :body_encoding
         | 
| 230 | 
            +
             | 
| 231 | 
            +
              # Sets the encoding that should be used when reading the body:
         | 
| 232 | 
            +
              #
         | 
| 233 | 
            +
              # - If the given value is an Encoding object, that encoding will be used.
         | 
| 234 | 
            +
              # - Otherwise if the value is a string, the value of
         | 
| 235 | 
            +
              #   {Encoding#find(value)}[https://docs.ruby-lang.org/en/master/Encoding.html#method-c-find]
         | 
| 236 | 
            +
              #   will be used.
         | 
| 237 | 
            +
              # - Otherwise an encoding will be deduced from the body itself.
         | 
| 238 | 
            +
              #
         | 
| 239 | 
            +
              # Examples:
         | 
| 240 | 
            +
              #
         | 
| 241 | 
            +
              #   http = Net::HTTP.new(hostname)
         | 
| 242 | 
            +
              #   req = Net::HTTP::Get.new('/')
         | 
| 243 | 
            +
              #
         | 
| 244 | 
            +
              #   http.request(req) do |res|
         | 
| 245 | 
            +
              #     p res.body.encoding # => #<Encoding:ASCII-8BIT>
         | 
| 246 | 
            +
              #   end
         | 
| 247 | 
            +
              #
         | 
| 248 | 
            +
              #   http.request(req) do |res|
         | 
| 249 | 
            +
              #     res.body_encoding = "UTF-8"
         | 
| 250 | 
            +
              #     p res.body.encoding # => #<Encoding:UTF-8>
         | 
| 251 | 
            +
              #   end
         | 
| 252 | 
            +
              #
         | 
| 253 | 
            +
              def body_encoding=(value)
         | 
| 254 | 
            +
                value = Encoding.find(value) if value.is_a?(String)
         | 
| 255 | 
            +
                @body_encoding = value
         | 
| 256 | 
            +
              end
         | 
| 257 | 
            +
             | 
| 258 | 
            +
              # Whether to ignore EOF when reading bodies with a specified Content-Length
         | 
| 259 | 
            +
              # header.
         | 
| 260 | 
            +
              attr_accessor :ignore_eof
         | 
| 261 | 
            +
             | 
| 109 262 | 
             
              def inspect
         | 
| 110 263 | 
             
                "#<#{self.class} #{@code} #{@message} readbody=#{@read}>"
         | 
| 111 264 | 
             
              end
         | 
| @@ -120,7 +273,7 @@ class Net::HTTPResponse | |
| 120 273 |  | 
| 121 274 | 
             
              def error!   #:nodoc:
         | 
| 122 275 | 
             
                message = @code
         | 
| 123 | 
            -
                message  | 
| 276 | 
            +
                message = "#{message} #{@message.dump}" if @message
         | 
| 124 277 | 
             
                raise error_type().new(message, self)
         | 
| 125 278 | 
             
              end
         | 
| 126 279 |  | 
| @@ -213,30 +366,42 @@ class Net::HTTPResponse | |
| 213 366 | 
             
                  @body = nil
         | 
| 214 367 | 
             
                end
         | 
| 215 368 | 
             
                @read = true
         | 
| 369 | 
            +
                return if @body.nil?
         | 
| 370 | 
            +
             | 
| 371 | 
            +
                case enc = @body_encoding
         | 
| 372 | 
            +
                when Encoding, false, nil
         | 
| 373 | 
            +
                  # Encoding: force given encoding
         | 
| 374 | 
            +
                  # false/nil: do not force encoding
         | 
| 375 | 
            +
                else
         | 
| 376 | 
            +
                  # other value: detect encoding from body
         | 
| 377 | 
            +
                  enc = detect_encoding(@body)
         | 
| 378 | 
            +
                end
         | 
| 379 | 
            +
             | 
| 380 | 
            +
                @body.force_encoding(enc) if enc
         | 
| 216 381 |  | 
| 217 382 | 
             
                @body
         | 
| 218 383 | 
             
              end
         | 
| 219 384 |  | 
| 220 | 
            -
              # Returns the  | 
| 385 | 
            +
              # Returns the string response body;
         | 
| 386 | 
            +
              # note that repeated calls for the unmodified body return a cached string:
         | 
| 221 387 | 
             
              #
         | 
| 222 | 
            -
              #  | 
| 223 | 
            -
              #  | 
| 388 | 
            +
              #   path = '/todos/1'
         | 
| 389 | 
            +
              #   Net::HTTP.start(hostname) do |http|
         | 
| 390 | 
            +
              #     res = http.get(path)
         | 
| 391 | 
            +
              #     p res.body
         | 
| 392 | 
            +
              #     p http.head(path).body # No body.
         | 
| 393 | 
            +
              #   end
         | 
| 224 394 | 
             
              #
         | 
| 225 | 
            -
              # | 
| 226 | 
            -
              #     puts res.body
         | 
| 227 | 
            -
              #   }
         | 
| 395 | 
            +
              # Output:
         | 
| 228 396 | 
             
              #
         | 
| 229 | 
            -
              #    | 
| 230 | 
            -
              # | 
| 231 | 
            -
              #     p res.body.object_id   # 538149362
         | 
| 232 | 
            -
              #   }
         | 
| 397 | 
            +
              #   "{\n  \"userId\": 1,\n  \"id\": 1,\n  \"title\": \"delectus aut autem\",\n  \"completed\": false\n}"
         | 
| 398 | 
            +
              #   nil
         | 
| 233 399 | 
             
              #
         | 
| 234 400 | 
             
              def body
         | 
| 235 401 | 
             
                read_body()
         | 
| 236 402 | 
             
              end
         | 
| 237 403 |  | 
| 238 | 
            -
              #  | 
| 239 | 
            -
              # this method facilitates that.
         | 
| 404 | 
            +
              # Sets the body of the response to the given value.
         | 
| 240 405 | 
             
              def body=(value)
         | 
| 241 406 | 
             
                @body = value
         | 
| 242 407 | 
             
              end
         | 
| @@ -245,6 +410,141 @@ class Net::HTTPResponse | |
| 245 410 |  | 
| 246 411 | 
             
              private
         | 
| 247 412 |  | 
| 413 | 
            +
              # :nodoc:
         | 
| 414 | 
            +
              def detect_encoding(str, encoding=nil)
         | 
| 415 | 
            +
                if encoding
         | 
| 416 | 
            +
                elsif encoding = type_params['charset']
         | 
| 417 | 
            +
                elsif encoding = check_bom(str)
         | 
| 418 | 
            +
                else
         | 
| 419 | 
            +
                  encoding = case content_type&.downcase
         | 
| 420 | 
            +
                  when %r{text/x(?:ht)?ml|application/(?:[^+]+\+)?xml}
         | 
| 421 | 
            +
                    /\A<xml[ \t\r\n]+
         | 
| 422 | 
            +
                      version[ \t\r\n]*=[ \t\r\n]*(?:"[0-9.]+"|'[0-9.]*')[ \t\r\n]+
         | 
| 423 | 
            +
                      encoding[ \t\r\n]*=[ \t\r\n]*
         | 
| 424 | 
            +
                      (?:"([A-Za-z][\-A-Za-z0-9._]*)"|'([A-Za-z][\-A-Za-z0-9._]*)')/x =~ str
         | 
| 425 | 
            +
                    encoding = $1 || $2 || Encoding::UTF_8
         | 
| 426 | 
            +
                  when %r{text/html.*}
         | 
| 427 | 
            +
                    sniff_encoding(str)
         | 
| 428 | 
            +
                  end
         | 
| 429 | 
            +
                end
         | 
| 430 | 
            +
                return encoding
         | 
| 431 | 
            +
              end
         | 
| 432 | 
            +
             | 
| 433 | 
            +
              # :nodoc:
         | 
| 434 | 
            +
              def sniff_encoding(str, encoding=nil)
         | 
| 435 | 
            +
                # the encoding sniffing algorithm
         | 
| 436 | 
            +
                # http://www.w3.org/TR/html5/parsing.html#determining-the-character-encoding
         | 
| 437 | 
            +
                if enc = scanning_meta(str)
         | 
| 438 | 
            +
                  enc
         | 
| 439 | 
            +
                # 6. last visited page or something
         | 
| 440 | 
            +
                # 7. frequency
         | 
| 441 | 
            +
                elsif str.ascii_only?
         | 
| 442 | 
            +
                  Encoding::US_ASCII
         | 
| 443 | 
            +
                elsif str.dup.force_encoding(Encoding::UTF_8).valid_encoding?
         | 
| 444 | 
            +
                  Encoding::UTF_8
         | 
| 445 | 
            +
                end
         | 
| 446 | 
            +
                # 8. implementation-defined or user-specified
         | 
| 447 | 
            +
              end
         | 
| 448 | 
            +
             | 
| 449 | 
            +
              # :nodoc:
         | 
| 450 | 
            +
              def check_bom(str)
         | 
| 451 | 
            +
                case str.byteslice(0, 2)
         | 
| 452 | 
            +
                when "\xFE\xFF"
         | 
| 453 | 
            +
                  return Encoding::UTF_16BE
         | 
| 454 | 
            +
                when "\xFF\xFE"
         | 
| 455 | 
            +
                  return Encoding::UTF_16LE
         | 
| 456 | 
            +
                end
         | 
| 457 | 
            +
                if "\xEF\xBB\xBF" == str.byteslice(0, 3)
         | 
| 458 | 
            +
                  return Encoding::UTF_8
         | 
| 459 | 
            +
                end
         | 
| 460 | 
            +
                nil
         | 
| 461 | 
            +
              end
         | 
| 462 | 
            +
             | 
| 463 | 
            +
              # :nodoc:
         | 
| 464 | 
            +
              def scanning_meta(str)
         | 
| 465 | 
            +
                require 'strscan'
         | 
| 466 | 
            +
                ss = StringScanner.new(str)
         | 
| 467 | 
            +
                if ss.scan_until(/<meta[\t\n\f\r ]*/)
         | 
| 468 | 
            +
                  attrs = {} # attribute_list
         | 
| 469 | 
            +
                  got_pragma = false
         | 
| 470 | 
            +
                  need_pragma = nil
         | 
| 471 | 
            +
                  charset = nil
         | 
| 472 | 
            +
             | 
| 473 | 
            +
                  # step: Attributes
         | 
| 474 | 
            +
                  while attr = get_attribute(ss)
         | 
| 475 | 
            +
                    name, value = *attr
         | 
| 476 | 
            +
                    next if attrs[name]
         | 
| 477 | 
            +
                    attrs[name] = true
         | 
| 478 | 
            +
                    case name
         | 
| 479 | 
            +
                    when 'http-equiv'
         | 
| 480 | 
            +
                      got_pragma = true if value == 'content-type'
         | 
| 481 | 
            +
                    when 'content'
         | 
| 482 | 
            +
                      encoding = extracting_encodings_from_meta_elements(value)
         | 
| 483 | 
            +
                      unless charset
         | 
| 484 | 
            +
                        charset = encoding
         | 
| 485 | 
            +
                      end
         | 
| 486 | 
            +
                      need_pragma = true
         | 
| 487 | 
            +
                    when 'charset'
         | 
| 488 | 
            +
                      need_pragma = false
         | 
| 489 | 
            +
                      charset = value
         | 
| 490 | 
            +
                    end
         | 
| 491 | 
            +
                  end
         | 
| 492 | 
            +
             | 
| 493 | 
            +
                  # step: Processing
         | 
| 494 | 
            +
                  return if need_pragma.nil?
         | 
| 495 | 
            +
                  return if need_pragma && !got_pragma
         | 
| 496 | 
            +
             | 
| 497 | 
            +
                  charset = Encoding.find(charset) rescue nil
         | 
| 498 | 
            +
                  return unless charset
         | 
| 499 | 
            +
                  charset = Encoding::UTF_8 if charset == Encoding::UTF_16
         | 
| 500 | 
            +
                  return charset # tentative
         | 
| 501 | 
            +
                end
         | 
| 502 | 
            +
                nil
         | 
| 503 | 
            +
              end
         | 
| 504 | 
            +
             | 
| 505 | 
            +
              def get_attribute(ss)
         | 
| 506 | 
            +
                ss.scan(/[\t\n\f\r \/]*/)
         | 
| 507 | 
            +
                if ss.peek(1) == '>'
         | 
| 508 | 
            +
                  ss.getch
         | 
| 509 | 
            +
                  return nil
         | 
| 510 | 
            +
                end
         | 
| 511 | 
            +
                name = ss.scan(/[^=\t\n\f\r \/>]*/)
         | 
| 512 | 
            +
                name.downcase!
         | 
| 513 | 
            +
                raise if name.empty?
         | 
| 514 | 
            +
                ss.skip(/[\t\n\f\r ]*/)
         | 
| 515 | 
            +
                if ss.getch != '='
         | 
| 516 | 
            +
                  value = ''
         | 
| 517 | 
            +
                  return [name, value]
         | 
| 518 | 
            +
                end
         | 
| 519 | 
            +
                ss.skip(/[\t\n\f\r ]*/)
         | 
| 520 | 
            +
                case ss.peek(1)
         | 
| 521 | 
            +
                when '"'
         | 
| 522 | 
            +
                  ss.getch
         | 
| 523 | 
            +
                  value = ss.scan(/[^"]+/)
         | 
| 524 | 
            +
                  value.downcase!
         | 
| 525 | 
            +
                  ss.getch
         | 
| 526 | 
            +
                when "'"
         | 
| 527 | 
            +
                  ss.getch
         | 
| 528 | 
            +
                  value = ss.scan(/[^']+/)
         | 
| 529 | 
            +
                  value.downcase!
         | 
| 530 | 
            +
                  ss.getch
         | 
| 531 | 
            +
                when '>'
         | 
| 532 | 
            +
                  value = ''
         | 
| 533 | 
            +
                else
         | 
| 534 | 
            +
                  value = ss.scan(/[^\t\n\f\r >]+/)
         | 
| 535 | 
            +
                  value.downcase!
         | 
| 536 | 
            +
                end
         | 
| 537 | 
            +
                [name, value]
         | 
| 538 | 
            +
              end
         | 
| 539 | 
            +
             | 
| 540 | 
            +
              def extracting_encodings_from_meta_elements(value)
         | 
| 541 | 
            +
                # http://dev.w3.org/html5/spec/fetching-resources.html#algorithm-for-extracting-an-encoding-from-a-meta-element
         | 
| 542 | 
            +
                if /charset[\t\n\f\r ]*=(?:"([^"]*)"|'([^']*)'|["']|\z|([^\t\n\f\r ;]+))/i =~ value
         | 
| 543 | 
            +
                  return $1 || $2 || $3
         | 
| 544 | 
            +
                end
         | 
| 545 | 
            +
                return nil
         | 
| 546 | 
            +
              end
         | 
| 547 | 
            +
             | 
| 248 548 | 
             
              ##
         | 
| 249 549 | 
             
              # Checks for a supported Content-Encoding header and yields an Inflate
         | 
| 250 550 | 
             
              # wrapper for this response's socket when zlib is present.  If the
         | 
| @@ -272,6 +572,9 @@ class Net::HTTPResponse | |
| 272 572 | 
             
                  ensure
         | 
| 273 573 | 
             
                    begin
         | 
| 274 574 | 
             
                      inflate_body_io.finish
         | 
| 575 | 
            +
                      if self['content-length']
         | 
| 576 | 
            +
                        self['content-length'] = inflate_body_io.bytes_inflated.to_s
         | 
| 577 | 
            +
                      end
         | 
| 275 578 | 
             
                    rescue => err
         | 
| 276 579 | 
             
                      # Ignore #finish's error if there is an exception from yield
         | 
| 277 580 | 
             
                      raise err if success
         | 
| @@ -297,7 +600,7 @@ class Net::HTTPResponse | |
| 297 600 |  | 
| 298 601 | 
             
                  clen = content_length()
         | 
| 299 602 | 
             
                  if clen
         | 
| 300 | 
            -
                    @socket.read clen, dest,  | 
| 603 | 
            +
                    @socket.read clen, dest, @ignore_eof
         | 
| 301 604 | 
             
                    return
         | 
| 302 605 | 
             
                  end
         | 
| 303 606 | 
             
                  clen = range_length()
         | 
| @@ -337,7 +640,7 @@ class Net::HTTPResponse | |
| 337 640 | 
             
              end
         | 
| 338 641 |  | 
| 339 642 | 
             
              def stream_check
         | 
| 340 | 
            -
                raise IOError, 'attempt to read body out of block' if @socket.closed?
         | 
| 643 | 
            +
                raise IOError, 'attempt to read body out of block' if @socket.nil? || @socket.closed?
         | 
| 341 644 | 
             
              end
         | 
| 342 645 |  | 
| 343 646 | 
             
              def procdest(dest, block)
         | 
| @@ -346,7 +649,7 @@ class Net::HTTPResponse | |
| 346 649 | 
             
                if block
         | 
| 347 650 | 
             
                  Net::ReadAdapter.new(block)
         | 
| 348 651 | 
             
                else
         | 
| 349 | 
            -
                  dest || ''
         | 
| 652 | 
            +
                  dest || +''
         | 
| 350 653 | 
             
                end
         | 
| 351 654 | 
             
              end
         | 
| 352 655 |  | 
| @@ -373,6 +676,14 @@ class Net::HTTPResponse | |
| 373 676 | 
             
                  @inflate.finish
         | 
| 374 677 | 
             
                end
         | 
| 375 678 |  | 
| 679 | 
            +
                ##
         | 
| 680 | 
            +
                # The number of bytes inflated, used to update the Content-Length of
         | 
| 681 | 
            +
                # the response.
         | 
| 682 | 
            +
             | 
| 683 | 
            +
                def bytes_inflated
         | 
| 684 | 
            +
                  @inflate.total_out
         | 
| 685 | 
            +
                end
         | 
| 686 | 
            +
             | 
| 376 687 | 
             
                ##
         | 
| 377 688 | 
             
                # Returns a Net::ReadAdapter that inflates each read chunk into +dest+.
         | 
| 378 689 | 
             
                #
         |