Skip to content

Commit

Permalink
Merge pull request #47336 from pedro108/fix-raw-post-for-chunked-request
Browse files Browse the repository at this point in the history
Fix request.raw_post empty bug when the Transfer-Encoding header is present
  • Loading branch information
guilleiguaran committed Feb 12, 2023
2 parents b6ecefd + c426e46 commit 097ead2
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 3 deletions.
12 changes: 9 additions & 3 deletions actionpack/lib/action_dispatch/http/request.rb
Expand Up @@ -290,6 +290,7 @@ def media_type

# Returns the content length of the request as an integer.
def content_length
return raw_post.bytesize if headers.key?("Transfer-Encoding")
super.to_i
end

Expand Down Expand Up @@ -344,9 +345,8 @@ def server_software
# work with raw requests directly.
def raw_post
unless has_header? "RAW_POST_DATA"
raw_post_body = body
set_header("RAW_POST_DATA", raw_post_body.read(content_length))
raw_post_body.rewind if raw_post_body.respond_to?(:rewind)
set_header("RAW_POST_DATA", read_body_stream)
body_stream.rewind if body_stream.respond_to?(:rewind)
end
get_header "RAW_POST_DATA"
end
Expand Down Expand Up @@ -472,6 +472,12 @@ def check_method(name)
def default_session
Session.disabled(self)
end

def read_body_stream
body_stream.rewind if body_stream.respond_to?(:rewind)
return body_stream.read if headers.key?("Transfer-Encoding") # Read body stream until EOF if "Transfer-Encoding" is present
body_stream.read(content_length)
end
end
end

Expand Down
53 changes: 53 additions & 0 deletions railties/test/railties/http_request_test.rb
@@ -0,0 +1,53 @@
# frozen_string_literal: true

require "isolation/abstract_unit"
require "stringio"
require "rack/test"
require "active_support/core_ext/module/delegation"

module RailtiesTest
class HttpRequestTest < ActiveSupport::TestCase
include ActiveSupport::Testing::Isolation
include Rack::Test::Methods

def setup
build_app

app_file "config/routes.rb", <<-RUBY
Rails.application.routes.draw do
post "posts", to: "posts#create"
end
RUBY

controller "posts", <<-RUBY
class PostsController < ApplicationController
def create
render json: {
raw_post: request.raw_post,
content_length: request.content_length
}
end
end
RUBY
end

def teardown
teardown_app
end

class TestInput < StringIO
undef_method :size
end

test "parses request raw_post correctly when request has Transfer-Encoding header without a Content-Length value" do
require "#{app_path}/config/environment"

header "Transfer-Encoding", "gzip, chunked;foo=bar"
post "/posts", TestInput.new("foo=bar") # prevents Rack::MockRequest from adding a Content-Length

json_response = JSON.parse(last_response.body)
assert_equal 7, json_response["content_length"]
assert_equal "foo=bar", json_response["raw_post"]
end
end
end

0 comments on commit 097ead2

Please sign in to comment.