Date | Commit message (Collapse) |
|
HTTP requests without trailers still need a CRLF after the last
chunk, that is: it must end as: "0\r\n\r\n", not "0\r\n". So
we'll always pretend there are trailers to parse for the
sake of TeeInput.
This is mostly a pedantic fix, as the two bytes in the socket
buffer are unlikely to trigger protocol errors.
|
|
Not fun, but maybe this can help us spot _real_ problems
more easily in the future.
|
|
* init_globals() is a static function, avoid conflicting
with any potential libraries out there...
* mUnicorn and cHttpParser do not need to be static globals
they're not used outside of Init_unicorn_http().
|
|
We never come close to the signed limits anywhere, so it
should be safe either way, but make paranoid compiler settings
less noisy if possible.
|
|
First off, this memory leak DOES NOT affect Unicorn itself.
Unicorn allocates the HttpParser once and always reuses it
in every sequential request.
This leak affects applications which repeatedly allocate a new
HTTP parser. Thus this bug affects _all_ deployments of
Rainbows! and Zbatery. These servers allocate a new parser for
every client connection.
I misread the Data_Make_Struct/Data_Wrap_Struct documentation
and ended up passing NULL as the "free" argument instead of -1,
causing the memory to never be freed.
From README.EXT in the MRI source which I misread:
> The free argument is the function to free the pointer
> allocation. If this is -1, the pointer will be just freed.
> The functions mark and free will be called from garbage
> collector.
|
|
This allows clients to trickle headers and trailers. While
Unicorn itself does not support slow clients for many reasons,
this affects servers that depend on our parser like Rainbows!.
This actually does affect Unicorn when handling trailers, but
HTTP trailers are very ever rarely used in requests.
Fortunately this stupid bug does not seem able to trigger
out-of-bounds conditions.
|
|
assert_frozen() should not be checking what type of
object it is, instead put an extra assertion in there
to ensure we have a string.
|
|
Since empty values on one line can be a heuristic to determine
future lines are continuation lines (and a as a result, a
decently long header), pre-allocate a string buffer just in
case.
This is to workaround what appears to be bug in the Rubinius C
API, but it could be considered (intended) DWIM behavior, too...
|
|
Rubinius supports these functions as of
039091066244cfcf483310b86b5c4989aaa6302b
This allows the test_http_parser_ng.rb test to run under
Rubinius db612aa62cad9e5cc41a4a4be645642362029d20
|
|
Rubinius does not support frozen objects, maybe other Rubies
lack support for it as well.
|
|
This probably doesn't affect anyone with HTTP/1.1, but
future versions of HTTP will use absolute URIs and maybe
we'll eventually get clients that (mistakenly) send us
Host: headers along with absolute URIs.
|
|
No need to add an extra check, even if it does avoid a
function call.
|
|
This should be more inline with Ruby standards/coding style
and probably more future-proof, as well.
|
|
This makes it easier for bug reporters to tell us what's
wrong in case line numbers change.
|
|
Just in case, it'll be easier to track down if bugs
pop up.
|
|
There's no need to use a goto here to avoid one level of
nesting.
|
|
This should make code easier to read and follow.
|
|
In case we modify our struct to not use bitflags, this should
make it easier to change the parser code. This also adds extra
clarification for how we track keepalive and why we only do it
for certain request methods.
|
|
These are similar to the macros found in MRI, and
can more easily allow us to swap out the bitflags
for real struct members...
|
|
Avoid a negative conditional in the process and having an
explicit else in there makes this piece easier to track.
Also explain /why/ the Host: header can get ignored.
|
|
Just pass the http_parser struct pointer when checking for
invalid headers in the trailer. The compiler should be smart
enough to inline and not relookup the flags. This avoids having
to worry about the flags being signed or not (they should never
be) and also makes it easier to maintain if we move away from
using bitfields.
|
|
This method determines if there are headers in the request.
Simple HTTP/0.9 requests did not have headers in the request
(and our responses we make should not have them, either).
|
|
And it'll default to HTTP/0.9 if HTTP_VERSION is not specified
(as version-less HTTP requests imply HTTP/0.9.
|
|
neither buffer nor p should be const (since we modify buffer in
$snake_upcase_char), but this is a much smaller change _for now_
|
|
While I still consider pound to be irrelevant, but I still
sometimes get hand-crafted HTTP requests that come in with
multiline headers. Since these are part of the HTTP specs and
not difficult to support, we might as well support them for
the sake of completeness.
|
|
Ruby strings may be copy-on-write (multiple #dup'ed strings can
point to the same internal buffers). So since
HttpParser#headers modifies its buffer argument, we'll need to
make sure the String object we have points to its own private
buffer.
This doesn't affect Unicorn except in a to-be-written test case
that relies on a #dup'ed String.
|
|
* Documented Unicorn::HttpParser API methods
* Keep GPL2 (COPYING) as-is without RDoc formatting.
* The auto-generated index.html is stupid, replace it with
README which looks saner.
|
|
ab still sends this with HTTP/1.0 requests, which is
unfortunate, but synthetic benchmarks are good for marketing
purposes!
|
|
This should be used to detect if a request can really handle
keepalives and pipelining. Currently, the rules are:
1. MUST be a GET or HEAD request
2. MUST be HTTP/1.1
3. MUST NOT have "Connection: close" set
This also reduces the amount of garbage we create by
globalizing constants and using them whenever possible.
|
|
This method is strictly a filter, it does no I/O so "read"
is not an appropriate name to give it.
|
|
Since Rack requires a Hash object, this is joined in in
accordance with rfc2616, section 4.2[1]. Of course, it's up to
the framework or application to handle such requests.
I could optimize this to avoid creating a single garbage
String object, but I don't think it's common enough to
worry about...
[1] - http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
|
|
We're bound by the maximum value of off_t when handling
input bodies (we need to buffer to disk). Also ensure
we stop bad clients that send us unparseable lengths.
|
|
This should be more robust, faster and easier to deal
with than the ugly proof-of-concept regexp-based ones.
|
|
|
|
Explicitly track if our request will need Content-Length
or chunked body decoding.
|
|
The macro version lets us painlessly compare Ruby strings
against constant C strings. It wraps a C version of the
function which is necessary to avoid double evaluation while
preventing the user from having to type sizeof or strlen.
|
|
We'll need to keep track of a few more things to account
for content/chunk length and the temporary file descriptor
we'll need to use.
|
|
It's easy enough to just check a single equality without having
extra functions obscuring what's actually going on.
|
|
We'll need to be defining g_http_transfer_encoding and
g_content_length in the near future.
|
|
Just extra noise we don't care about. This also allows us to
undef the DEF_GLOBAL macro to avoid polluting the main
namespace.
|
|
It's mostly uninteresting code.
|
|
Create a Ruby string object before jumping into the function
to reduce the number of parameters passed and to take advantage
of our STR_NEW macro to reduce noise.
|
|
|
|
It doesn't conflict with any any common variables, tokens or
documentation pieces in the code.
|
|
Eliminate unnecessary jumping around in the source code to find
actions that lead to other actions and making it harder to
notice side effects when dealing with data we're sharing anyways.
|
|
There's also no point in validating field hits if our field is a
common field; so only do the validation for field length if we
need to allocate memory for a new field.
|
|
The "_value" suffix was used to denote the return type, which is
redundandant as it is already known at compile time (being that
this is C and functions have explicit return types). Furthurmore,
the "_value" is confusing since we're actually returning a "key"
when "value" is used in the context of "key-value" pairs.
|
|
More tightly integrate the C/Ruby portions with C/Ragel to avoid
the confusing the flow. Split out some files into hopefully
logical areas so it's easier to focus on more
interesting/volatile code.
|
|
So that blame falls on Eric if stuff breaks.
|
|
typedefs can be misleading for aggregate types, a struct is a
struct.
|