f700566c removed a line from evhttp_connection_stop_detectclose that
cleared the EVHTTP_CON_CLOSEDETECT flag. I think this was an
accident, and suspect that it may be the cause of bug 3069555.
evhttp needs to be mindful of all hostnames and addresses that clients
use to contact the main server and vhosts to know the difference between
proxy requests and non-proxy requests.
When we call evhttp_get_bodylen() [when transfer-encoding isn't set],
having req->ntoread == -1 means that we have no content-length. But a
request with no content-length has no body! We were treating the
absent content-length as meaning "read till closed", which only holds
for replies, not requests.
This patch also allows PATCH requests to have a body.
This patch defines enumerators for all HTTP methods that exist
(including PATCH introduced in RFC 5789).
It also makes them bit-masky (that's not a word, is it?), breaking
binary- but not source-code compatibility.
evhttp now stores a bitmask specifying for which methods requests to
dispatch and which ones to reject with "405 Method Not Allowed".
By default that's the ones we currently have (GET, POST, HEAD, PUT,
DELETE), thereby keeping functional compatibility (besides the minor
change that one of the other methods will now cause 405 instead of
400. But I believe that could even be considered a bug-fix).
evhttp is extended by evhttp_set_allowed_methods() with which the
user can change that bitmask.
no regressions here and my test-app still works. Haven't yet
actually tested any of the new methods.
What's obviously missing here is the special logic for the methods:
OPTIONS: We should be fine here - I believe our current dispatch
logic should work fine. Some convenience functions would be fine
though.
TRACE: I'm pretty certain we should never dispatch this to the
callbacks and simply implement the necessary functionality built-in.
CONNECT: Pretty straight-forward to implement (and considering the
framework in which we implement it very efficient too). Should
probably go built-in.
PATCH: Except for checking the RFC against our pre-dispatch logic
(there just might be some "MUST not have Some-Header" lurking
somewhere) there is nothing to be done here, this is completely up
to the user. Nothing to do.
We had to turn a couple of 32-bit size arguments into 64-bit arguments
or size_t arguments (since otherwise we would have had to do it post
2.0.x-stable, and that would be worse).
The trigger for starting to read the first line of a request used to
be, "When data has arrived and we're looking for the first line."
But that's not good enough: if the entire next request gets read
into our bufev->inbuf while we're still processing the current
request, we'll never see any more data arrive, and so will never
process it.
So the fix is to make sure that whenever we hit evhttp_send_done, we
call evhttp_read_cb. We can't call it directly, though, since
evhttp_send_done is reachable from the user API, and evhttp_read_cb
can invoke user functions, and we don't want to force everyone to
have reentrant callbacks. So, we use a deferred_cb.
Found by Ivan Andropov. This is bug 3008344.
We were using evbuffer_add_buffer, which moved the entire buffer
contents. But if we had a valid content_length, we only wanted to
move up to the amount of data remaining in ntoread. Our bug would
make us put our ntoread in the negative, which would in turn make us
read all data until the connection closed.
Found by Denis Bilenko. Should fix bug 2963172.
The old evhttp_decode_uri() function would act as tough it was doing
an (illegal, undefined) decode operation on a whole URL at once, and
treat + characters following a ? as different from + characters
preceding one. But that's not useful: If you are decoding a URI
before splitting off query parameters, you are begging to fail as soon
as somebody gives you a value with an encoded & in it.
The new evhttp_uridecode() function takes an argument that says
whether to decode + signs. Both uridecode and uriencode also now
support encoding or decoding to strings with internal 0-valued
characters.
Perviously, some characters not listed as "unreserved" by RFC 3986
(notably "!$'()*+,/:=@") were not encoded by evhttp_encode_uri. This
made trouble, especially when encoding path components (where @ and /
are bad news) and parameters (where + should get encoded so it doesn't
later decode into a space).
Spotted by Bas Verhoeven.
We already detected certain malformed queries, but we responded by
aborting the query-parsing process half-way through without telling
the user. Now, if query-parsing fails, no headers are returned, and
evhttp_parse_query returns -1.
Remember, the code
int is_less_than(int a, unsigned b) {
return a < b;
}
is buggy, since the C integer promotion rules basically turn it into
int is_less_than(int a, unsigned b) {
return ((unsigned)a) < b;
}
and we really want something closer to
int is_less_than(int a, unsigned b) {
return a < 0 || ((unsigned)a) < b;
}
.
Suggested by an example from Ralph Castain