[master] b2f32cd Try to get http->protover into some kind of consistent state so we do not send HTTP/2.0 headers to backends on pass from HTTP/2.0 clients
Poul-Henning Kamp
phk at FreeBSD.org
Wed Mar 1 00:04:05 CET 2017
commit b2f32cd82111a9e6f388af0e459b9c1511bcae07
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Tue Feb 28 23:03:17 2017 +0000
Try to get http->protover into some kind of consistent state so we
do not send HTTP/2.0 headers to backends on pass from HTTP/2.0 clients
diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index c9fda21..fba8763 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -761,9 +761,10 @@ void http_ForceHeader(struct http *to, const char *hdr, const char *val);
void http_PrintfHeader(struct http *to, const char *fmt, ...)
__v_printflike(2, 3);
void http_TimeHeader(struct http *to, const char *fmt, double now);
+void http_Proto(struct http *to);
void http_SetHeader(struct http *to, const char *hdr);
-void http_SetH(const struct http *to, unsigned n, const char *fm);
-void http_ForceField(const struct http *to, unsigned n, const char *t);
+void http_SetH(struct http *to, unsigned n, const char *fm);
+void http_ForceField(struct http *to, unsigned n, const char *t);
void HTTP_Setup(struct http *, struct ws *, struct vsl_log *, enum VSL_tag_e);
void http_Teardown(struct http *ht);
int http_GetHdr(const struct http *hp, const char *hdr, const char **ptr);
diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c
index 1287f08..4aa3dd2 100644
--- a/bin/varnishd/cache/cache_fetch.c
+++ b/bin/varnishd/cache/cache_fetch.c
@@ -185,9 +185,12 @@ vbf_stp_mkbereq(struct worker *wrk, struct busyobj *bo)
http_ForceField(bo->bereq0, HTTP_HDR_PROTO, "HTTP/1.1");
if (cache_param->http_gzip_support)
http_ForceHeader(bo->bereq0, H_Accept_Encoding, "gzip");
- http_CopyHome(bo->bereq0);
- } else
+ } else {
AZ(bo->stale_oc);
+ if (bo->bereq0->protover > 11)
+ http_ForceField(bo->bereq0, HTTP_HDR_PROTO, "HTTP/1.1");
+ }
+ http_CopyHome(bo->bereq0);
if (bo->stale_oc != NULL &&
ObjCheckFlag(bo->wrk, bo->stale_oc, OF_IMSCAND) &&
diff --git a/bin/varnishd/cache/cache_http.c b/bin/varnishd/cache/cache_http.c
index 6642ea9..c200e24 100644
--- a/bin/varnishd/cache/cache_http.c
+++ b/bin/varnishd/cache/cache_http.c
@@ -199,12 +199,37 @@ HTTP_Copy(struct http *to, const struct http * const fm)
memcpy(&to->nhd, &fm->nhd, sizeof *to - offsetof(struct http, nhd));
memcpy(to->hd, fm->hd, fm->nhd * sizeof *to->hd);
memcpy(to->hdf, fm->hdf, fm->nhd * sizeof *to->hdf);
+ to->protover = fm->protover;
}
/*--------------------------------------------------------------------*/
void
-http_SetH(const struct http *to, unsigned n, const char *fm)
+http_Proto(struct http *to)
+{
+ const char *fm;
+
+ fm = to->hd[HTTP_HDR_PROTO].b;
+
+ if ((fm[0] == 'H' || fm[0] == 'h') &&
+ (fm[1] == 'T' || fm[0] == 't') &&
+ (fm[2] == 'T' || fm[0] == 't') &&
+ (fm[3] == 'P' || fm[0] == 'p') &&
+ fm[4] == '/' &&
+ vct_isdigit(fm[5]) &&
+ fm[6] == '.' &&
+ vct_isdigit(fm[7]) &&
+ fm[8] == '\0') {
+ to->protover = 10 * (fm[5] - '0') + (fm[7] - '0');
+ } else {
+ to->protover = 0;
+ }
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+http_SetH(struct http *to, unsigned n, const char *fm)
{
assert(n < to->nhd);
@@ -213,12 +238,14 @@ http_SetH(const struct http *to, unsigned n, const char *fm)
to->hd[n].e = strchr(to->hd[n].b, '\0');
to->hdf[n] = 0;
http_VSLH(to, n);
+ if (n == HTTP_HDR_PROTO)
+ http_Proto(to);
}
/*--------------------------------------------------------------------*/
static void
-http_PutField(const struct http *to, int field, const char *string)
+http_PutField(struct http *to, int field, const char *string)
{
char *p;
@@ -233,6 +260,8 @@ http_PutField(const struct http *to, int field, const char *string)
to->hd[field].e = strchr(p, '\0');
to->hdf[field] = 0;
http_VSLH(to, field);
+ if (field == HTTP_HDR_PROTO)
+ http_Proto(to);
}
/*--------------------------------------------------------------------*/
@@ -759,7 +788,7 @@ http_GetMethod(const struct http *hp)
*/
void
-http_ForceField(const struct http *to, unsigned n, const char *t)
+http_ForceField(struct http *to, unsigned n, const char *t)
{
int i;
@@ -1077,6 +1106,7 @@ http_FilterReq(struct http *to, const struct http *fm, unsigned how)
http_linkh(to, fm, HTTP_HDR_METHOD);
http_linkh(to, fm, HTTP_HDR_URL);
http_linkh(to, fm, HTTP_HDR_PROTO);
+ to->protover = fm->protover;
http_filterfields(to, fm, how);
}
diff --git a/bin/varnishd/cache/cache_vrt_var.c b/bin/varnishd/cache/cache_vrt_var.c
index 000ae75..d0380a8 100644
--- a/bin/varnishd/cache/cache_vrt_var.c
+++ b/bin/varnishd/cache/cache_vrt_var.c
@@ -45,7 +45,7 @@ static char vrt_hostname[255] = "";
*/
static void
-vrt_do_string(VRT_CTX, const struct http *hp, int fld,
+vrt_do_string(VRT_CTX, struct http *hp, int fld,
const char *err, const char *p, va_list ap)
{
const char *b;
diff --git a/bin/varnishd/http1/cache_http1_proto.c b/bin/varnishd/http1/cache_http1_proto.c
index e788ed6..05d23b3 100644
--- a/bin/varnishd/http1/cache_http1_proto.c
+++ b/bin/varnishd/http1/cache_http1_proto.c
@@ -285,6 +285,8 @@ http1_splitline(struct http *hp, struct http_conn *htc, const int *hf,
*p = '\0';
p += i;
+ http_Proto(hp);
+
return (http1_dissect_hdrs(hp, p, htc, maxhdr));
}
@@ -340,19 +342,6 @@ http1_body_status(const struct http *hp, struct http_conn *htc, int request)
/*--------------------------------------------------------------------*/
-static int8_t
-http1_proto_ver(const struct http *hp)
-{
- if (!strcasecmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.0"))
- return (10);
- else if (!strcasecmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.1"))
- return (11);
- else
- return (0);
-}
-
-/*--------------------------------------------------------------------*/
-
uint16_t
HTTP1_DissectRequest(struct http_conn *htc, struct http *hp)
{
@@ -367,8 +356,8 @@ HTTP1_DissectRequest(struct http_conn *htc, struct http *hp)
HTTP1_Req, cache_param->http_req_hdr_len);
if (retval != 0)
return (retval);
- hp->protover = http1_proto_ver(hp);
- if (hp->protover == 0)
+
+ if (hp->protover < 10 || hp->protover > 11)
return (400);
if (http_CountHdr(hp, H_Host) > 1)
@@ -418,29 +407,24 @@ HTTP1_DissectRequest(struct http_conn *htc, struct http *hp)
uint16_t
HTTP1_DissectResponse(struct http_conn *htc, struct http *hp,
- const struct http *req)
+ const struct http *rhttp)
{
uint16_t retval = 0;
const char *p;
- int8_t rv;
-
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
- CHECK_OBJ_NOTNULL(req, HTTP_MAGIC);
+ CHECK_OBJ_NOTNULL(rhttp, HTTP_MAGIC);
if (http1_splitline(hp, htc,
HTTP1_Resp, cache_param->http_resp_hdr_len))
retval = 503;
- if (retval == 0) {
- hp->protover = http1_proto_ver(hp);
- if (hp->protover == 0)
- retval = 503;
- rv = http1_proto_ver(req);
- if (hp->protover > rv)
- hp->protover = rv;
- }
+ if (retval == 0 && hp->protover < 10)
+ retval = 503;
+
+ if (retval == 0 && hp->protover > rhttp->protover)
+ http_SetH(hp, HTTP_HDR_PROTO, rhttp->hd[HTTP_HDR_PROTO].b);
if (retval == 0 && Tlen(hp->hd[HTTP_HDR_STATUS]) != 3)
retval = 503;
diff --git a/bin/varnishd/http2/cache_http2_proto.c b/bin/varnishd/http2/cache_http2_proto.c
index 1a11609..3148751 100644
--- a/bin/varnishd/http2/cache_http2_proto.c
+++ b/bin/varnishd/http2/cache_http2_proto.c
@@ -471,7 +471,6 @@ h2_rx_headers(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
}
VSLb_ts_req(req, "Req", req->t_req);
http_SetH(req->http, HTTP_HDR_PROTO, "HTTP/2.0");
- req->http->protover = 20;
if (h2->rxf_flags & H2FF_HEADERS_END_STREAM)
req->req_body_status = REQ_BODY_NONE;
@@ -821,7 +820,6 @@ h2_new_ou_session(struct worker *wrk, struct h2_sess *h2,
req->task.priv = req;
req->err_code = 0;
http_SetH(req->http, HTTP_HDR_PROTO, "HTTP/2.0");
- req->http->protover = 20;
XXXAZ(Pool_Task(wrk->pool, &req->task, TASK_QUEUE_REQ));
/* Wait for PRISM response */
diff --git a/bin/varnishtest/tests/t02006.vtc b/bin/varnishtest/tests/t02006.vtc
index d8354b9..1fd54e1 100644
--- a/bin/varnishtest/tests/t02006.vtc
+++ b/bin/varnishtest/tests/t02006.vtc
@@ -2,6 +2,7 @@ varnishtest "H2 POST w/ 100 Continue"
server s1 {
rxreq
+ expect req.proto == HTTP/1.1
txresp -hdr "Content-Type: text/plain" -body response
} -start
More information about the varnish-commit
mailing list