All the code inherited from version 1.1 still holds a lot ot sessions
called "t" because in 1.1 they were tasks. This naming is very annoying
and sometimes even confusing, for example in code involving tables.
Let's get rid of this once for all and before 1.5-final.
Nothing changed beyond just carefully renaming these variables.
OK, for once it cannot easily know this one, and certain versions are
emitting this harmless warning :
src/dumpstats.c: In function 'http_stats_io_handler':
src/dumpstats.c:4507:19: warning: 'last_fwd' may be used uninitialized in this function [-Wmaybe-uninitialized]
It's useless to process 100-continue in the middle of response filters
because there's no info in the 100 response itself, and it could even
make things worse. So better use it as it is, an interim response
waiting for the next response, thus we just have to put it into
http_wait_for_response(). That way we ensure to have a valid response
in this function.
Since commit d7ad9f5 ("MAJOR: channel: add a new flag CF_WAKE_WRITE to
notify the task of writes"), we got another bug with 100-continue responses.
If the final response comes in the same packet as the 100, then the rest of
the buffer is not processed since there is no wake-up event.
In fact the change above uncoverred the real culprit which is more
likely session.c which should detect that an earlier analyser was set
and should loop back to it.
A cleaner fix would be better, but setting the flag works fine.
This issue was introduced in 1.5-dev22, no backport is needed.
Patches c623c17 ("MEDIUM: http: start to centralize the forwarding code")
and bed410e ("MAJOR: http: centralize data forwarding in the request path")
merged into 1.5-dev23 cause transfers to be silently aborted after the
server timeout due to the fact that the analysers are woken up when the
timeout strikes and they believe they have nothing more to do, so they're
terminating the transfer.
No backport is needed.
This basically reimplements commit f3221f9 ("MEDIUM: stats: add support
for HTTP keep-alive on the stats page") which was reverted by commit
51437d2 after Igor Chan reported a broken stats page caused by the bug
fix by previous commit.
The errors reported by Igor Chan on the stats interface in chunked mode
were caused by data wrapping at the wrong place in the buffer. It could
be reliably reproduced by picking random buffer sizes until the issue
appeared (for a given conf, 5300 with 1024 maxrewrite was OK).
The issue is that the stats interface uses bi_putchk() to emit data,
which relies on bi_putblk(). This code checks the largest part that can
be emitted while preserving the rewrite reserve, but uses that result to
compute the wrapping offset, which is wrong. If some data remain present
in the buffer, the wrapping may be allowed and will happen before the
end of the buffer, leaving some old data in the buffer.
The reason it did not happen before keep-alive is simply that the buffer
was much less likely to contain older data. It also used to happen only
for certain configs after a certain amount of time because the size of
the counters used to inflate the output till the point wrapping started
to happen.
The fix is trivial, buffer_contig_space_with_res() simply needs to be
replaced by buffer_contig_space().
Note that peers were using the same function so it is possible that they
were affected as well.
This issue was introduced in 1.5-dev8. No backport to stable is needed.
Commit f003d37 ("BUG/MINOR: http: don't report client aborts as server errors")
attempted to fix a longstanding issue by which some client aborts could be
logged as server errors. Unfortunately, one of the tests involved there also
catches truncated server responses, which are reported as client aborts.
Instead, only check that the client has really closed using the abortonclose
option, just as in done in the request path (which means that the close was
propagated to the server).
The faulty fix above was introduced in 1.5-dev15, and was backported into
1.4.23.
Thanks to Patrick Hemmer for reporting this issue with traces showing the
root cause of the problem.
Released version 1.5-dev23 with the following main changes :
- BUG/MINOR: reject malformed HTTP/0.9 requests
- MINOR: systemd wrapper: re-execute on SIGUSR2
- MINOR: systemd wrapper: improve logging
- MINOR: systemd wrapper: propagate exit status
- BUG/MINOR: tcpcheck connect wrong behavior
- MEDIUM: proxy: support use_backend with dynamic names
- MINOR: stats: Enhancement to stats page to provide information of last session time.
- BUG/MEDIUM: peers: fix key consistency for integer stick tables
- DOC: fix a typo on http-server-close and encapsulate options with double-quotes
- DOC: fix fetching samples syntax
- MINOR: ssl: add ssl_fc_unique_id to fetch TLS Unique ID
- MEDIUM: ssl: Use ALPN support as it will be available in OpenSSL 1.0.2
- DOC: fix typo
- CLEANUP: code style: use tabs to indent codes instead of spaces
- DOC: fix a few config typos.
- BUG/MINOR: raw_sock: also consider ENOTCONN in addition to EAGAIN for recv()
- DOC: lowercase format string in unique-id
- MINOR: set IP_FREEBIND on IPv6 sockets in transparent mode
- BUG/MINOR: acl: req_ssl_sni fails with SSLv3 record version
- BUG/MINOR: build: add missing objects in osx and bsd Makefiles
- BUG/MINOR: build: handle whitespaces in wc -l output
- BUG/MINOR: Fix name lookup ordering when compiled with USE_GETADDRINFO
- MEDIUM: ssl: Add standardized DH parameters >= 1024 bits
- BUG/MEDIUM: map: The map parser includes blank lines.
- BUG/MINOR: log: The log of quotted capture header has been terminated by 2 quotes.
- MINOR: standard: add function "encode_chunk"
- BUG/MINOR: http: fix encoding of samples used in http headers
- MINOR: sample: add hex converter
- MEDIUM: sample: change the behavior of the bin2str cast
- MAJOR: auth: Change the internal authentication system.
- MEDIUM: acl/pattern: standardisation "of pat_parse_int()" and "pat_parse_dotted_ver()"
- MEDIUM: pattern: The pattern parser no more uses <opaque> and just takes one string.
- MEDIUM: pattern: Change the prototype of the function pattern_register().
- CONTRIB: ip6range: add a network IPv6 range to mask converter
- MINOR: pattern: separe list element from the data part.
- MEDIUM: pattern: add indexation function.
- MEDIUM: pattern: The parse functions just return "struct pattern" without memory allocation
- MINOR: pattern: Rename "pat_idx_elt" to "pattern_tree"
- MINOR: sample: dont call the sample cast function "c_none"
- MINOR: standard: Add function for converting cidr to network mask.
- MEDIUM: sample: Remove types SMP_T_CSTR and SMP_T_CBIN, replace it by SMP_F_CONST flags
- MEDIUM: sample/http_proto: Add new type called method
- MINOR: dumpstats: Group map inline help
- MEDIUM: pattern: The function pattern_exec_match() returns "struct pattern" if the patten match.
- MINOR: dumpstats: change map inline sentences
- MINOR: dumpstats: change the "get map" display management
- MINOR: map/dumpstats: The cli cmd "get map ..." display the "int" format.
- MEDIUM: pattern: The match function browse itself the list or the tree.
- MEDIUM: pattern: Index IPv6 addresses in a tree.
- MEDIUM: pattern: add delete functions
- MEDIUM: pattern: add prune function
- MEDIUM: pattern: add sample lookup function.
- MEDIUM: pattern/dumpstats: The function pattern_lookup() is no longer used
- MINOR: map/pattern: The sample parser is stored in the pattern
- MAJOR: pattern/map: Extends the map edition system in the patterns
- MEDIUM: pattern: merge same pattern
- MEDIUM: pattern: The expected type is stored in the pattern head, and conversion is executed once.
- MINOR: pattern: Each pattern is identified by unique id.
- MINOR: pattern/acl: Each pattern of each acl can be load with specified id
- MINOR: pattern: The function "pattern_register()" is no longer used.
- MINOR: pattern: Merge function pattern_add() with pat_ref_push().
- MINOR: pattern: store configuration reference for each acl or map pattern.
- MINOR: pattern: Each pattern expression element store the reference struct.
- MINOR: dumpstats: display the reference for th key/pattern and value.
- MEDIUM: pattern: delete() function uses the pat_ref_elt to find the element to be removed
- MEDIUM: pattern_find_smp: functions find_smp uses the pat_ref_elt to find the element to be removed
- MEDIUM: dumpstats/pattern: display and use each pointer of each pattern dumped
- MINOR: pattern/map/acl: Centralization of the file parsers
- MINOR: pattern: Check if the file reference is not used with acl and map
- MINOR: acl/pattern: Acl "-M" option force to load file as map file with two columns
- MEDIUM: dumpstats: Display error message during add of values.
- MINOR: pattern: The function pat_ref_set() have now atomic behavior
- MINOR: regex: The pointer regstr in the struc regex is no longer used.
- MINOR: cli: Block the usage of the command "acl add" in many cases.
- MINOR: doc: Update the documentation about the map and acl
- MINOR: pattern: index duplicates
- MINOR: configuration: File and line propagation
- MINOR: dumpstat/conf: display all the configuration lines that using pattern reference
- MINOR: standard: Disable ip resolution during the runtime
- MINOR: pattern: Remove the flag "PAT_F_FROM_FILE".
- MINOR: pattern: forbid dns resolutions
- DOC: document "get map" / "get acl" on the CLI
- MEDIUM: acl: Change the acl register struct
- BUG/MEDIUM: acl: boolean only matches were broken by recent changes
- DOC: pattern: pattern organisation schematics
- MINOR: pattern/cli: Update used terms in documentation and cli
- MINOR: cli: remove information about acl or map owner.
- MINOR: session: don't always assume there's a listener
- MINOR: pattern: Add function to prune and reload pattern list.
- MINOR: standard: Add ipv6 support in the function url2sa().
- MEDIUM: config: Dynamic sections.
- BUG/MEDIUM: stick-table: fix IPv4-to-IPv6 conversion in src_* fetches
- MINOR: http: Add the "language" converter to for use with accept-language
- BUG/MINOR: log: Don't dump empty unique-id
- BUG/MAJOR: session: fix a possible crash with src_tracked
- DOC: Update "language" documentation
- MINOR: http: add the function "del-header" to the directives http-request and http-response
- DOC: add some information on capture.(req|res).hdr
- MINOR: http: capture.req.method and capture.req.uri
- MINOR: http: optimize capture.req.method and capture.req.uri
- MINOR: session: clean up the connection free code
- BUG/MEDIUM: checks: immediately report a connection success
- MEDIUM: connection: don't use real send() flags in snd_buf()
- OPTIM: ssl: implement dynamic record size adjustment
- MINOR: stats: report exact last session time in backend too
- BUG/MEDIUM: stats: the "lastsess" field must appear last in the CSV.
- BUG/MAJOR: check: fix memory leak in "tcp-check connect" over SSL
- BUG/MINOR: channel: initialize xfer_small/xfer_large on new buffers
- MINOR: channel: add the date of last read in the channel
- MEDIUM: stream-int: automatically disable CF_STREAMER flags after idle
- MINOR: ssl: add DEFAULT_SSL_MAX_RECORD to set the record size at build time
- MINOR: config: make the stream interface idle timer user-configurable
- MINOR: config: add global directives to set default SSL ciphers
- MINOR: sample: add a rand() sample fetch to return a sample.
- BUG/MEDIUM: config: immediately abort if peers section has no name
- BUG/MINOR: ssl: fix syntax in config error message
- BUG/MEDIUM: ssl: always send a full buffer after EAGAIN
- BUG/MINOR: config: server on-marked-* statement is ignored in default-server
- BUG/MEDIUM: backend: prefer-last-server breaks redispatch
- BUG/MEDIUM: http: continue to emit 503 on keep-alive to different server
- MEDIUM: acl: fix pattern type for payload / payload_lv
- BUG/MINOR: config: fix a crash on startup when a disabled backend references a peer
- BUG/MEDIUM: compression: fix the output type of the compressor name
- BUG/MEDIUM: http: don't start to forward request data before the connect
- MINOR: http: release compression context only in http_end_txn()
- MINOR: protect ebimtree/ebistree against multiple inclusions
- MEDIUM: proxy: create a tree to store proxies by name
- MEDIUM: proxy: make findproxy() use trees to look up proxies
- MEDIUM: proxy: make get_backend_server() use findproxy() to lookup proxies
- MEDIUM: stick-table: lookup table names using trees.
- MEDIUM: config: faster lookup for duplicated proxy name
- CLEANUP: acl: remove obsolete test in parse_acl_expr()
- MINOR: sample: move smp_to_type to sample.c
- MEDIUM: compression: consider the "q=" attribute in Accept-Encoding
- REORG: cfgparse: move server keyword parsing to server.c
- BUILD: adjust makefile for AIX 5.1
- BUG/MEDIUM: pattern: fix wrong definition of the pat_prune_fcts array
- CLEANUP: pattern: move array definitions to proto/ and not types/
- BUG/MAJOR: counters: check for null-deref when looking up an alternate table
- BUILD: ssl: previous patch failed
- BUILD/MEDIUM: standard: get rid of the last strcpy()
- BUILD/MEDIUM: standard: get rid of sprintf()
- BUILD/MEDIUM: cfgparse: get rid of sprintf()
- BUILD/MEDIUM: checks: get rid of sprintf()
- BUILD/MEDIUM: http: remove calls to sprintf()
- BUG/MEDIUM: systemd-wrapper: fix locating of haproxy binary
- BUILD/MINOR: ssl: remove one call to sprintf()
- MEDIUM: http: don't reject anymore message bodies not containing the url param
- MEDIUM: http: wait for the first chunk or message body length in http_process_body
- CLEANUP: http: rename http_process_request_body()
- CLEANUP: http: prepare dedicated processing for chunked encoded message bodies
- MINOR: http: make msg->eol carry the last CRLF length
- MAJOR: http: do not use msg->sol while processing messages or forwarding data
- MEDIUM: http: http_parse_chunk_crlf() must not advance the buffer pointer
- MAJOR: http: don't update msg->sov anymore while processing the body
- MINOR: http: add a small helper to compute the amount of body bytes present
- MEDIUM: http: add a small helper to compute how far to rewind to find headers
- MINOR: http: add a small helper to compute how far to rewind to find URI
- MEDIUM: http: small helpers to compute how far to rewind to find BODY and DATA
- MAJOR: http: reset msg->sov after headers are forwarded
- MEDIUM: http: forward headers again while waiting for connection to complete
- BUG/MINOR: http: deinitialize compression after a parsing error
- BUG/MINOR: http: deinitialize compression after a compression error
- MEDIUM: http: headers must be forwarded even if data was already inspected
- MAJOR: http: re-enable compression on chunked encoding
- MAJOR: http/compression: fix chunked-encoded response processing
- MEDIUM: http: cleanup: centralize a little bit HTTP compression end
- MEDIUM: http: start to centralize the forwarding code
- MINOR: http: further cleanups of response forwarding function
- MEDIUM: http: only allocate the temporary compression buffer when needed
- MAJOR: http: centralize data forwarding in the request path
- CLEANUP: http: document the response forwarding states
- CLEANUP: http: remove all calls to http_silent_debug()
- DOC: internal: add some reminders about HTTP parsing and pointer states
- BUG/MAJOR: http: fix bug in parse_qvalue() when selecting compression algo
- BUG/MINOR: stats: last session was not always set
- DOC: add pointer to the Cyril's HTML doc in the README
- MEDIUM: config: relax use_backend check to make the condition optional
- MEDIUM: config: report misplaced http-request rules
- MEDIUM: config: report misplaced use-server rules
- DOC: update roadmap with what was done.
Till now there was no check against misplaced use-server rules, and
no warning was emitted, adding to the confusion. They're processed
just after the use_backend rules, or more exactly at the same level
but for the backend.
Recently, the http-request ruleset started to be used a lot and some
bug reports were caused by misplaced http-request rules because there
was no warning if they're after a redirect or use_backend rule. Let's
fix this now. http-request rules are just after the block rules.
Since it became possible to use log-format expressions in use_backend,
having a mandatory condition becomes annoying because configurations
are full of "if TRUE". Let's relax the check to accept no condition
like many other keywords (eg: redirect).
Cyril Bont reported that the "lastsess" field of a stats-only backend
was never updated. In fact the same is true for any applet and anything
not a server. Also, lastsess was not updated for a server reusing its
connection for a new request.
Since the goal of this field is to report recent activity, it's better
to ensure that all accesses are reported. The call has been moved to
the code validating the session establishment instead, since everything
passes there.
The syntax used to document fetching samples with optional arguments was not
always valid. This commit fixes this issue in order to allow an easier parsing
of the documentation.
Commit ad90351 ("MINOR: http: Add the "language" converter to for use with accept-language")
introduced a typo in parse_qvalue :
if (*end)
*end = qvalue;
while it should be :
if (end)
*end = qvalue;
Since end is tested for being NULL. This crashes when selecting the
compression algorithm since end is NULL here. No backport is needed,
this is just in latest 1.5-dev.
The forwarding code is never obvious to enter into for newcomers, so
better improve the documentation about how states are chained and what
happens for each of them.
Doing so avoids calling channel_forward() for each part of the chunk
parsing and lowers the number of calls to channel_forward() to only
one per buffer, resulting in about 11% performance increase on small
chunks forwarding rate.
The call to flush the compression buffers only needs to be done when
entering the final states or when leaving with missing data. After
that, if trailers are present, they have to be forwarded.
Now we have valid buffer offsets, we can use them to safely parse the
input and only forward when needed. Thus we can get rid of the
consumed_data accumulator, and the code now works both for chunked and
content-length, even with a server feeding one byte at a time (which
systematically broke the previous one).
It's worth noting that 0<CRLF> must always be sent after end of data
(ie: chunk_len==0), and that the trailing CRLF is sent only content
length mode, because in chunked we'll have to pass trailers.
This is basically a revert of commit 667c2a3 ("BUG/MAJOR: http: compression
still has defects on chunked responses").
The latest changes applied to message pointers should have got rid of all
the issues that were making the compression of partial chunks unreliable.
Currently, we forward headers only if the incoming message is still before
HTTP_MSG_CHUNK_SIZE, otherwise they'll be considered as data. In practice
this is always true for the response since there's no data inspection, and
for the request there is no compression so there's no problem with forwarding
them as data.
But the principle is incorrect and will make it difficult to later add data
processing features. So better fix it now.
The new principle is simple :
- if headers were not yet forwarded, forward them now.
- while doing so, check if we need to update the state
If for some reason, the compression returns an error, the compression
is not deinitialized which also means that any pending data are not
flushed and could be lost, especially in the chunked-encoded case.
No backport is needed.
When a parsing error was encountered in a chunked response, we failed
to properly deinitialize the compression context. There was no impact
till now since compression of chunked responses was disabled. No backport
is needed.
Thanks to the last updates on the message pointers, it is now safe again to
enable forwarding of the request headers while waiting for the connection to
complete because we know how to safely rewind this part.
So this patch slightly modifies what was done in commit 80a92c0 ("BUG/MEDIUM:
http: don't start to forward request data before the connect") to let up to
msg->sov bytes be forwarded when waiting for the connection. The resulting
effect is that a POST request may now be sent with the connect's ACK, which
still saves a packet and may even be useful later when TFO is supported.
In order to avoid abusively relying on buf->o to guess how many bytes to
rewind during a redispatch, we now clear msg->sov. Thus the meaning of this
field is exactly "how many bytes of headers are left to be forwarded". It
is still possible to rewind because msg->eoh + msg->eol equal that value
before scheduling the forwarding, so we can always subtract them.
http_body_rewind() returns the number of bytes to rewind before buf->p to
find the message's body. It relies on http_hdr_rewind() to find the beginning
and adds msg->eoh + msg->eol which are always safe.
http_data_rewind() does the same to get the beginning of the data, which
differs from above when a chunk is present. It uses the function above and
adds msg->sol.
The purpose is to centralize further ->sov changes aiming at avoiding
to rely on buf->o.
http_uri_rewind() returns the number of bytes to rewind before buf->p to
find the URI. It relies on http_hdr_rewind() to find the beginning and
is just here to simplify operations.
The purpose is to centralize further ->sov changes aiming at avoiding
to rely on buf->o.
http_hdr_rewind() returns the number of bytes to rewind before buf->p to
find the beginning of headers. At the moment it's not exact as it still
relies on buf->o, assuming that no other data from a past message were
pending there, but it's what was done till there.
The purpose is to centralize further ->sov changes aiming at avoiding
to rely on buf->o.
http_body_bytes() returns the number of bytes of the current message body
present in the buffer. It is compatible with being called before and after
the headers are forwarded.
This is done to centralize further ->sov changes.
We used to have msg->sov updated for every chunk that was parsed. The issue
is that we want to be able to rewind after chunks were parsed in case we need
to redispatch a request and perform a new hash on the request or insert a
different server header name.
Currently, msg->sov and msg->next make parallel progress. We reached a point
where they're always equal because msg->next is initialized from msg->sov,
and is subtracted msg->sov's value each time msg->sov bytes are forwarded.
So we can now ensure that msg->sov can always be replaced by msg->next for
every state after HTTP_MSG_BODY where it is used as a position counter.
This allows us to keep msg->sov untouched whatever the number of chunks that
are parsed, as is needed to extract data from POST request (eg: url_param).
However, we still need to know the starting position of the data relative to
the body, which differs by the chunk size length. We use msg->sol for this
since it's now always zero and unused in the body.
So with this patch, we have the following situation :
- msg->sov = msg->eoh + msg->eol = size of the headers including last CRLF
- msg->sol = length of the chunk size if any. So msg->sov + msg->sol = DATA.
- msg->next corresponds to the byte being inspected based on the current
state and is always >= msg->sov before starting to forward anything.
Since sov and next are updated in case of header rewriting, a rewind will
fix them both when needed. Of course, ->sol has no reason for changing in
such conditions, so it's fine to keep it relative to msg->sov.
In theory, even if a redispatch has to be performed, a transformation
occurring on the request would still work because the data moved would
still appear at the same place relative to bug->p.
This function is only a parser, it must start to parse at the next character
and only update the outgoing relative pointers, but not expect the buffer to
be aligned with the next byte to be parsed.
It's important to fix this otherwise we cannot use this function to parse
chunks without starting to forward data.
There are still some pending issues in the gzip compressor, and fixing
them requires a better handling of intermediate parsing states.
Another issue to deal with is the rewinding of a buffer during a redispatch
when a load balancing algorithm involves L7 data because the exact amount of
data to rewind is not clear. At the moment, this is handled by unwinding all
pending data, which cannot work in responses due to pipelining.
Last, having a first analysis which parses the body and another one which
restarts from where the parsing was left is wrong. Right now it only works
because we never both parse and transform in the same direction. But that
is wrong anyway.
In order to address the first issue, we'll have to use msg->eoh + msg->eol
to find the end of headers, and we still need to store the information about
the forwarded header length somewhere (msg->sol might be reused for this).
msg->sov may only be used for the start of data and not for subsequent chunks
if possible. This first implies that we stop sharing it with header length,
and stop using msg->sol there. In fact we don't need it already as it is
always zero when reaching the HTTP_MSG_BODY state. It was only updated to
reflect a copy of msg->sov.
So now as a first step into that direction, this patch ensure that msg->sol
is never re-assigned after being set to zero and is not used anymore when
we're dealing with HTTP processing and forwarding. We'll later reuse it
differently but for now it's secured.
The patch does nothing magic, it only removes msg->sol everywhere it was
already zero and avoids setting it. In order to keep the sov-sol difference,
it now resets sov after forwarding data. In theory there's no problem here,
but the patch is still tagged major because that code is complex.
One of the issues we face when we need to either forward headers only
before compressing, or rewind the stream during a redispatch is to know
the proper length of the request headers. msg->eoh always has the total
length up to the last CRLF, and we never know whether the request ended
with a single LF or a standard CRLF. This makes it hard to rewind the
headers without explicitly checking the bytes in the buffer.
Instead of doing so, we now use msg->eol to carry the length of the last
CRLF (either 1 or 2). Since it is not modified at all after HTTP_MSG_BODY,
and was only left in an undefined state, it is safe to use at any moment.
Thus, the complete header length to forward or to rewind now is always
msg->eoh + msg->eol.
Content-length encoded message bodies are trivial to deal with, but
chunked-encoded will require improvements, so let's separate the code
flows between the two to ease next steps. The behaviour is not changed
at all, the code is only rearranged.
This is the continuation of previous patch. Now that full buffers are
not rejected anymore, let's wait for at least the advertised chunk or
body length to be present or the buffer to be full. When either
condition is met, the message processing can go forward.
Thus we don't need to use url_param_post_limit anymore, which was passed
in the configuration as an optionnal <max_wait> parameter after the
"check_post" value. This setting was necessary when the feature was
implemented because there was no support for parsing message bodies.
The argument is now silently ignored if set in the configuration.
http_process_request_body() currently expects a request body containing
exactly an expected message body. This was done in order to support load
balancing on a unique POST parameter but the way it's done still suffers
from some limitations. One of them is that there is no guarantee that the
accepted message will contain the appropriate string if it starts with
another parameter. But at the same time it will reject a message when the
buffer is full.
So as a first step, we don't reject anymore message bodies that fill the
buffer.