Method: HTTPTools::Encoding.transfer_encoding_chunked_decode

Defined in:
lib/http_tools/encoding.rb

.transfer_encoding_chunked_decode(str, scanner = StringScanner.new(str)) ⇒ Object

:call-seq: Encoding.transfer_encoding_chunked_decode(encoded_string) -> array

Decoding a complete chunked response will return an array containing the decoded response and nil. Example:

encoded_string = "3\r\nfoo\r\n3\r\nbar\r\n0\r\n"
Encoding.transfer_encoding_chunked_decode(encoded_string)\

> [“foobar”, nil]

Decoding a partial response will return an array of the response decoded so far, and the remainder of the encoded string. Example

encoded_string = "3\r\nfoo\r\n3\r\nba"
Encoding.transfer_encoding_chunked_decode(encoded_string)\

> [“foo”, “3\r\nba”]

If the chunks are complete, but there is no empty terminating chunk, the second element in the array will be an empty string.

encoded_string = "3\r\nfoo\r\n3\r\nbar"
Encoding.transfer_encoding_chunked_decode(encoded_string)\

> [“foobar”, “”]

If nothing can be decoded the first element in the array will be an empty string and the second the remainder

encoded_string = "3\r\nfo"
Encoding.transfer_encoding_chunked_decode(encoded_string)\

> [“”, “3\r\nfo”]

Example use:

include Encoding
decoded = ""
remainder = ""
while remainder
  remainder << get_data
  chunk, remainder = transfer_encoding_chunked_decode(remainder)
  decoded << chunk if chunk
end


140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/http_tools/encoding.rb', line 140

def transfer_encoding_chunked_decode(str, scanner=StringScanner.new(str))
  decoded = ""
  
  remainder = while true
    start_pos = scanner.pos
    hex_chunk_length = scanner.scan(/[0-9a-f]+ *\r?\n/i)
    break scanner.rest unless hex_chunk_length
    
    chunk_length = hex_chunk_length.to_i(16)
    break nil if chunk_length == 0
    
    begin
      chunk = scanner.rest.slice(0, chunk_length)
      scanner.pos += chunk_length
      if chunk && scanner.skip(/\r?\n/i)
        decoded << chunk
      else
        scanner.pos = start_pos
        break scanner.rest
      end
    rescue RangeError
      scanner.pos = start_pos
      break scanner.rest
    end
  end
  
  [(decoded if decoded.length > 0), remainder]
end