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.
diff --git a/include/types/h1.h b/include/types/h1.h
index dd883e8..ec967ac 100644
--- a/include/types/h1.h
+++ b/include/types/h1.h
@@ -141,6 +141,18 @@
#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,
diff --git a/src/h1.c b/src/h1.c
index ec8bb38..b78f584 100644
--- a/src/h1.c
+++ b/src/h1.c
@@ -659,6 +659,44 @@
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 @@
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;