Skip to content

Fix multipart forms without explicit Conent-Length header #2150

@gsamokovarov

Description

@gsamokovarov

Uploading multipart forms without setting the Content-Length header fails for Passenger on Rack 2.x releases. This is because Rack itself does not conform to it's Input Stream SPEC and calls an #eof? on an input stream in the case of no Content-Length header:

      def self.parse(io, content_length, content_type, tmpfile, bufsize, qp)
        return EMPTY if 0 == content_length

        boundary = parse_boundary content_type
        return EMPTY unless boundary

        io = BoundedIO.new(io, content_length) if content_length

        parser = new(boundary, tmpfile, bufsize, qp)
        parser.on_read io.read(bufsize), io.eof?

        loop do
          break if parser.state == :DONE
          parser.on_read io.read(bufsize), io.eof?
        end

        io.rewind
        parser.result
      end

https://github.com/rack/rack/blob/8376dd11e6526a53432ee59b7a5d092bda9fc901/lib/rack/multipart/parser.rb#L59-L77

At this point, the io is of type PhusionPassenger::Utils::TeeInput, which does not implement the #eof?method. This is pretty legit, as the Rack SPEC does not require it. However, in the case of no content length, no BoundedIO wrapping is happening, which leaves a raw call to the #eof? method of PhusionPassenger::Utils::TeeInput, which leads to:

NoMethodError: undefined method `eof?' for #<PhusionPassenger::Utils::TeeInput:0x0000563c49844cf8>

This is where it gets interesting. This problem was found out and fixed in 2017 by rack/rack#1201. The commit sat in master and wasn't ported to rack's 2-0-stable branch, where the 2.* are built from. Yesterday the rack maintainers backported the change into the 2-0-stable branch, but no release have been made yet.

While you are completely complying to the spec, it may be a good idea to put the #eof? method on the TeeInput class for the folks who cannot run on 2-0-stable or are locked to a specific rack version, but can fix the issue by updating Passenger.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions