Skip to content

Commit

Permalink
Remove rewindable rack.input from SPEC
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremyevans authored and ioquatix committed Feb 12, 2022
1 parent a61c0b4 commit 42aff22
Show file tree
Hide file tree
Showing 10 changed files with 9 additions and 88 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ All notable changes to this project will be documented in this file. For info on

- Do not use semicolon as GET parameter separator. ([#1733](https://github.com/rack/rack/pull/1733), [@jeremyevans](https://github.com/jeremyevans))

### SPEC Changes

- rack.input is no longer required to be rewindable.

### Removed

- Remove `rack.multithread`/`rack.multiprocess`/`rack.run_once`. These variables generally come too late to be useful. ([#1720](https://github.com/rack/rack/pull/1720), [@ioquatix](https://github.com/ioquatix), [@jeremyevans](https://github.com/jeremyevans)))
Expand Down
7 changes: 1 addition & 6 deletions SPEC.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ The input stream is an IO-like object which contains the raw HTTP
POST data.
When applicable, its external encoding must be "ASCII-8BIT" and it
must be opened in binary mode, for Ruby 1.9 compatibility.
The input stream must respond to +gets+, +each+, +read+ and +rewind+.
The input stream must respond to +gets+, +each+, and +read+.
* +gets+ must be called without arguments and return a string,
or +nil+ on EOF.
* +read+ behaves like IO#read.
Expand All @@ -165,11 +165,6 @@ The input stream must respond to +gets+, +each+, +read+ and +rewind+.
If +buffer+ is given, then the read data will be placed
into +buffer+ instead of a newly created String object.
* +each+ must be called without arguments and only yield Strings.
* +rewind+ must be called without arguments. It rewinds the input
stream back to the beginning. It must not raise Errno::ESPIPE:
that is, it may not be a pipe or a socket. Therefore, handler
developers must buffer the input data into some rewindable object
if the underlying input stream is not rewindable.
* +close+ must never be called on the input stream.

=== The Error Stream
Expand Down
2 changes: 1 addition & 1 deletion lib/rack/handler/cgi.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def self.serve(app)

env.update(
RACK_VERSION => Rack::VERSION,
RACK_INPUT => Rack::RewindableInput.new($stdin),
RACK_INPUT => $stdin,
RACK_ERRORS => $stderr,
RACK_URL_SCHEME => ["yes", "on", "1"].include?(ENV[HTTPS]) ? "https" : "http"
)
Expand Down
19 changes: 2 additions & 17 deletions lib/rack/lint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,8 @@ def check_input(input)
raise LintError, "rack.input #{input} is not opened in binary mode"
end

## The input stream must respond to +gets+, +each+, +read+ and +rewind+.
[:gets, :each, :read, :rewind].each { |method|
## The input stream must respond to +gets+, +each+, and +read+.
[:gets, :each, :read].each { |method|
unless input.respond_to? method
raise LintError, "rack.input #{input} does not respond to ##{method}"
end
Expand Down Expand Up @@ -460,21 +460,6 @@ def each(*args)
}
end

## * +rewind+ must be called without arguments. It rewinds the input
## stream back to the beginning. It must not raise Errno::ESPIPE:
## that is, it may not be a pipe or a socket. Therefore, handler
## developers must buffer the input data into some rewindable object
## if the underlying input stream is not rewindable.
def rewind(*args)
raise LintError, "rack.input#rewind called with arguments" unless args.size == 0
begin
@input.rewind
true
rescue Errno::ESPIPE
raise LintError, "rack.input#rewind raised Errno::ESPIPE"
end
end

## * +close+ must never be called on the input stream.
def close(*args)
raise LintError, "rack.input#close must not be called"
Expand Down
1 change: 0 additions & 1 deletion lib/rack/multipart.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ def parse_multipart(env, params = Rack::Utils.default_query_parser)

def extract_multipart(req, params = Rack::Utils.default_query_parser)
io = req.get_header(RACK_INPUT)
io.rewind
content_length = req.content_length
content_length = content_length.to_i if content_length

Expand Down
5 changes: 0 additions & 5 deletions lib/rack/multipart/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@ def read(size, outbuf = nil)

str
end

def rewind
@io.rewind
end
end

MultipartInfo = Struct.new :params, :tmp_files
Expand All @@ -77,7 +73,6 @@ def self.parse(io, content_length, content_type, tmpfile, bufsize, qp)
parser = new(boundary, tmpfile, bufsize, qp)
parser.parse(io)

io.rewind
parser.result
end

Expand Down
2 changes: 0 additions & 2 deletions lib/rack/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -468,8 +468,6 @@ def POST

set_header RACK_REQUEST_FORM_VARS, form_vars
set_header RACK_REQUEST_FORM_HASH, parse_query(form_vars, '&')

get_header(RACK_INPUT).rewind
end
set_header RACK_REQUEST_FORM_INPUT, get_header(RACK_INPUT)
get_header RACK_REQUEST_FORM_HASH
Expand Down
35 changes: 0 additions & 35 deletions test/spec_lint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -569,14 +569,6 @@ def input.each; 10.times {yield 'foo'}; end
}.must_raise(Rack::Lint::LintError).
message.must_match(/read called with non-String buffer/)

lambda {
Rack::Lint.new(lambda { |env|
env["rack.input"].rewind(0)
[201, { "Content-type" => "text/plain", "Content-length" => "0" }, []]
}).call(env({}))
}.must_raise(Rack::Lint::LintError).
message.must_match(/rewind called with arguments/)

weirdio = Object.new
class << weirdio
def gets
Expand All @@ -591,10 +583,6 @@ def each
yield 23
yield 42
end

def rewind
raise Errno::ESPIPE, "Errno::ESPIPE"
end
end

eof_weirdio = Object.new
Expand All @@ -609,9 +597,6 @@ def read(*args)

def each
end

def rewind
end
end

lambda {
Expand Down Expand Up @@ -646,15 +631,6 @@ def rewind
}.must_raise(Rack::Lint::LintError).
message.must_match(/read\(nil\) returned nil on EOF/)

lambda {
Rack::Lint.new(lambda { |env|
env["rack.input"].rewind
[201, { "Content-type" => "text/plain", "Content-length" => "0" }, []]
}).call(env("rack.input" => weirdio))
}.must_raise(Rack::Lint::LintError).
message.must_match(/rewind raised Errno::ESPIPE/)


lambda {
Rack::Lint.new(lambda { |env|
env["rack.input"].close
Expand Down Expand Up @@ -737,14 +713,3 @@ def assert_lint(*args)
end

end

describe "Rack::Lint::Wrapper::InputWrapper" do
it "delegate :rewind to underlying IO object" do
io = StringIO.new("123")
wrapper = Rack::Lint::Wrapper::InputWrapper.new(io)
wrapper.read.must_equal "123"
wrapper.read.must_equal ""
wrapper.rewind
wrapper.read.must_equal "123"
end
end
11 changes: 1 addition & 10 deletions test/spec_multipart.rb
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ def rd.rewind; end
data.write("-" * (1024 * 1024))
data.write("\r\n")
data.write("--#{boundary}--\r\n")
data.rewind

fixture = {
"CONTENT_TYPE" => "multipart/form-data; boundary=#{boundary}",
Expand Down Expand Up @@ -509,16 +510,6 @@ def initialize(*)
files[:tempfile].read.must_equal "contents"
end

it "rewinds input after parsing upload" do
options = multipart_fixture(:text)
input = options[:input]
env = Rack::MockRequest.env_for("/", options)
params = Rack::Multipart.parse_multipart(env)
params["submit-name"].must_equal "Larry"
params["files"][:filename].must_equal "file1.txt"
input.read.length.must_equal 307
end

it "builds multipart body" do
files = Rack::Multipart::UploadedFile.new(multipart_file("file1.txt"))
data = Rack::Multipart.build_multipart("submit-name" => "Larry", "files" => files)
Expand Down
11 changes: 0 additions & 11 deletions test/spec_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -454,17 +454,6 @@ def initialize(*)
"CONTENT_TYPE" => 'application/x-www-form-urlencoded',
:input => "foo=bar&quux=bla")
req.POST.must_equal "foo" => "bar", "quux" => "bla"
req.body.read.must_equal "foo=bar&quux=bla"
end

it "rewind input after parsing POST data" do
input = StringIO.new("foo=bar&quux=bla")
req = make_request \
Rack::MockRequest.env_for("/",
"CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar',
:input => input)
req.params.must_equal "foo" => "bar", "quux" => "bla"
input.read.must_equal "foo=bar&quux=bla"
end

it "safely accepts POST requests with empty body" do
Expand Down

0 comments on commit 42aff22

Please sign in to comment.