Commit b2f32cd8 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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
parent 2a8398c1
......@@ -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);
......
......@@ -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) &&
......
......@@ -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);
}
......
......@@ -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;
......
......@@ -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;
......
......@@ -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 */
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment