MINOR: h1: parse the Connection header field

The new function h1_parse_connection_header() is called when facing a
connection header in the generic parser, and it will set up to 3 bits
in h1m->flags indicating if at least one "close", "keep-alive" or "upgrade"
tokens was seen.
This commit is contained in:
Willy Tarreau 2018-09-13 14:15:58 +02:00
parent ba5fbca33f
commit 98f5cf7a59
2 changed files with 53 additions and 0 deletions

View File

@ -141,6 +141,18 @@ enum h1m_state {
#define H1_MF_RESP 0x00000004 // this message is the response message
#define H1_MF_TOLOWER 0x00000008 // turn the header names to lower case
#define H1_MF_VER_11 0x00000010 // message indicates version 1.1 or above
#define H1_MF_CONN_CLO 0x00000020 // message contains "connection: close"
#define H1_MF_CONN_KAL 0x00000040 // message contains "connection: keep-alive"
#define H1_MF_CONN_UPG 0x00000080 // message contains "connection: upgrade"
/* Note: for a connection to be persistent, we need this for the request :
* - one of CLEN or CHNK
* - version 1.0 and KAL and not CLO
* - or version 1.1 and not CLO
* For the response it's the same except that UPG must not appear either.
* So in short, for a request it's (CLEN|CHNK) > 0 && !CLO && (VER_11 || KAL)
* and for a response it's (CLEN|CHNK) > 0 && !(CLO|UPG) && (VER_11 || KAL)
*/
/* basic HTTP/1 message state for use in parsers. The err_pos field is special,

View File

@ -659,6 +659,44 @@ void http_msg_analyzer(struct http_msg *msg, struct hdr_idx *idx)
return;
}
/* Parse the Connection: header of an HTTP/1 request, looking for "close",
* "keep-alive", and "upgrade" values, and updating h1m->flags according to
* what was found there. Note that flags are only added, not removed, so the
* function is safe for being called multiple times if multiple occurrences
* are found.
*/
void h1_parse_connection_header(struct h1m *h1m, struct ist value)
{
char *e, *n;
struct ist word;
word.ptr = value.ptr - 1; // -1 for next loop's pre-increment
e = value.ptr + value.len;
while (++word.ptr < e) {
/* skip leading delimitor and blanks */
if (HTTP_IS_LWS(*word.ptr))
continue;
n = http_find_hdr_value_end(word.ptr, e); // next comma or end of line
word.len = n - word.ptr;
/* trim trailing blanks */
while (word.len && HTTP_IS_LWS(word.ptr[word.len-1]))
word.len--;
if (isteqi(word, ist("keep-alive")))
h1m->flags |= H1_MF_CONN_KAL;
else if (isteqi(word, ist("close")))
h1m->flags |= H1_MF_CONN_CLO;
else if (isteqi(word, ist("upgrade")))
h1m->flags |= H1_MF_CONN_UPG;
word.ptr = n;
}
}
/* This function parses a contiguous HTTP/1 headers block starting at <start>
* and ending before <stop>, at once, and converts it a list of (name,value)
* pairs representing header fields into the array <hdr> of size <hdr_num>,
@ -1244,6 +1282,9 @@ int h1_headers_to_hdr_list(char *start, const char *stop,
strl2llrc(v.ptr, v.len, &cl);
h1m->curr_len = h1m->body_len = cl;
}
else if (isteqi(n, ist("connection"))) {
h1_parse_connection_header(h1m, v);
}
}
sol = ptr - start;