diff --git a/lib/puma/request.rb b/lib/puma/request.rb index 8a629bf3d9..66c9884cca 100644 --- a/lib/puma/request.rb +++ b/lib/puma/request.rb @@ -148,8 +148,9 @@ def handle_request(client, lines) res_body.each do |part| next if part.bytesize.zero? if chunked - str = part.bytesize.to_s(16) << line_ending << part << line_ending - fast_write io, str + fast_write io, (part.bytesize.to_s(16) << line_ending) + fast_write io, part # part may have different encoding + fast_write io, line_ending else fast_write io, part end diff --git a/test/test_puma_server.rb b/test/test_puma_server.rb index eb05d1c9e0..5e591171bf 100644 --- a/test/test_puma_server.rb +++ b/test/test_puma_server.rb @@ -839,6 +839,31 @@ def test_chunked_keep_alive_two_back_to_back_with_set_remote_address sock.close end + def test_chunked_encoding + enc = Encoding::UTF_16LE + str = "──иї_テスト──\n".encode enc + + server_run app: ->(env) { + hdrs = {} + hdrs['Content-Type'] = "text; charset=#{enc.to_s.downcase}" + + body = Enumerator.new do |yielder| + 100.times do |entry| + yielder << str + end + yielder << "\nHello World\n".encode(enc) + end + + [200, hdrs, body] + } + + body = Net::HTTP.start @host, @port do |http| + http.request(Net::HTTP::Get.new '/').body.force_encoding(enc) + end + assert_includes body, str + assert_equal enc, body.encoding + end + def test_empty_header_values server_run app: ->(env) { [200, {"X-Empty-Header" => ""}, []] } @@ -1180,7 +1205,6 @@ def test_custom_io_selector @server = Puma::Server.new @app, @events, {:io_selector_backend => backend} @server.run - @server.stop selector = @server.instance_variable_get(:@reactor).instance_variable_get(:@selector)