+++ /dev/null
-commit 54948f3fd310ffc74a6c252dc11046a8a18ab230
-Author: Jerome Magnin <jmagnin@haproxy.com>
-Date: Sat Nov 9 18:00:47 2019 +0100
-
- BUG/MINOR: stream: init variables when the list is empty
-
- We need to call vars_init() when the list is empty otherwise we
- can't use variables in the response scope. This regression was
- introduced by cda7f3f5 (MINOR: stream: don't prune variables if
- the list is empty).
-
- The following config reproduces the issue:
-
- defaults
- mode http
-
- frontend in
- bind *:11223
- http-request set-var(req.foo) str("foo") if { path /bar }
- http-request set-header bar %[var(req.foo)] if { var(req.foo) -m found }
- http-response set-var(res.bar) str("bar")
- http-response set-header foo %[var(res.bar)] if { var(res.bar) -m found }
- use_backend out
-
- backend out
- server s1 127.0.0.1:11224
-
- listen back
- bind *:11224
- http-request deny deny_status 200
-
- > GET /ba HTTP/1.1
- > Host: localhost:11223
- > User-Agent: curl/7.66.0
- > Accept: */*
- >
- < HTTP/1.0 200 OK
- < Cache-Control: no-cache
- < Content-Type: text/html
-
- > GET /bar HTTP/1.1
- > Host: localhost:11223
- > User-Agent: curl/7.66.0
- > Accept: */*
- >
- < HTTP/1.0 200 OK
- < Cache-Control: no-cache
- < Content-Type: text/html
- < foo: bar
-
- This must be backported as far as 1.9.
-
- (cherry picked from commit 2f44e8843a553ef0f9c53c9b27899727de097777)
- Signed-off-by: Willy Tarreau <w@1wt.eu>
-
-diff --git a/src/stream.c b/src/stream.c
-index 4a7ced22..9fe0efaf 100644
---- a/src/stream.c
-+++ b/src/stream.c
-@@ -2399,10 +2399,9 @@ struct task *process_stream(struct task *t, void *context, unsigned short state)
- if (si_state_in(si_b->state, SI_SB_REQ|SI_SB_QUE|SI_SB_TAR|SI_SB_ASS)) {
- /* prune the request variables and swap to the response variables. */
- if (s->vars_reqres.scope != SCOPE_RES) {
-- if (!LIST_ISEMPTY(&s->vars_reqres.head)) {
-+ if (!LIST_ISEMPTY(&s->vars_reqres.head))
- vars_prune(&s->vars_reqres, s->sess, s);
-- vars_init(&s->vars_reqres, SCOPE_RES);
-- }
-+ vars_init(&s->vars_reqres, SCOPE_RES);
- }
-
- do {
+++ /dev/null
-commit 3a00e5fcc1af121dea16793d47627c16c97fb953
-Author: Christopher Faulet <cfaulet@haproxy.com>
-Date: Wed Nov 27 11:22:37 2019 +0100
-
- BUG/MINOR: contrib/prometheus-exporter: Use HTX errors and not legacy ones
-
- This bug was introduced when the commit 32d634f1 ("MINOR:
- contrib/prometheus-exporter: filter exported metrics by scope") was backported
- to 2.0.
-
- In 2.0, Error chunks exist in raw format (http_err_chunks[]) and in HTX format
- (htx_err_chunks[]). Prometheus exported only supports the HTX. So error must not
- be reported using the raw chunks.
-
- This fix is specific to 2.0. No backport needed.
-
-diff --git a/contrib/prometheus-exporter/service-prometheus.c b/contrib/prometheus-exporter/service-prometheus.c
-index 56d49a39..cfbfb8c3 100644
---- a/contrib/prometheus-exporter/service-prometheus.c
-+++ b/contrib/prometheus-exporter/service-prometheus.c
-@@ -2292,7 +2292,7 @@ static int promex_parse_uri(struct appctx *appctx, struct stream_interface *si)
- return 1;
-
- error:
-- err = &http_err_chunks[HTTP_ERR_400];
-+ err = &htx_err_chunks[HTTP_ERR_400];
- channel_erase(res);
- res->buf.data = b_data(err);
- memcpy(res->buf.area, b_head(err), b_data(err));
+++ /dev/null
-commit 200c6215fe9c592d576f52d4a79627381ed6aa7f
-Author: William Dauchy <w.dauchy@criteo.com>
-Date: Tue Nov 26 12:56:26 2019 +0100
-
- BUG/MINOR: contrib/prometheus-exporter: decode parameter and value only
-
- we were decoding all substring and then parsing; this could lead to
- consider & and = in decoding result as delimiters where it should not.
- this patch reverses the order by first parsing and then decoding each key
- and value separately.
-
- we also stop parsing after number sign (#).
-
- This patch should be backported to 2.1 and 2.0
-
- Signed-off-by: William Dauchy <w.dauchy@criteo.com>
- (cherry picked from commit c65f656d75091db3087a752dbc956159392fc8f2)
- Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
- (cherry picked from commit 8ec21c5fef89f13fea2ac9be55d55215d4b9104a)
- Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-
-diff --git a/contrib/prometheus-exporter/service-prometheus.c b/contrib/prometheus-exporter/service-prometheus.c
-index cfbfb8c3..c34ee0e1 100644
---- a/contrib/prometheus-exporter/service-prometheus.c
-+++ b/contrib/prometheus-exporter/service-prometheus.c
-@@ -2220,7 +2220,8 @@ static int promex_parse_uri(struct appctx *appctx, struct stream_interface *si)
- struct channel *res = si_ic(si);
- struct htx *req_htx, *res_htx;
- struct htx_sl *sl;
-- const char *p, *end;
-+ char *p, *key, *value;
-+ const char *end;
- struct buffer *err;
- int default_scopes = PROMEX_FL_SCOPE_ALL;
- int len;
-@@ -2234,57 +2235,72 @@ static int promex_parse_uri(struct appctx *appctx, struct stream_interface *si)
- if (!p)
- goto end;
- end = HTX_SL_REQ_UPTR(sl) + HTX_SL_REQ_ULEN(sl);
-- len = end-p;
-
-- /* Decode the query-string */
-+ /* copy the query-string */
-+ len = end - p;
- chunk_reset(&trash);
- memcpy(trash.area, p, len);
- trash.area[len] = 0;
-- len = url_decode(trash.area);
-- if (len == -1)
-- goto error;
- p = trash.area;
-- end = p + len;
-+ end = trash.area + len;
-
- /* Parse the query-string */
-- while (p < end) {
-- if (*p == '&')
-+ while (p < end && *p && *p != '#') {
-+ value = NULL;
-+
-+ /* decode parameter name */
-+ key = p;
-+ while (p < end && *p != '=' && *p != '&' && *p != '#')
- ++p;
-- else if (*p == 's' && (end-p) >= 6 && !memcmp(p, "scope=", 6)) {
-- default_scopes = 0; /* at least a scope defined, unset default scopes */
-- p += 6; /* now p point on the parameter value */
-- len = 0; /* len is the value length */
-- while ((p+len) < end && *(p+len) != '&')
-- ++len;
-+ /* found a value */
-+ if (*p == '=') {
-+ *(p++) = 0;
-+ value = p;
-+ }
-+ else if (*p == '&')
-+ *(p++) = 0;
-+ else if (*p == '#')
-+ *p = 0;
-+ len = url_decode(key);
-+ if (len == -1)
-+ goto error;
-+
-+ /* decode value */
-+ if (value) {
-+ while (p < end && *p != '=' && *p != '&' && *p != '#')
-+ ++p;
-+ if (*p == '=')
-+ goto error;
-+ if (*p == '&')
-+ *(p++) = 0;
-+ else if (*p == '#')
-+ *p = 0;
-+ len = url_decode(value);
-+ if (len == -1)
-+ goto error;
-+ }
-
-- if (len == 0)
-+ if (!strcmp(key, "scope")) {
-+ default_scopes = 0; /* at least a scope defined, unset default scopes */
-+ if (!value)
-+ goto error;
-+ else if (*value == 0)
- appctx->ctx.stats.flags &= ~PROMEX_FL_SCOPE_ALL;
-- else if (len == 1 && *p == '*')
-+ else if (*value == '*')
- appctx->ctx.stats.flags |= PROMEX_FL_SCOPE_ALL;
-- else if (len == 6) {
-- if (!memcmp(p, "global", len))
-- appctx->ctx.stats.flags |= PROMEX_FL_SCOPE_GLOBAL;
-- else if (!memcmp(p, "server", len))
-- appctx->ctx.stats.flags |= PROMEX_FL_SCOPE_SERVER;
-- }
-- else if (len == 7 && !memcmp(p, "backend", len))
-+ else if (!strcmp(value, "global"))
-+ appctx->ctx.stats.flags |= PROMEX_FL_SCOPE_GLOBAL;
-+ else if (!strcmp(value, "server"))
-+ appctx->ctx.stats.flags |= PROMEX_FL_SCOPE_SERVER;
-+ else if (!strcmp(value, "backend"))
- appctx->ctx.stats.flags |= PROMEX_FL_SCOPE_BACK;
-- else if (len == 8 && !memcmp(p, "frontend", len))
-+ else if (!strcmp(value, "frontend"))
- appctx->ctx.stats.flags |= PROMEX_FL_SCOPE_FRONT;
- else
- goto error;
--
-- p += len;
- }
-- else if (*p == 'n' && (end-p) >= 8 && !memcmp(p, "no-maint", 8)) {
-+ else if (!strcmp(key, "no-maint"))
- appctx->ctx.stats.flags |= PROMEX_FL_NO_MAINT_SRV;
-- p += 8;
-- }
-- else {
-- /* ignore all other params for now */
-- while (p < end && *p != '&')
-- p++;
-- }
- }
-
- end: