rack-devel archive mirror (unofficial) https://groups.google.com/group/rack-devel
 help / color / mirror / Atom feed
* Does Rack-servers block until the whole request body has been read?
@ 2011-04-13  7:17 Daniel Abrahamsson
  2011-04-25 14:26 ` Joshua Ballanco
  2011-04-26  1:16 ` Eric Wong
  0 siblings, 2 replies; 3+ messages in thread
From: Daniel Abrahamsson @ 2011-04-13  7:17 UTC (permalink / raw)
  To: rack-devel

[-- Attachment #1: Type: text/plain, Size: 997 bytes --]

Hi,

I am working on a server that deals with large file uploads (currently built 
upon Rails, with a Metal taking care of the uploads). According to the 
rack-specification:
"... handler developers must buffer the input data into some rewindable 
object if the underlying input stream is not rewindable".

For Passenger and Mongrel, this means a temp file is created for the request 
(at least for requests as big as those I am dealing with).

Now, my question is, does Rack wait until all data from the client has been 
read to a tempfile before passing on control to the Rack app (in this case, 
Rails)? Or does it pass on control directly, and block if the application 
reads data faster than the client is sending it?

After some initial testing, it appears to me that the former is the case. 
Can anyone give me advice on how to test this? Perhaps it depends on the web 
server used? Perhaps on the framework?

Thank you in advance for any advance or clarification on this matter.

//Daniel

[-- Attachment #2: Type: text/html, Size: 1030 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Does Rack-servers block until the whole request body has been read?
  2011-04-13  7:17 Does Rack-servers block until the whole request body has been read? Daniel Abrahamsson
@ 2011-04-25 14:26 ` Joshua Ballanco
  2011-04-26  1:16 ` Eric Wong
  1 sibling, 0 replies; 3+ messages in thread
From: Joshua Ballanco @ 2011-04-25 14:26 UTC (permalink / raw)
  To: rack-devel

[-- Attachment #1: Type: text/plain, Size: 1755 bytes --]

Hi Daniel,

I faced this same issue when writing ControlTower. When a request gets
handed off to the application does depend on the server in question. Mongrel
waits for the entire body to be received first (even though it uses a
tempfile). Passenger, on the other hand, does not wait (at least, it didn't
the last time I tested it). Passenger also does not directly use a tempfile,
but rather a custom request body class. If you wanted to test directly, have
a look at Net::HTTP using body_stream (there seems to be some info you might
use here:
http://stackoverflow.com/questions/213613/buffered-multipart-form-posts-in-ruby
).

Cheers,

Josh

On Wed, Apr 13, 2011 at 3:17 AM, Daniel Abrahamsson <hamsson@gmail.com>wrote:

> Hi,
>
> I am working on a server that deals with large file uploads (currently
> built upon Rails, with a Metal taking care of the uploads). According to the
> rack-specification:
> "... handler developers must buffer the input data into some rewindable
> object if the underlying input stream is not rewindable".
>
> For Passenger and Mongrel, this means a temp file is created for the
> request (at least for requests as big as those I am dealing with).
>
> Now, my question is, does Rack wait until all data from the client has been
> read to a tempfile before passing on control to the Rack app (in this case,
> Rails)? Or does it pass on control directly, and block if the application
> reads data faster than the client is sending it?
>
> After some initial testing, it appears to me that the former is the case.
> Can anyone give me advice on how to test this? Perhaps it depends on the web
> server used? Perhaps on the framework?
>
> Thank you in advance for any advance or clarification on this matter.
>
> //Daniel
>

[-- Attachment #2: Type: text/html, Size: 2206 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Does Rack-servers block until the whole request body has been read?
  2011-04-13  7:17 Does Rack-servers block until the whole request body has been read? Daniel Abrahamsson
  2011-04-25 14:26 ` Joshua Ballanco
@ 2011-04-26  1:16 ` Eric Wong
  1 sibling, 0 replies; 3+ messages in thread
From: Eric Wong @ 2011-04-26  1:16 UTC (permalink / raw)
  To: rack-devel

Daniel Abrahamsson <hamsson@gmail.com> wrote:
> I am working on a server that deals with large file uploads (currently built 
> upon Rails, with a Metal taking care of the uploads). According to the 
> rack-specification:
> "... handler developers must buffer the input data into some rewindable 
> object if the underlying input stream is not rewindable".

The current Rack spec requires rewindability, but I think the
requirement will go away for Rack 2.0

> For Passenger and Mongrel, this means a temp file is created for the request 
> (at least for requests as big as those I am dealing with).
> 
> Now, my question is, does Rack wait until all data from the client has been 
> read to a tempfile before passing on control to the Rack app (in this case, 
> Rails)? Or does it pass on control directly, and block if the application 
> reads data faster than the client is sending it?

It depends on the Rack webserver.  I can confirm Mongrel waits
until everthing is sent.


Disclaimer: I'm the BFDL for both Unicorn and Rainbows!

Both Unicorn[1] and Rainbows![3] can pass control directly and
block inside the app if the app is faster than the client.

Unicorn reads off the socket as data comes in and "tee"'s off the
input to a temporary file for rewindability.  However, you can disable
the temporary file backing store by setting the
"rewindable_input false" option in the Unicorn config file[2].

Setting "rewindable_input false" violates the Rack spec, but can save
you a lot of filesystem I/O if you handle large files.

Unless all your clients are fast (on the same LAN), Unicorn requires
nginx in front of it and nginx reads everything before sending it to
Unicorn), so "rewindable_input false" doesn't do much, however...

Rainbows! is based on Unicorn, but it is designed to handle slow
clients.  It offers many concurrency options, and some of them offer
rack.input streaming like Unicorn does.  I recommend
ThreadSpawn/ThreadPool for the greatest compatibility if you want input
streaming[4].

> After some initial testing, it appears to me that the former is the case. 
> Can anyone give me advice on how to test this? Perhaps it depends on the web 
> server used? Perhaps on the framework?

The framework also matters.  You'll want to audit all your layers and
make sure they don't call methods like "rewind" or "size" on the
env["rack.input"] object.

I once wrote an app (which I haven't touched in a long time,
but probably still works) to do upload progress with Rack + Rainbows!
based on the streaming rack.input support I have:

  http://upr.bogomips.org/


[1] http://unicorn.bogomips.org/
[2] http://unicorn.bogomips.org/Unicorn/Configurator.html#method-i-rewindable_input
[3] http://rainbows.rubyforge.org/
[4] http://rainbows.rubyforge.org/Summary.html

-- 
Eric Wong

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-04-26  1:16 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-13  7:17 Does Rack-servers block until the whole request body has been read? Daniel Abrahamsson
2011-04-25 14:26 ` Joshua Ballanco
2011-04-26  1:16 ` Eric Wong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).