Date | Commit message (Collapse) |
|
This ensures any string literals that pop up in *our* code will
just be a bag of bytes. This shouldn't affect/fix/break
existing apps in most cases, but most constants will always have
the "correct" encoding (none!) to be consistent with HTTP/socket
expectations. Since this comment affects things only on a
per-source basis, it won't affect existing apps with the
exception of strings we pass to the Rack application.
This will eventually allow us to get rid of that Unicorn::Z
constant, too.
|
|
Our current TrailerParser is liberal and does not require it,
but the to-be-activated Ragel one is not.
|
|
This change gives applications full control to deny clients
from uploading unwanted message bodies. This also paves the
way for doing things like upload progress notification within
applications in a Rack::Lint-compatible manner.
Since we don't support HTTP keepalive, so we have more freedom
here by being able to close TCP connections and deny clients the
ability to write to us (and thus wasting our bandwidth).
While I could've left this feature off by default indefinitely
for maximum backwards compatibility (for arguably broken
applications), Unicorn is not and has never been about
supporting the lowest common denominator.
|
|
Support for the "Trailer:" header and associated Trailer
lines should be reasonably well supported now
|
|
|
|
This has been broken since
6945342a1f0a4caaa918f2b0b1efef88824439e0
"Transfer-Encoding: chunked streaming input support" but
somehow never caught by me or anyone else.
|
|
Additionally, provide verifications for sizes after-the-fact
to avoid slamming all of our input into the server.
|
|
This adds support for handling POST/PUT request bodies sent with
chunked transfer encodings ("Transfer-Encoding: chunked").
Attention has been paid to ensure that a client cannot OOM us by
sending an extremely large chunk.
This implementation is pure Ruby as the Ragel-based
implementation in rfuzz didn't offer a streaming interface. It
should be reasonably close to RFC-compliant but please test it
in an attempt to break it.
The more interesting part is the ability to stream data to the
hosted Rack application as it is being transferred to the
server. This can be done regardless if the input is chunked or
not, enabling the streaming of POST/PUT bodies can allow the
hosted Rack application to process input as it receives it. See
examples/echo.ru for an example echo server over HTTP.
Enabling streaming also allows Rack applications to support
upload progress monitoring previously supported by Mongrel
handlers.
Since Rack specifies that the input needs to be rewindable, this
input is written to a temporary file (a la tee(1)) as it is
streamed to the application the first time. Subsequent rewinded
reads will read from the temporary file instead of the socket.
Streaming input to the application is disabled by default since
applications may not necessarily read the entire input body
before returning. Since this is a completely new feature we've
never seen in any Ruby HTTP application server before, we're
taking the safe route by leaving it disabled by default.
Enabling this can only be done globally by changing the
Unicorn HttpRequest::DEFAULTS hash:
Unicorn::HttpRequest::DEFAULTS["unicorn.stream_input"] = true
Similarly, a Rack application can check if streaming input
is enabled by checking the value of the "unicorn.stream_input"
key in the environment hashed passed to it.
All of this code has only been lightly tested and test coverage
is lacking at the moment.
[1] - http://tools.ietf.org/html/rfc2616#section-3.6.1
|
|
It seems most applications use buffered IO#read instead of
IO#sysread. So make sure our encoding is set correctly for
buffered IO#read applications, too.
|
|
StringIO.new(partial_body) does not update the offset for new
writes. So instead create the StringIO object and then syswrite
to it and try to follow the same code path used by large uploads
which use Tempfiles.
|
|
Sockets always return binary encoded data, so when
StringIO.new(string) is called, that StringIO object inherits
the encoding of the initial string it was created with.
And yes, Ruby 1.9 still makes me seriously uncomfortable with
I/O manipulation since the encoding layer does things behind my
back. UNIX is (and should always be) just a bag of bytes!
Signed-off-by: Eric Wong <normalperson@yhbt.net>
|
|
We need to ensure the next request has started
processing before we can guarantee a temp file
has been unlinked.
|
|
Otherwise we bloat TMPDIR and run the host out of space, oops!
|
|
Despite reading numerous articles and inspecting the 1.9.1-p0 C
source, I will never trust that we're always handling
encoding-aware IO objects correctly. Thus this new test uses
UNIX shell utilities that should always operate on files/sockets
on a byte-level.
Signed-off-by: Eric Wong <normalperson@yhbt.net>
|
|
Reset connections can also return EPIPE under Linux, not just
ECONNRESET; so be sure to trap that error, too.
|
|
Prevent the GC from trying to close it (and hitting the wrong
descriptor) when @random is reopened for running tests.
|
|
Ruby 1.9 Tempfile objects can be passed directly to File.rename
(instead of the pathname). This doesn't work in 1.8, so always
just pass the pathname to File.rename.
|
|
Tempfile reuse was over-engineered and the problem was not
nearly as big a problem as initially thought.
Additionally, it could lead to a subtle bug in an applications
that link(2)s or rename(2)s the temporary file to a permanent
location _without_ closing it after the request is done.
Applications that suffer from the problem of directory bloat are
still free to modify ENV['TMPDIR'] to influence the creation of
Tempfiles.
|